]> git.saurik.com Git - apple/libc.git/blob - arm/sys/OSAtomic-v4.c
f3a1b37548d94d86cf25804978c6b90d08ca8155
[apple/libc.git] / arm / sys / OSAtomic-v4.c
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <libkern/OSAtomic.h>
25 #include <arm/arch.h>
26
27
28 #if !defined(_ARM_ARCH_6)
29
30 /*
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.
35 *
36 * Since we have only a single, in-order, CPU, we do not need
37 * memory barriers for data.
38 */
39
40 static OSSpinLock _atomic_lock = OS_SPINLOCK_INIT;
41
42 int32_t OSAtomicAdd32( int32_t theAmount, int32_t *theValue )
43 {
44 int32_t result;
45
46 OSSpinLockLock(&_atomic_lock);
47 result = (*theValue += theAmount);
48 OSSpinLockUnlock(&_atomic_lock);
49
50 return result;
51 }
52
53 int32_t OSAtomicAdd32Barrier( int32_t theAmount, int32_t *theValue )
54 {
55 return OSAtomicAdd32(theAmount, theValue);
56 }
57
58 int32_t OSAtomicOr32( uint32_t theMask, uint32_t *theValue )
59 {
60 int32_t result;
61
62 OSSpinLockLock(&_atomic_lock);
63 result = (*theValue |= theMask);
64 OSSpinLockUnlock(&_atomic_lock);
65
66 return result;
67 }
68
69 int32_t OSAtomicOr32Barrier( uint32_t theMask, uint32_t *theValue )
70 {
71 return OSAtomicOr32(theMask, theValue);
72 }
73
74 int32_t OSAtomicAnd32( uint32_t theMask, uint32_t *theValue )
75 {
76 int32_t result;
77
78 OSSpinLockLock(&_atomic_lock);
79 result = (*theValue &= theMask);
80 OSSpinLockUnlock(&_atomic_lock);
81
82 return result;
83 }
84
85 int32_t OSAtomicAnd32Barrier( uint32_t theMask, uint32_t *theValue )
86 {
87 return OSAtomicAnd32(theMask, theValue);
88 }
89
90 int32_t OSAtomicXor32( uint32_t theMask, uint32_t *theValue )
91 {
92 int32_t result;
93
94 OSSpinLockLock(&_atomic_lock);
95 result = (*theValue ^= theMask);
96 OSSpinLockUnlock(&_atomic_lock);
97
98 return result;
99 }
100
101 int32_t OSAtomicXor32Barrier( uint32_t theMask, uint32_t *theValue )
102 {
103 return OSAtomicXor32(theMask, theValue);
104 }
105
106 bool OSAtomicCompareAndSwap32( int32_t oldValue, int32_t newValue, int32_t *theValue )
107 {
108 bool result;
109
110 OSSpinLockLock(&_atomic_lock);
111 result = (*theValue == oldValue);
112 if (result) *theValue = newValue;
113 OSSpinLockUnlock(&_atomic_lock);
114
115 return result;
116 }
117
118 bool OSAtomicCompareAndSwap32Barrier( int32_t oldValue, int32_t newValue, int32_t *theValue )
119 {
120 return OSAtomicCompareAndSwap32(oldValue, newValue, theValue);
121 }
122
123 bool OSAtomicTestAndSet( uint32_t n, void *theAddress )
124 {
125 char *byteAddress = ((char*)theAddress + (n>>3));
126 uint32_t byteBit = (0x80>>(n&7));
127 bool result;
128
129 OSSpinLockLock(&_atomic_lock);
130 result = *byteAddress & byteBit;
131 *byteAddress |= byteBit;
132 OSSpinLockUnlock(&_atomic_lock);
133
134 return result;
135 }
136
137 bool OSAtomicTestAndSetBarrier( uint32_t n, void *theAddress )
138 {
139 return OSAtomicTestAndSet(n, theAddress);
140 }
141
142 bool OSAtomicTestAndClear( uint32_t n, void *theAddress )
143 {
144 char *byteAddress = ((char*)theAddress + (n>>3));
145 uint32_t byteBit = (0x80>>(n&7));
146 bool result;
147
148 OSSpinLockLock(&_atomic_lock);
149 result = *byteAddress & byteBit;
150 *byteAddress &= (~byteBit);
151 OSSpinLockUnlock(&_atomic_lock);
152
153 return result;
154 }
155
156 bool OSAtomicTestAndClearBarrier( uint32_t n, void *theAddress )
157 {
158 return OSAtomicTestAndClear(n, theAddress);
159 }
160
161 void OSMemoryBarrier( void )
162 {
163 return;
164 }
165
166 #endif /* !defined(_ARM_ARCH_6) */