]>
Commit | Line | Data |
---|---|---|
59e0d9fe | 1 | /* |
224c7076 | 2 | * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved. |
59e0d9fe A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
59e0d9fe A |
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 | #ifndef _OSATOMIC_H_ | |
25 | #define _OSATOMIC_H_ | |
26 | ||
27 | #include <stddef.h> | |
28 | #include <sys/cdefs.h> | |
29 | #include <stdint.h> | |
30 | #include <stdbool.h> | |
31 | ||
1f2f436a A |
32 | #include <Availability.h> |
33 | ||
34 | /*! @header | |
35 | * These are the preferred versions of the atomic and synchronization operations. | |
59e0d9fe A |
36 | * Their implementation is customized at boot time for the platform, including |
37 | * late-breaking errata fixes as necessary. They are thread safe. | |
38 | * | |
1f2f436a A |
39 | * WARNING: all addresses passed to these functions must be "naturally aligned", |
40 | * i.e. * <code>int32_t</code> pointers must be 32-bit aligned (low 2 bits of | |
41 | * address are zeroes), and <code>int64_t</code> pointers must be 64-bit aligned | |
42 | * (low 3 bits of address are zeroes.) | |
43 | * | |
44 | * Note that some versions of the atomic functions incorporate memory barriers | |
45 | * and some do not. Barriers strictly order memory access on weakly-ordered | |
46 | * architectures such as PPC. All loads and stores that appear (in sequential | |
47 | * program order) before the barrier are guaranteed to complete before any | |
48 | * load or store that appears after the barrier. | |
3d9156a7 | 49 | * |
1f2f436a A |
50 | * On a uniprocessor system, the barrier operation is typically a no-op. On a |
51 | * multiprocessor system, the barrier can be quite expensive on some platforms, | |
52 | * such as PPC. | |
3d9156a7 | 53 | * |
1f2f436a A |
54 | * Most code should use the barrier functions to ensure that memory shared between |
55 | * threads is properly synchronized. For example, if you want to initialize | |
3d9156a7 | 56 | * a shared data structure and then atomically increment a variable to indicate |
1f2f436a A |
57 | * that the initialization is complete, you must use {@link OSAtomicIncrement32Barrier} |
58 | * to ensure that the stores to your data structure complete before the atomic | |
59 | * increment. | |
60 | * | |
61 | * Likewise, the consumer of that data structure must use {@link OSAtomicDecrement32Barrier}, | |
3d9156a7 A |
62 | * in order to ensure that their loads of the structure are not executed before |
63 | * the atomic decrement. On the other hand, if you are simply incrementing a global | |
1f2f436a | 64 | * counter, then it is safe and potentially faster to use {@link OSAtomicIncrement32}. |
3d9156a7 A |
65 | * |
66 | * If you are unsure which version to use, prefer the barrier variants as they are | |
67 | * safer. | |
68 | * | |
69 | * The spinlock and queue operations always incorporate a barrier. | |
1f2f436a A |
70 | * |
71 | * For the kernel-space version of this header, see | |
72 | * {@link //apple_ref/doc/header/OSAtomic.h OSAtomic.h (Kernel Framework)} | |
73 | * | |
74 | * @apiuid //apple_ref/doc/header/user_space_OSAtomic.h | |
59e0d9fe A |
75 | */ |
76 | __BEGIN_DECLS | |
77 | ||
3d9156a7 | 78 | |
1f2f436a A |
79 | /*! @group Arithmetic functions |
80 | All functions in this group return the new value. | |
81 | */ | |
82 | ||
83 | /*! @abstract Atomically adds two 32-bit values. | |
84 | @discussion | |
85 | This function adds the value given by <code>__theAmount</code> to the | |
86 | value in the memory location referenced by <code>__theValue</code>, | |
87 | storing the result back to that memory location atomically. | |
88 | @result Returns the new value. | |
59e0d9fe | 89 | */ |
224c7076 | 90 | int32_t OSAtomicAdd32( int32_t __theAmount, volatile int32_t *__theValue ); |
1f2f436a A |
91 | |
92 | ||
93 | /*! @abstract Atomically adds two 32-bit values. | |
94 | @discussion | |
95 | This function adds the value given by <code>__theAmount</code> to the | |
96 | value in the memory location referenced by <code>__theValue</code>, | |
97 | storing the result back to that memory location atomically. | |
98 | ||
99 | This function is equivalent to {@link OSAtomicAdd32} | |
100 | except that it also introduces a barrier. | |
101 | @result Returns the new value. | |
102 | */ | |
224c7076 | 103 | int32_t OSAtomicAdd32Barrier( int32_t __theAmount, volatile int32_t *__theValue ); |
3d9156a7 | 104 | |
1f2f436a A |
105 | |
106 | /*! @abstract Atomically increments a 32-bit value. | |
107 | */ | |
34e8f829 | 108 | __inline static |
224c7076 A |
109 | int32_t OSAtomicIncrement32( volatile int32_t *__theValue ) |
110 | { return OSAtomicAdd32( 1, __theValue); } | |
1f2f436a A |
111 | |
112 | ||
113 | /*! @abstract Atomically increments a 32-bit value with a barrier. | |
114 | @discussion | |
115 | This function is equivalent to {@link OSAtomicIncrement32} | |
116 | except that it also introduces a barrier. | |
117 | @result Returns the new value. | |
118 | */ | |
34e8f829 | 119 | __inline static |
224c7076 A |
120 | int32_t OSAtomicIncrement32Barrier( volatile int32_t *__theValue ) |
121 | { return OSAtomicAdd32Barrier( 1, __theValue); } | |
3d9156a7 | 122 | |
1f2f436a | 123 | /*! @abstract Atomically decrements a 32-bit value. */ |
34e8f829 | 124 | __inline static |
224c7076 A |
125 | int32_t OSAtomicDecrement32( volatile int32_t *__theValue ) |
126 | { return OSAtomicAdd32( -1, __theValue); } | |
1f2f436a A |
127 | |
128 | /*! @abstract Atomically increments a 32-bit value with a barrier. | |
129 | @discussion | |
130 | This function is equivalent to {@link OSAtomicDecrement32} | |
131 | except that it also introduces a barrier. | |
132 | @result Returns the new value. | |
133 | */ | |
34e8f829 | 134 | __inline static |
224c7076 A |
135 | int32_t OSAtomicDecrement32Barrier( volatile int32_t *__theValue ) |
136 | { return OSAtomicAdd32Barrier( -1, __theValue); } | |
3d9156a7 | 137 | |
1f2f436a | 138 | |
34e8f829 | 139 | #if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) |
3d9156a7 | 140 | |
1f2f436a A |
141 | /*! @abstract Atomically adds two 64-bit values. |
142 | @discussion | |
143 | This function adds the value given by <code>__theAmount</code> to the | |
144 | value in the memory location referenced by <code>__theValue</code>, | |
145 | storing the result back to that memory location atomically. | |
146 | */ | |
224c7076 | 147 | int64_t OSAtomicAdd64( int64_t __theAmount, volatile int64_t *__theValue ); |
3d9156a7 | 148 | |
1f2f436a A |
149 | |
150 | /*! @abstract Atomically adds two 64-bit values with a barrier. | |
151 | @discussion | |
152 | This function adds the value given by <code>__theAmount</code> to the | |
153 | value in the memory location referenced by <code>__theValue</code>, | |
154 | storing the result back to that memory location atomically. | |
155 | ||
156 | This function is equivalent to {@link OSAtomicAdd64} | |
157 | except that it also introduces a barrier. | |
158 | @result Returns the new value. | |
159 | */ | |
160 | int64_t OSAtomicAdd64Barrier( int64_t __theAmount, volatile int64_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_3_2); | |
161 | ||
162 | ||
163 | /*! @abstract Atomically increments a 64-bit value. */ | |
34e8f829 | 164 | __inline static |
224c7076 A |
165 | int64_t OSAtomicIncrement64( volatile int64_t *__theValue ) |
166 | { return OSAtomicAdd64( 1, __theValue); } | |
1f2f436a A |
167 | |
168 | /*! @abstract Atomically increments a 64-bit value with a barrier. | |
169 | @discussion | |
170 | This function is equivalent to {@link OSAtomicIncrement64} | |
171 | except that it also introduces a barrier. | |
172 | @result Returns the new value. | |
173 | */ | |
34e8f829 | 174 | __inline static |
224c7076 A |
175 | int64_t OSAtomicIncrement64Barrier( volatile int64_t *__theValue ) |
176 | { return OSAtomicAdd64Barrier( 1, __theValue); } | |
3d9156a7 | 177 | |
1f2f436a A |
178 | |
179 | /*! @abstract Atomically decrements a 64-bit value. | |
180 | @discussion | |
181 | This function is equivalent to {@link OSAtomicIncrement64} | |
182 | except that it also introduces a barrier. | |
183 | @result Returns the new value. | |
184 | */ | |
34e8f829 | 185 | __inline static |
224c7076 A |
186 | int64_t OSAtomicDecrement64( volatile int64_t *__theValue ) |
187 | { return OSAtomicAdd64( -1, __theValue); } | |
1f2f436a A |
188 | |
189 | ||
190 | /*! @abstract Atomically decrements a 64-bit value with a barrier. | |
191 | @discussion | |
192 | This function is equivalent to {@link OSAtomicDecrement64} | |
193 | except that it also introduces a barrier. | |
194 | @result Returns the new value. | |
195 | */ | |
34e8f829 | 196 | __inline static |
224c7076 A |
197 | int64_t OSAtomicDecrement64Barrier( volatile int64_t *__theValue ) |
198 | { return OSAtomicAdd64Barrier( -1, __theValue); } | |
3d9156a7 | 199 | |
1f2f436a | 200 | |
34e8f829 | 201 | #endif /* defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) */ |
59e0d9fe | 202 | |
3d9156a7 | 203 | |
1f2f436a A |
204 | /*! @group Boolean functions (AND, OR, XOR) |
205 | * | |
206 | * @discussion Functions in this group come in four variants for each operation: | |
207 | * with and without barriers, and functions that return the original value or | |
208 | * the result value of the operation. | |
209 | * | |
210 | * The "Orig" versions return the original value, (before the operation); the non-Orig | |
224c7076 | 211 | * versions return the value after the operation. All are layered on top of |
1f2f436a A |
212 | * {@link OSAtomicCompareAndSwap32} and similar. |
213 | */ | |
214 | ||
215 | /*! @abstract Atomic bitwise OR of two 32-bit values. | |
216 | @discussion | |
217 | This function performs the bitwise OR of the value given by <code>__theMask</code> | |
218 | with the value in the memory location referenced by <code>__theValue</code>, | |
219 | storing the result back to that memory location atomically. | |
220 | @result Returns the new value. | |
59e0d9fe | 221 | */ |
224c7076 | 222 | int32_t OSAtomicOr32( uint32_t __theMask, volatile uint32_t *__theValue ); |
1f2f436a A |
223 | |
224 | ||
225 | /*! @abstract Atomic bitwise OR of two 32-bit values with barrier. | |
226 | @discussion | |
227 | This function performs the bitwise OR of the value given by <code>__theMask</code> | |
228 | with the value in the memory location referenced by <code>__theValue</code>, | |
229 | storing the result back to that memory location atomically. | |
230 | ||
231 | This function is equivalent to {@link OSAtomicOr32} | |
232 | except that it also introduces a barrier. | |
233 | @result Returns the new value. | |
234 | */ | |
224c7076 | 235 | int32_t OSAtomicOr32Barrier( uint32_t __theMask, volatile uint32_t *__theValue ); |
224c7076 | 236 | |
1f2f436a A |
237 | |
238 | /*! @abstract Atomic bitwise OR of two 32-bit values returning original. | |
239 | @discussion | |
240 | This function performs the bitwise OR of the value given by <code>__theMask</code> | |
241 | with the value in the memory location referenced by <code>__theValue</code>, | |
242 | storing the result back to that memory location atomically. | |
243 | @result Returns the original value referenced by <code>__theValue</code>. | |
244 | */ | |
245 | int32_t OSAtomicOr32Orig( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); | |
246 | ||
247 | ||
248 | /*! @abstract Atomic bitwise OR of two 32-bit values returning original with barrier. | |
249 | @discussion | |
250 | This function performs the bitwise OR of the value given by <code>__theMask</code> | |
251 | with the value in the memory location referenced by <code>__theValue</code>, | |
252 | storing the result back to that memory location atomically. | |
253 | ||
254 | This function is equivalent to {@link OSAtomicOr32Orig} | |
255 | except that it also introduces a barrier. | |
256 | @result Returns the original value referenced by <code>__theValue</code>. | |
257 | */ | |
258 | int32_t OSAtomicOr32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); | |
259 | ||
260 | ||
261 | ||
262 | ||
263 | /*! @abstract Atomic bitwise AND of two 32-bit values. | |
264 | @discussion | |
265 | This function performs the bitwise AND of the value given by <code>__theMask</code> | |
266 | with the value in the memory location referenced by <code>__theValue</code>, | |
267 | storing the result back to that memory location atomically. | |
268 | @result Returns the new value. | |
269 | */ | |
224c7076 | 270 | int32_t OSAtomicAnd32( uint32_t __theMask, volatile uint32_t *__theValue ); |
1f2f436a A |
271 | |
272 | ||
273 | /*! @abstract Atomic bitwise AND of two 32-bit values with barrier. | |
274 | @discussion | |
275 | This function performs the bitwise AND of the value given by <code>__theMask</code> | |
276 | with the value in the memory location referenced by <code>__theValue</code>, | |
277 | storing the result back to that memory location atomically. | |
278 | ||
279 | This function is equivalent to {@link OSAtomicAnd32} | |
280 | except that it also introduces a barrier. | |
281 | @result Returns the new value. | |
282 | */ | |
224c7076 | 283 | int32_t OSAtomicAnd32Barrier( uint32_t __theMask, volatile uint32_t *__theValue ); |
224c7076 | 284 | |
1f2f436a A |
285 | |
286 | /*! @abstract Atomic bitwise AND of two 32-bit values returning original. | |
287 | @discussion | |
288 | This function performs the bitwise AND of the value given by <code>__theMask</code> | |
289 | with the value in the memory location referenced by <code>__theValue</code>, | |
290 | storing the result back to that memory location atomically. | |
291 | @result Returns the original value referenced by <code>__theValue</code>. | |
292 | */ | |
293 | int32_t OSAtomicAnd32Orig( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); | |
294 | ||
295 | ||
296 | /*! @abstract Atomic bitwise AND of two 32-bit values returning original with barrier. | |
297 | @discussion | |
298 | This function performs the bitwise AND of the value given by <code>__theMask</code> | |
299 | with the value in the memory location referenced by <code>__theValue</code>, | |
300 | storing the result back to that memory location atomically. | |
301 | ||
302 | This function is equivalent to {@link OSAtomicAnd32Orig} | |
303 | except that it also introduces a barrier. | |
304 | @result Returns the original value referenced by <code>__theValue</code>. | |
305 | */ | |
306 | int32_t OSAtomicAnd32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); | |
307 | ||
308 | ||
309 | ||
310 | ||
311 | /*! @abstract Atomic bitwise XOR of two 32-bit values. | |
312 | @discussion | |
313 | This function performs the bitwise XOR of the value given by <code>__theMask</code> | |
314 | with the value in the memory location referenced by <code>__theValue</code>, | |
315 | storing the result back to that memory location atomically. | |
316 | @result Returns the new value. | |
317 | */ | |
224c7076 | 318 | int32_t OSAtomicXor32( uint32_t __theMask, volatile uint32_t *__theValue ); |
1f2f436a A |
319 | |
320 | ||
321 | /*! @abstract Atomic bitwise XOR of two 32-bit values with barrier. | |
322 | @discussion | |
323 | This function performs the bitwise XOR of the value given by <code>__theMask</code> | |
324 | with the value in the memory location referenced by <code>__theValue</code>, | |
325 | storing the result back to that memory location atomically. | |
326 | ||
327 | This function is equivalent to {@link OSAtomicXor32} | |
328 | except that it also introduces a barrier. | |
329 | @result Returns the new value. | |
330 | */ | |
224c7076 | 331 | int32_t OSAtomicXor32Barrier( uint32_t __theMask, volatile uint32_t *__theValue ); |
1f2f436a A |
332 | |
333 | ||
334 | /*! @abstract Atomic bitwise XOR of two 32-bit values returning original. | |
335 | @discussion | |
336 | This function performs the bitwise XOR of the value given by <code>__theMask</code> | |
337 | with the value in the memory location referenced by <code>__theValue</code>, | |
338 | storing the result back to that memory location atomically. | |
339 | @result Returns the original value referenced by <code>__theValue</code>. | |
340 | */ | |
341 | int32_t OSAtomicXor32Orig( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); | |
342 | ||
343 | ||
344 | /*! @abstract Atomic bitwise XOR of two 32-bit values returning original with barrier. | |
345 | @discussion | |
346 | This function performs the bitwise XOR of the value given by <code>__theMask</code> | |
347 | with the value in the memory location referenced by <code>__theValue</code>, | |
348 | storing the result back to that memory location atomically. | |
349 | ||
350 | This function is equivalent to {@link OSAtomicXor32Orig} | |
351 | except that it also introduces a barrier. | |
352 | @result Returns the original value referenced by <code>__theValue</code>. | |
353 | */ | |
354 | int32_t OSAtomicXor32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); | |
224c7076 A |
355 | |
356 | ||
1f2f436a A |
357 | /*! @group Compare and swap |
358 | * Functions in this group return true if the swap occured. There are several versions, | |
359 | * depending on data type and on whether or not a barrier is used. | |
360 | */ | |
361 | ||
362 | ||
363 | /*! @abstract Compare and swap for 32-bit values. | |
364 | @discussion | |
365 | This function compares the value in <code>__oldValue</code> to the value | |
366 | in the memory location referenced by <code>__theValue</code>. If the values | |
367 | match, this function stores the value from <code>__newValue</code> into | |
368 | that memory location atomically. | |
369 | @result Returns TRUE on a match, FALSE otherwise. | |
224c7076 A |
370 | */ |
371 | bool OSAtomicCompareAndSwap32( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue ); | |
1f2f436a A |
372 | |
373 | ||
374 | /*! @abstract Compare and swap for 32-bit values with barrier. | |
375 | @discussion | |
376 | This function compares the value in <code>__oldValue</code> to the value | |
377 | in the memory location referenced by <code>__theValue</code>. If the values | |
378 | match, this function stores the value from <code>__newValue</code> into | |
379 | that memory location atomically. | |
380 | ||
381 | This function is equivalent to {@link OSAtomicCompareAndSwap32} | |
382 | except that it also introduces a barrier. | |
383 | @result Returns TRUE on a match, FALSE otherwise. | |
384 | */ | |
224c7076 | 385 | bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue ); |
1f2f436a A |
386 | |
387 | ||
388 | /*! @abstract Compare and swap pointers. | |
389 | @discussion | |
390 | This function compares the pointer stored in <code>__oldValue</code> to the pointer | |
391 | in the memory location referenced by <code>__theValue</code>. If the pointers | |
392 | match, this function stores the pointer from <code>__newValue</code> into | |
393 | that memory location atomically. | |
394 | @result Returns TRUE on a match, FALSE otherwise. | |
395 | */ | |
396 | bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | |
397 | ||
398 | ||
399 | /*! @abstract Compare and swap pointers with barrier. | |
400 | @discussion | |
401 | This function compares the pointer stored in <code>__oldValue</code> to the pointer | |
402 | in the memory location referenced by <code>__theValue</code>. If the pointers | |
403 | match, this function stores the pointer from <code>__newValue</code> into | |
404 | that memory location atomically. | |
405 | ||
406 | This function is equivalent to {@link OSAtomicCompareAndSwapPtr} | |
407 | except that it also introduces a barrier. | |
408 | @result Returns TRUE on a match, FALSE otherwise. | |
409 | */ | |
410 | bool OSAtomicCompareAndSwapPtrBarrier( void *__oldValue, void *__newValue, void * volatile *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | |
411 | ||
412 | ||
413 | /*! @abstract Compare and swap for <code>int</code> values. | |
414 | @discussion | |
415 | This function compares the value in <code>__oldValue</code> to the value | |
416 | in the memory location referenced by <code>__theValue</code>. If the values | |
417 | match, this function stores the value from <code>__newValue</code> into | |
418 | that memory location atomically. | |
419 | ||
420 | This function is equivalent to {@link OSAtomicCompareAndSwap32}. | |
421 | @result Returns TRUE on a match, FALSE otherwise. | |
422 | */ | |
423 | bool OSAtomicCompareAndSwapInt( int __oldValue, int __newValue, volatile int *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | |
424 | ||
425 | ||
426 | /*! @abstract Compare and swap for <code>int</code> values. | |
427 | @discussion | |
428 | This function compares the value in <code>__oldValue</code> to the value | |
429 | in the memory location referenced by <code>__theValue</code>. If the values | |
430 | match, this function stores the value from <code>__newValue</code> into | |
431 | that memory location atomically. | |
432 | ||
433 | This function is equivalent to {@link OSAtomicCompareAndSwapInt} | |
434 | except that it also introduces a barrier. | |
435 | ||
436 | This function is equivalent to {@link OSAtomicCompareAndSwap32Barrier}. | |
437 | @result Returns TRUE on a match, FALSE otherwise. | |
438 | */ | |
439 | bool OSAtomicCompareAndSwapIntBarrier( int __oldValue, int __newValue, volatile int *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | |
440 | ||
441 | ||
442 | /*! @abstract Compare and swap for <code>long</code> values. | |
443 | @discussion | |
444 | This function compares the value in <code>__oldValue</code> to the value | |
445 | in the memory location referenced by <code>__theValue</code>. If the values | |
446 | match, this function stores the value from <code>__newValue</code> into | |
447 | that memory location atomically. | |
448 | ||
449 | This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures, | |
450 | or {@link OSAtomicCompareAndSwap64} on 64-bit architectures. | |
451 | @result Returns TRUE on a match, FALSE otherwise. | |
452 | */ | |
453 | bool OSAtomicCompareAndSwapLong( long __oldValue, long __newValue, volatile long *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | |
454 | ||
455 | ||
456 | /*! @abstract Compare and swap for <code>long</code> values. | |
457 | @discussion | |
458 | This function compares the value in <code>__oldValue</code> to the value | |
459 | in the memory location referenced by <code>__theValue</code>. If the values | |
460 | match, this function stores the value from <code>__newValue</code> into | |
461 | that memory location atomically. | |
462 | ||
463 | This function is equivalent to {@link OSAtomicCompareAndSwapLong} | |
464 | except that it also introduces a barrier. | |
465 | ||
466 | This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures, | |
467 | or {@link OSAtomicCompareAndSwap64} on 64-bit architectures. | |
468 | @result Returns TRUE on a match, FALSE otherwise. | |
469 | */ | |
470 | bool OSAtomicCompareAndSwapLongBarrier( long __oldValue, long __newValue, volatile long *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | |
471 | ||
3d9156a7 | 472 | |
34e8f829 | 473 | #if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) |
3d9156a7 | 474 | |
1f2f436a A |
475 | /*! @abstract Compare and swap for <code>uint64_t</code> values. |
476 | @discussion | |
477 | This function compares the value in <code>__oldValue</code> to the value | |
478 | in the memory location referenced by <code>__theValue</code>. If the values | |
479 | match, this function stores the value from <code>__newValue</code> into | |
480 | that memory location atomically. | |
481 | @result Returns TRUE on a match, FALSE otherwise. | |
482 | */ | |
224c7076 | 483 | bool OSAtomicCompareAndSwap64( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue ); |
1f2f436a A |
484 | |
485 | ||
486 | /*! @abstract Compare and swap for <code>uint64_t</code> values. | |
487 | @discussion | |
488 | This function compares the value in <code>__oldValue</code> to the value | |
489 | in the memory location referenced by <code>__theValue</code>. If the values | |
490 | match, this function stores the value from <code>__newValue</code> into | |
491 | that memory location atomically. | |
492 | ||
493 | This function is equivalent to {@link OSAtomicCompareAndSwap64} | |
494 | except that it also introduces a barrier. | |
495 | @result Returns TRUE on a match, FALSE otherwise. | |
496 | */ | |
497 | bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_3_2); | |
3d9156a7 | 498 | |
34e8f829 | 499 | #endif /* defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) */ |
59e0d9fe | 500 | |
3d9156a7 A |
501 | |
502 | /* Test and set. They return the original value of the bit, and operate on bit (0x80>>(n&7)) | |
224c7076 | 503 | * in byte ((char*)theAddress + (n>>3)). |
59e0d9fe | 504 | */ |
1f2f436a A |
505 | /*! @abstract Atomic test and set |
506 | @discussion | |
507 | This function tests a bit in the value referenced by <code>__theAddress</code> | |
508 | and if it is not set, sets it. The bit is chosen by the value of <code>__n</code>. | |
509 | The bits are numbered in order beginning with bit 1 as the lowest order bit. | |
510 | ||
511 | For example, if <code>__theAddress</code> points to a 64-bit value, | |
512 | to compare the value of the highest bit, you would specify <code>64</code> for | |
513 | <code>__n</code>. | |
514 | @result | |
515 | Returns the original value of the bit being tested. | |
516 | */ | |
224c7076 | 517 | bool OSAtomicTestAndSet( uint32_t __n, volatile void *__theAddress ); |
1f2f436a A |
518 | |
519 | ||
520 | /*! @abstract Atomic test and set with barrier | |
521 | @discussion | |
522 | This function tests a bit in the value referenced by <code>__theAddress</code> | |
523 | and if it is not set, sets it. The bit is chosen by the value of <code>__n</code>. | |
524 | The bits are numbered in order beginning with bit 1 as the lowest order bit. | |
525 | ||
526 | For example, if <code>__theAddress</code> points to a 64-bit value, | |
527 | to compare the value of the highest bit, you would specify <code>64</code> for | |
528 | <code>__n</code>. | |
529 | ||
530 | This function is equivalent to {@link OSAtomicTestAndSet} | |
531 | except that it also introduces a barrier. | |
532 | @result | |
533 | Returns the original value of the bit being tested. | |
534 | */ | |
535 | ||
224c7076 | 536 | bool OSAtomicTestAndSetBarrier( uint32_t __n, volatile void *__theAddress ); |
1f2f436a A |
537 | |
538 | ||
539 | ||
540 | /*! @abstract Atomic test and clear | |
541 | @discussion | |
542 | This function tests a bit in the value referenced by <code>__theAddress</code> | |
543 | and if it is not cleared, clears it. The bit is chosen by the value of <code>__n</code>. | |
544 | The bits are numbered in order beginning with bit 1 as the lowest order bit. | |
545 | ||
546 | For example, if <code>__theAddress</code> points to a 64-bit value, | |
547 | to compare the value of the highest bit, you would specify <code>64</code> for | |
548 | <code>__n</code>. | |
549 | @result | |
550 | Returns the original value of the bit being tested. | |
551 | */ | |
224c7076 | 552 | bool OSAtomicTestAndClear( uint32_t __n, volatile void *__theAddress ); |
1f2f436a A |
553 | |
554 | ||
555 | /*! @abstract Atomic test and clear | |
556 | @discussion | |
557 | This function tests a bit in the value referenced by <code>__theAddress</code> | |
558 | and if it is not cleared, clears it. The bit is chosen by the value of <code>__n</code>. | |
559 | The bits are numbered in order beginning with bit 1 as the lowest order bit. | |
560 | ||
561 | For example, if <code>__theAddress</code> points to a 64-bit value, | |
562 | to compare the value of the highest bit, you would specify <code>64</code> for | |
563 | <code>__n</code>. | |
564 | ||
565 | This function is equivalent to {@link OSAtomicTestAndSet} | |
566 | except that it also introduces a barrier. | |
567 | @result | |
568 | Returns the original value of the bit being tested. | |
569 | */ | |
224c7076 | 570 | bool OSAtomicTestAndClearBarrier( uint32_t __n, volatile void *__theAddress ); |
3d9156a7 | 571 | |
224c7076 | 572 | |
1f2f436a A |
573 | /*! @group Spinlocks |
574 | * These spinlocks use memory barriers as required to synchronize access to shared | |
575 | * memory protected by the lock. | |
576 | */ | |
577 | ||
578 | /*! @abstract The default value for an <code>OSSpinLock</code>. | |
579 | @discussion | |
580 | The convention is that unlocked is zero, locked is nonzero. | |
59e0d9fe A |
581 | */ |
582 | #define OS_SPINLOCK_INIT 0 | |
583 | ||
1f2f436a A |
584 | |
585 | /*! @abstract Data type for a spinlock. | |
586 | @discussion | |
587 | You should always initialize a spinlock to {@link OS_SPINLOCK_INIT} before | |
588 | using it. | |
589 | */ | |
224c7076 | 590 | typedef int32_t OSSpinLock; |
59e0d9fe | 591 | |
1f2f436a A |
592 | |
593 | /*! @abstract Locks a spinlock if it would not block | |
594 | @result | |
595 | Returns <code>false</code> if the lock was already held by another thread, | |
596 | <code>true</code> if it took the lock successfully. | |
597 | */ | |
224c7076 | 598 | bool OSSpinLockTry( volatile OSSpinLock *__lock ); |
1f2f436a A |
599 | |
600 | ||
601 | /*! @abstract Locks a spinlock | |
602 | @discussion | |
603 | Although the lock operation spins, it employs various strategies | |
604 | to back off if the lock is held, making it immune to most priority-inversion | |
605 | livelocks. | |
606 | */ | |
224c7076 | 607 | void OSSpinLockLock( volatile OSSpinLock *__lock ); |
1f2f436a A |
608 | |
609 | ||
610 | /*! @abstract Unlocks a spinlock */ | |
224c7076 A |
611 | void OSSpinLockUnlock( volatile OSSpinLock *__lock ); |
612 | ||
613 | ||
1f2f436a A |
614 | /*! @group Lockless atomic enqueue and dequeue |
615 | * These routines manipulate singly-linked LIFO lists. | |
616 | */ | |
617 | ||
618 | /*! @abstract The data structure for a queue head. | |
619 | @discussion | |
620 | You should always initialize a queue head structure with the | |
621 | initialization vector {@link OS_ATOMIC_QUEUE_INIT} before use. | |
224c7076 A |
622 | */ |
623 | #if defined(__x86_64__) | |
624 | ||
625 | typedef volatile struct { | |
626 | void *opaque1; | |
627 | long opaque2; | |
1f2f436a | 628 | } __attribute__ ((aligned (16))) OSQueueHead; |
224c7076 A |
629 | |
630 | #else | |
631 | ||
632 | typedef volatile struct { | |
633 | void *opaque1; | |
634 | long opaque2; | |
635 | } OSQueueHead; | |
636 | ||
637 | #endif | |
638 | ||
1f2f436a | 639 | /*! @abstract The initialization vector for a queue head. */ |
224c7076 A |
640 | #define OS_ATOMIC_QUEUE_INIT { NULL, 0 } |
641 | ||
1f2f436a A |
642 | /*! @abstract Enqueue an item onto a list. |
643 | @discussion | |
644 | Memory barriers are incorporated as needed to permit thread-safe access | |
645 | to the queue element. | |
646 | @param __list | |
647 | The list on which you want to enqueue the item. | |
648 | @param __new | |
649 | The item to add. | |
650 | @param __offset | |
651 | The "offset" parameter is the offset (in bytes) of the link field | |
652 | from the beginning of the data structure being queued (<code>__new</code>). | |
653 | The link field should be a pointer type. | |
654 | The <code>__offset</code> value needs to be same for all enqueuing and | |
655 | dequeuing operations on the same queue, even if different structure types | |
656 | are enqueued on that queue. The use of <code>offsetset()</code>, defined in | |
657 | <code>stddef.h</code> is the common way to specify the <code>__offset</code> | |
658 | value. | |
659 | */ | |
660 | void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_4_0); | |
661 | ||
662 | ||
663 | /*! @abstract Dequeue an item from a list. | |
664 | @discussion | |
665 | Memory barriers are incorporated as needed to permit thread-safe access | |
666 | to the queue element. | |
667 | @param __list | |
668 | The list on which you want to enqueue the item. | |
669 | @param __offset | |
670 | The "offset" parameter is the offset (in bytes) of the link field | |
671 | from the beginning of the data structure being queued (<code>__new</code>). | |
672 | The link field should be a pointer type. | |
673 | The <code>__offset</code> value needs to be same for all enqueuing and | |
674 | dequeuing operations on the same queue, even if different structure types | |
675 | are enqueued on that queue. The use of <code>offsetset()</code>, defined in | |
676 | <code>stddef.h</code> is the common way to specify the <code>__offset</code> | |
677 | value. | |
678 | @result | |
679 | Returns the most recently enqueued element, or <code>NULL</code> if the | |
680 | list is empty. | |
681 | */ | |
682 | void* OSAtomicDequeue( OSQueueHead *__list, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_4_0); | |
59e0d9fe | 683 | |
1f2f436a | 684 | #if defined(__x86_64__) || defined(__i386__) |
3d9156a7 | 685 | |
1f2f436a A |
686 | /*! @group Lockless atomic fifo enqueue and dequeue |
687 | * These routines manipulate singly-linked FIFO lists. | |
59e0d9fe | 688 | */ |
59e0d9fe | 689 | |
1f2f436a A |
690 | /*! @abstract The data structure for a fifo queue head. |
691 | @discussion | |
692 | You should always initialize a fifo queue head structure with the | |
693 | initialization vector {@link OS_ATOMIC_FIFO_QUEUE_INIT} before use. | |
694 | */ | |
695 | #if defined(__x86_64__) | |
696 | ||
697 | typedef volatile struct { | |
698 | void *opaque1; | |
699 | void *opaque2; | |
700 | int opaque3; | |
701 | } __attribute__ ((aligned (16))) OSFifoQueueHead; | |
702 | ||
703 | #else | |
704 | ||
705 | typedef volatile struct { | |
706 | void *opaque1; | |
707 | void *opaque2; | |
708 | int opaque3; | |
709 | } OSFifoQueueHead; | |
710 | ||
711 | #endif | |
712 | ||
713 | /*! @abstract The initialization vector for a fifo queue head. */ | |
714 | #define OS_ATOMIC_FIFO_QUEUE_INIT { NULL, NULL, 0 } | |
715 | ||
716 | /*! @abstract Enqueue an item onto a list. | |
717 | @discussion | |
718 | Memory barriers are incorporated as needed to permit thread-safe access | |
719 | to the queue element. | |
720 | @param __list | |
721 | The list on which you want to enqueue the item. | |
722 | @param __new | |
723 | The item to add. | |
724 | @param __offset | |
725 | The "offset" parameter is the offset (in bytes) of the link field | |
726 | from the beginning of the data structure being queued (<code>__new</code>). | |
727 | The link field should be a pointer type. | |
728 | The <code>__offset</code> value needs to be same for all enqueuing and | |
729 | dequeuing operations on the same queue, even if different structure types | |
730 | are enqueued on that queue. The use of <code>offsetset()</code>, defined in | |
731 | <code>stddef.h</code> is the common way to specify the <code>__offset</code> | |
732 | value. | |
733 | */ | |
734 | void OSAtomicFifoEnqueue( OSFifoQueueHead *__list, void *__new, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); | |
735 | ||
736 | /*! @abstract Dequeue an item from a list. | |
737 | @discussion | |
738 | Memory barriers are incorporated as needed to permit thread-safe access | |
739 | to the queue element. | |
740 | @param __list | |
741 | The list on which you want to enqueue the item. | |
742 | @param __offset | |
743 | The "offset" parameter is the offset (in bytes) of the link field | |
744 | from the beginning of the data structure being queued (<code>__new</code>). | |
745 | The link field should be a pointer type. | |
746 | The <code>__offset</code> value needs to be same for all enqueuing and | |
747 | dequeuing operations on the same queue, even if different structure types | |
748 | are enqueued on that queue. The use of <code>offsetset()</code>, defined in | |
749 | <code>stddef.h</code> is the common way to specify the <code>__offset</code> | |
750 | value. | |
751 | @result | |
752 | Returns the oldest enqueued element, or <code>NULL</code> if the | |
753 | list is empty. | |
754 | */ | |
755 | void* OSAtomicFifoDequeue( OSFifoQueueHead *__list, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); | |
756 | ||
757 | #endif /* __i386__ || __x86_64__ */ | |
758 | ||
759 | /*! @group Memory barriers */ | |
760 | ||
761 | /*! @abstract Memory barrier. | |
762 | @discussion | |
763 | This function serves as both a read and write barrier. | |
764 | */ | |
765 | void OSMemoryBarrier( void ); | |
224c7076 | 766 | |
59e0d9fe A |
767 | __END_DECLS |
768 | ||
769 | #endif /* _OSATOMIC_H_ */ |