]>
git.saurik.com Git - apple/libc.git/blob - arm/sys/OSAtomic-v4.c
2 * Copyright (c) 2004, 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <libkern/OSAtomic.h>
28 #if !defined(_ARM_ARCH_6)
31 * The only atomic operation ARMv4T provides (atomic swap) is not
32 * sufficient for the general 32-bit arithmetic and compare-and-swap
33 * operations OSAtomic is supposed to provide. So we use a global
34 * spin lock around all operations.
36 * Since we have only a single, in-order, CPU, we do not need
37 * memory barriers for data.
40 static OSSpinLock _atomic_lock
= OS_SPINLOCK_INIT
;
42 int32_t OSAtomicAdd32( int32_t theAmount
, volatile int32_t *theValue
)
46 OSSpinLockLock(&_atomic_lock
);
47 result
= (*theValue
+= theAmount
);
48 OSSpinLockUnlock(&_atomic_lock
);
53 int32_t OSAtomicAdd32Barrier( int32_t theAmount
, volatile int32_t *theValue
)
55 return OSAtomicAdd32(theAmount
, theValue
);
58 int64_t OSAtomicAdd64( int64_t theAmount
, volatile int64_t *theValue
)
62 OSSpinLockLock(&_atomic_lock
);
63 result
= (*theValue
+= theAmount
);
64 OSSpinLockUnlock(&_atomic_lock
);
69 int64_t OSAtomicAdd64Barrier( int64_t theAmount
, volatile int64_t *theValue
)
71 return OSAtomicAdd64(theAmount
, theValue
);
74 int32_t OSAtomicOr32( uint32_t theMask
, volatile uint32_t *theValue
)
78 OSSpinLockLock(&_atomic_lock
);
79 result
= (*theValue
|= theMask
);
80 OSSpinLockUnlock(&_atomic_lock
);
85 int32_t OSAtomicOr32Barrier( uint32_t theMask
, volatile uint32_t *theValue
)
87 return OSAtomicOr32(theMask
, theValue
);
90 int32_t OSAtomicOr32Orig( uint32_t theMask
, volatile uint32_t *theValue
)
94 OSSpinLockLock(&_atomic_lock
);
97 OSSpinLockUnlock(&_atomic_lock
);
102 int32_t OSAtomicOr32OrigBarrier( uint32_t theMask
, volatile uint32_t *theValue
)
104 return OSAtomicOr32Orig(theMask
, theValue
);
107 int32_t OSAtomicAnd32( uint32_t theMask
, volatile uint32_t *theValue
)
111 OSSpinLockLock(&_atomic_lock
);
112 result
= (*theValue
&= theMask
);
113 OSSpinLockUnlock(&_atomic_lock
);
118 int32_t OSAtomicAnd32Barrier( uint32_t theMask
, volatile uint32_t *theValue
)
120 return OSAtomicAnd32(theMask
, theValue
);
123 int32_t OSAtomicAnd32Orig( uint32_t theMask
, volatile uint32_t *theValue
)
127 OSSpinLockLock(&_atomic_lock
);
129 *theValue
&= theMask
;
130 OSSpinLockUnlock(&_atomic_lock
);
135 int32_t OSAtomicAnd32OrigBarrier( uint32_t theMask
, volatile uint32_t *theValue
)
137 return OSAtomicAnd32Orig(theMask
, theValue
);
140 int32_t OSAtomicXor32( uint32_t theMask
, volatile uint32_t *theValue
)
144 OSSpinLockLock(&_atomic_lock
);
145 result
= (*theValue
^= theMask
);
146 OSSpinLockUnlock(&_atomic_lock
);
151 int32_t OSAtomicXor32Barrier( uint32_t theMask
, volatile uint32_t *theValue
)
153 return OSAtomicXor32(theMask
, theValue
);
156 int32_t OSAtomicXor32Orig( uint32_t theMask
, volatile uint32_t *theValue
)
160 OSSpinLockLock(&_atomic_lock
);
162 *theValue
^= theMask
;
163 OSSpinLockUnlock(&_atomic_lock
);
168 int32_t OSAtomicXor32OrigBarrier( uint32_t theMask
, volatile uint32_t *theValue
)
170 return OSAtomicXor32Orig(theMask
, theValue
);
173 bool OSAtomicCompareAndSwap32( int32_t oldValue
, int32_t newValue
, volatile int32_t *theValue
)
177 OSSpinLockLock(&_atomic_lock
);
178 result
= (*theValue
== oldValue
);
179 if (result
) *theValue
= newValue
;
180 OSSpinLockUnlock(&_atomic_lock
);
185 bool OSAtomicCompareAndSwap32Barrier( int32_t oldValue
, int32_t newValue
, volatile int32_t *theValue
)
187 return OSAtomicCompareAndSwap32(oldValue
, newValue
, theValue
);
191 OSAtomicCompareAndSwapInt(int oldValue
, int newValue
, volatile int *theValue
)
193 return OSAtomicCompareAndSwap32(oldValue
, newValue
, theValue
);
197 OSAtomicCompareAndSwapIntBarrier(int oldValue
, int newValue
, volatile int *theValue
)
199 return OSAtomicCompareAndSwap32(oldValue
, newValue
, theValue
);
203 OSAtomicCompareAndSwapLong(long oldValue
, long newValue
, volatile long *theValue
)
205 return OSAtomicCompareAndSwap32(oldValue
, newValue
, (volatile int32_t *)theValue
);
209 OSAtomicCompareAndSwapLongBarrier(long oldValue
, long newValue
, volatile long *theValue
)
211 return OSAtomicCompareAndSwap32(oldValue
, newValue
, (volatile int32_t *)theValue
);
214 bool OSAtomicCompareAndSwap64( int64_t oldValue
, int64_t newValue
, volatile int64_t *theValue
)
218 OSSpinLockLock(&_atomic_lock
);
219 result
= (*theValue
== oldValue
);
220 if (result
) *theValue
= newValue
;
221 OSSpinLockUnlock(&_atomic_lock
);
226 bool OSAtomicCompareAndSwap64Barrier( int64_t oldValue
, int64_t newValue
, volatile int64_t *theValue
)
228 return OSAtomicCompareAndSwap64(oldValue
, newValue
, theValue
);
231 bool OSAtomicTestAndSet( uint32_t n
, volatile void *theAddress
)
233 char *byteAddress
= ((char*)theAddress
+ (n
>>3));
234 uint32_t byteBit
= (0x80>>(n
&7));
237 OSSpinLockLock(&_atomic_lock
);
238 result
= *byteAddress
& byteBit
;
239 *byteAddress
|= byteBit
;
240 OSSpinLockUnlock(&_atomic_lock
);
245 bool OSAtomicTestAndSetBarrier( uint32_t n
, volatile void *theAddress
)
247 return OSAtomicTestAndSet(n
, theAddress
);
250 bool OSAtomicTestAndClear( uint32_t n
, volatile void *theAddress
)
252 char *byteAddress
= ((char*)theAddress
+ (n
>>3));
253 uint32_t byteBit
= (0x80>>(n
&7));
256 OSSpinLockLock(&_atomic_lock
);
257 result
= *byteAddress
& byteBit
;
258 *byteAddress
&= (~byteBit
);
259 OSSpinLockUnlock(&_atomic_lock
);
264 bool OSAtomicTestAndClearBarrier( uint32_t n
, volatile void *theAddress
)
266 return OSAtomicTestAndClear(n
, theAddress
);
269 void OSMemoryBarrier( void )
275 bool OSAtomicCompareAndSwapPtrBarrier( void *__oldValue
, void *__newValue
, void * volatile *__theValue
)
277 return OSAtomicCompareAndSwapPtr(__oldValue
, __newValue
, __theValue
);
280 bool OSAtomicCompareAndSwapPtr( void *__oldValue
, void *__newValue
, void * volatile *__theValue
)
284 OSSpinLockLock(&_atomic_lock
);
285 result
= (*__theValue
== __oldValue
);
286 if (result
) *__theValue
= __newValue
;
287 OSSpinLockUnlock(&_atomic_lock
);
292 #endif /* !defined(_ARM_ARCH_6) */