2 * Copyright (c) 2013 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
21 #include "os/internal.h"
22 #include "libkern/OSAtomic.h"
25 #if TARGET_OS_EMBEDDED
28 int32_t OSAtomicAdd32Barrier(int32_t v
, volatile int32_t *p
);
30 int32_t OSAtomicIncrement32Barrier(volatile int32_t *p
);
32 int32_t OSAtomicDecrement32Barrier(volatile int32_t *p
);
34 int64_t OSAtomicAdd64Barrier(int64_t v
, volatile int64_t *p
);
36 int64_t OSAtomicIncrement64Barrier(volatile int64_t *p
);
38 int64_t OSAtomicDecrement64Barrier(volatile int64_t *p
);
40 int32_t OSAtomicAnd32Barrier(uint32_t v
, volatile uint32_t *p
);
42 int32_t OSAtomicAnd32OrigBarrier(uint32_t v
, volatile uint32_t *p
);
44 int32_t OSAtomicOr32Barrier(uint32_t v
, volatile uint32_t *p
);
46 int32_t OSAtomicOr32OrigBarrier(uint32_t v
, volatile uint32_t *p
);
48 int32_t OSAtomicXor32Barrier(uint32_t v
, volatile uint32_t *p
);
50 int32_t OSAtomicXor32OrigBarrier(uint32_t v
, volatile uint32_t *p
);
52 bool OSAtomicCompareAndSwap32Barrier(int32_t o
, int32_t n
, volatile int32_t *p
);
54 bool OSAtomicCompareAndSwap64Barrier(int64_t o
, int64_t n
, volatile int64_t *p
);
56 bool OSAtomicTestAndSetBarrier(uint32_t n
, volatile void * p
);
58 bool OSAtomicTestAndClearBarrier(uint32_t n
, volatile void * p
);
60 void OSAtomicEnqueue(OSQueueHead
*list
, void *new, size_t offset
);
62 void* OSAtomicDequeue(OSQueueHead
*list
, size_t offset
);
64 void OSMemoryBarrier(void);
67 #define OS_ATOMIC_ALIAS_NO_BARRIER(n) OS_ATOMIC_EXPORT_ALIAS(n, n##Barrier)
69 #define OS_ATOMIC_ALIAS_NO_BARRIER(n)
73 OSAtomicAdd32Barrier(int32_t v
, volatile int32_t *p
)
75 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicAdd32
);
76 int32_t r
= os_atomic_add(p
, v
, acq_rel
);
81 OSAtomicIncrement32Barrier(volatile int32_t *p
)
83 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicIncrement32
);
84 int32_t r
= os_atomic_add(p
, 1, acq_rel
);
89 OSAtomicDecrement32Barrier(volatile int32_t *p
)
91 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicDecrement32
);
92 int32_t r
= os_atomic_add(p
, -1, acq_rel
);
97 OSAtomicAdd64Barrier(int64_t v
, volatile int64_t *p
)
99 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicAdd64
);
100 int64_t r
= os_atomic_add(p
, v
, acq_rel
);
105 OSAtomicIncrement64Barrier(volatile int64_t *p
)
107 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicIncrement64
);
108 int64_t r
= os_atomic_add(p
, 1, acq_rel
);
113 OSAtomicDecrement64Barrier(volatile int64_t *p
)
115 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicDecrement64
);
116 int64_t r
= os_atomic_add(p
, -1, acq_rel
);
121 OSAtomicAnd32Barrier(uint32_t v
, volatile uint32_t *p
)
123 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicAnd32
);
124 uint32_t r
= os_atomic_and(p
, v
, acq_rel
);
129 OSAtomicAnd32OrigBarrier(uint32_t v
, volatile uint32_t *p
)
131 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicAnd32Orig
);
132 uint32_t r
= os_atomic_and_orig(p
, v
, acq_rel
);
137 OSAtomicOr32Barrier(uint32_t v
, volatile uint32_t *p
)
139 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicOr32
);
140 uint32_t r
= os_atomic_or(p
, v
, acq_rel
);
145 OSAtomicOr32OrigBarrier(uint32_t v
, volatile uint32_t *p
)
147 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicOr32Orig
);
148 uint32_t r
= os_atomic_or_orig(p
, v
, acq_rel
);
153 OSAtomicXor32Barrier(uint32_t v
, volatile uint32_t *p
)
155 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicXor32
);
156 uint32_t r
= os_atomic_xor(p
, v
, acq_rel
);
161 OSAtomicXor32OrigBarrier(uint32_t v
, volatile uint32_t *p
)
163 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicXor32Orig
);
164 uint32_t r
= os_atomic_xor_orig(p
, v
, acq_rel
);
169 OSAtomicCompareAndSwap32Barrier(int32_t o
, int32_t n
, volatile int32_t *p
)
171 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicCompareAndSwap32
);
172 OS_ATOMIC_ALIAS(OSAtomicCompareAndSwapIntBarrier
,
173 OSAtomicCompareAndSwap32Barrier
);
174 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicCompareAndSwapInt
);
176 OS_ATOMIC_ALIAS(OSAtomicCompareAndSwapLongBarrier
,
177 OSAtomicCompareAndSwap32Barrier
);
178 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicCompareAndSwapLong
);
179 OS_ATOMIC_ALIAS(OSAtomicCompareAndSwapPtrBarrier
,
180 OSAtomicCompareAndSwap32Barrier
);
181 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicCompareAndSwapPtr
);
183 return os_atomic_cmpxchg(p
, o
, n
, acq_rel
);
187 OSAtomicCompareAndSwap64Barrier(int64_t o
, int64_t n
, volatile int64_t *p
)
189 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicCompareAndSwap64
);
191 OS_ATOMIC_ALIAS(OSAtomicCompareAndSwapLongBarrier
,
192 OSAtomicCompareAndSwap64Barrier
);
193 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicCompareAndSwapLong
);
194 OS_ATOMIC_ALIAS(OSAtomicCompareAndSwapPtrBarrier
,
195 OSAtomicCompareAndSwap64Barrier
);
196 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicCompareAndSwapPtr
);
198 return os_atomic_cmpxchg(p
, o
, n
, acq_rel
);
201 static inline uint32_t*
202 _OSAtomicTestPtrVal(uint32_t bit
, volatile void *addr
, uint32_t *vp
)
204 uintptr_t a
= (uintptr_t)addr
;
206 // 32-bit align addr and adjust bit to compensate <rdar://12927920>
210 *vp
= (0x80u
>> (bit
& 7)) << (bit
& ~7u & 31);
211 return (uint32_t*)((char*)a
+ 4 * (bit
/ 32));
215 OSAtomicTestAndSetBarrier(uint32_t bit
, volatile void *addr
)
217 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicTestAndSet
);
219 volatile uint32_t *p
= _OSAtomicTestPtrVal(bit
, addr
, &v
);
220 uint32_t r
= os_atomic_or_orig(p
, v
, acq_rel
);
225 OSAtomicTestAndClearBarrier(uint32_t bit
, volatile void *addr
)
227 OS_ATOMIC_ALIAS_NO_BARRIER(OSAtomicTestAndClear
);
229 volatile uint32_t *p
= _OSAtomicTestPtrVal(bit
, addr
, &v
);
230 uint32_t r
= os_atomic_and_orig(p
, ~v
, acq_rel
);
234 #if !OS_ATOMIC_NO_BARRIER_ONLY
236 typedef volatile struct {
237 void * volatile item
;
242 OSAtomicEnqueue(OSQueueHead
*list
, void *new, size_t offset
)
244 void * volatile *headptr
= &(((_OSQueueHead
*)list
)->item
);
245 void * volatile *nextptr
= (void*)((char*)new + offset
);
246 void *head
= *headptr
;
249 } while (!os_atomic_cmpxchgvw(headptr
, head
, new, &head
, release
));
253 OSAtomicDequeue(OSQueueHead
*list
, size_t offset
)
255 void * volatile *headptr
= &(((_OSQueueHead
*)list
)->item
);
256 void * volatile *nextptr
;
258 (void)os_atomic_rmw_loop(headptr
, head
, next
, acquire
, {
260 os_atomic_rmw_loop_give_up(break);
262 nextptr
= (void*)((char*)head
+ offset
);
269 OSMemoryBarrier(void)
271 os_atomic_thread_fence(seq_cst
);
274 #endif // !OS_ATOMIC_NO_BARRIER_ONLY
275 #endif // TARGET_OS_EMBEDDED
277 struct _os_empty_files_are_not_c_files
;