1/*
2 * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
3 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
4 *
5 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. The rights granted to you under the License
11 * may not be used to create, or enable the creation or redistribution of,
12 * unlawful or unlicensed copies of an Apple operating system, or to
13 * circumvent, violate, or enable the circumvention or violation of, any
14 * terms of an Apple operating system software license agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 *
19 * The Original Code and all software distributed under the License are
20 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
21 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
22 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
24 * Please see the License for the specific language governing rights and
25 * limitations under the License.
26 *
27 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 */
29/*
30 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
31 *
32 * HISTORY
33 *
34 */
35
36#ifndef _OS_OSATOMIC_H
37#define _OS_OSATOMIC_H
38
39#include <libkern/OSBase.h>
40#include <string.h>
41
42#if defined(__cplusplus)
43extern "C" {
44#endif
45
46#ifdef XNU_KERNEL_PRIVATE
47/*
48 * The macro SAFE_CAST_PTR() casts one type of pointer to another type,
49 * making sure the data the pointer is referencing is the same size.
50 * If it is not, it will cause a "size mismatch" assertion.
51 *
52 * This is to work around "SInt32" being defined as "long" on ILP32 and as "int"
53 * on LP64, which would require an explicit cast to "SInt32*" when for instance
54 * passing an "int*" to OSAddAtomic() - which masks size mismatches.
55 * -- var is used, but sizeof does not evaluate the
56 * argument, i.e. we're safe against "++" etc. in var --
57 */
58#define __SAFE_CAST_PTR(type, var) \
59 ({ _Static_assert(sizeof(*(var)) == sizeof(*(type)NULL), "size mismatch"); ((type)(var)); })
60#else
61#define __SAFE_CAST_PTR(type, var) ((type)(var))
62#endif
63
64/*!
65 * @header
66 *
67 * @abstract
68 * This header declares the OSAtomic group of functions for atomic
69 * reading and updating of values.
70 */
71
72/*!
73 * @function OSCompareAndSwap64
74 *
75 * @abstract
76 * 64-bit compare and swap operation.
77 *
78 * @discussion
79 * See OSCompareAndSwap.
80 */
81extern Boolean OSCompareAndSwap64(
82 UInt64 oldValue,
83 UInt64 newValue,
84 volatile UInt64 * address);
85#define OSCompareAndSwap64(a, b, c) \
86 (OSCompareAndSwap64(a, b, __SAFE_CAST_PTR(volatile UInt64*,c)))
87
88/*!
89 * @function OSAddAtomic64
90 *
91 * @abstract
92 * 64-bit atomic add operation.
93 *
94 * @discussion
95 * See OSAddAtomic.
96 */
97extern SInt64 OSAddAtomic64(
98 SInt64 theAmount,
99 volatile SInt64 * address);
100#define OSAddAtomic64(a, b) \
101 (OSAddAtomic64(a, __SAFE_CAST_PTR(volatile SInt64*,b)))
102
103/*!
104 * @function OSIncrementAtomic64
105 *
106 * @abstract
107 * 64-bit increment.
108 *
109 * @discussion
110 * See OSIncrementAtomic.
111 */
112inline static SInt64
113OSIncrementAtomic64(volatile SInt64 * address)
114{
115 return OSAddAtomic64(1LL, address);
116}
117
118/*!
119 * @function OSDecrementAtomic64
120 *
121 * @abstract
122 * 64-bit decrement.
123 *
124 * @discussion
125 * See OSDecrementAtomic.
126 */
127inline static SInt64
128OSDecrementAtomic64(volatile SInt64 * address)
129{
130 return OSAddAtomic64(-1LL, address);
131}
132
133#if XNU_KERNEL_PRIVATE
134/* Not to be included in headerdoc.
135 *
136 * @function OSAddAtomicLong
137 *
138 * @abstract
139 * 32/64-bit atomic add operation, depending on sizeof(long).
140 *
141 * @discussion
142 * See OSAddAtomic.
143 */
144extern long OSAddAtomicLong(
145 long theAmount,
146 volatile long * address);
147#define OSAddAtomicLong(a, b) \
148 (OSAddAtomicLong(a, __SAFE_CAST_PTR(volatile long*,b)))
149
150/* Not to be included in headerdoc.
151 *
152 * @function OSIncrementAtomicLong
153 *
154 * @abstract
155 * 32/64-bit increment, depending on sizeof(long)
156 *
157 * @discussion
158 * See OSIncrementAtomic.
159 */
160inline static long
161OSIncrementAtomicLong(volatile long * address)
162{
163 return OSAddAtomicLong(1L, address);
164}
165
166/* Not to be included in headerdoc.
167 *
168 * @function OSDecrementAtomicLong
169 *
170 * @abstract
171 * 32/64-bit decrement, depending on sizeof(long)
172 *@discussion See OSDecrementAtomic.
173 */
174inline static long
175OSDecrementAtomicLong(volatile long * address)
176{
177 return OSAddAtomicLong(-1L, address);
178}
179#endif /* XNU_KERNEL_PRIVATE */
180
181#if XNU_KERNEL_PRIVATE
182/*!
183 * @function OSCompareAndSwap8
184 *
185 * @abstract
186 * Compare and swap operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
187 *
188 * @discussion
189 * The OSCompareAndSwap8 function compares the value at the specified address with oldVal. The value of newValue is written to the address only if oldValue and the value at the address are equal. OSCompareAndSwap returns true if newValue is written to the address; otherwise, it returns false.
190 *
191 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Additionally, this function incorporates a memory barrier on systems with weakly-ordered memory architectures.
192 *
193 * @param oldValue The value to compare at address.
194 * @param newValue The value to write to address if oldValue compares true.
195 * @param address The byte aligned address of the data to update atomically.
196 * @result true if newValue was written to the address.
197 */
198extern Boolean OSCompareAndSwap8(
199 UInt8 oldValue,
200 UInt8 newValue,
201 volatile UInt8 * address);
202#define OSCompareAndSwap8(a, b, c) \
203 (OSCompareAndSwap8(a, b, __SAFE_CAST_PTR(volatile UInt8*,c)))
204
205/*!
206 * @function OSCompareAndSwap16
207 *
208 * @abstract
209 * Compare and swap operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
210 *
211 * @discussion
212 * The OSCompareAndSwap16 function compares the value at the specified address with oldVal. The value of newValue is written to the address only if oldValue and the value at the address are equal. OSCompareAndSwap returns true if newValue is written to the address; otherwise, it returns false.
213 *
214 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Additionally, this function incorporates a memory barrier on systems with weakly-ordered memory architectures.
215 *
216 * @param oldValue The value to compare at address.
217 * @param newValue The value to write to address if oldValue compares true.
218 * @param address The 2-byte aligned address of the data to update atomically.
219 * @result true if newValue was written to the address.
220 */
221extern Boolean OSCompareAndSwap16(
222 UInt16 oldValue,
223 UInt16 newValue,
224 volatile UInt16 * address);
225#define OSCompareAndSwap16(a, b, c) \
226 (OSCompareAndSwap16(a, b, __SAFE_CAST_PTR(volatile UInt16*,c)))
227
228#endif /* XNU_KERNEL_PRIVATE */
229
230/*!
231 * @function OSCompareAndSwap
232 *
233 * @abstract
234 * Compare and swap operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
235 *
236 * @discussion
237 * The OSCompareAndSwap function compares the value at the specified address with oldVal. The value of newValue is written to the address only if oldValue and the value at the address are equal. OSCompareAndSwap returns true if newValue is written to the address; otherwise, it returns false.
238 *
239 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Additionally, this function incorporates a memory barrier on systems with weakly-ordered memory architectures.
240 *
241 * @param oldValue The value to compare at address.
242 * @param newValue The value to write to address if oldValue compares true.
243 * @param address The 4-byte aligned address of the data to update atomically.
244 * @result true if newValue was written to the address.
245 */
246extern Boolean OSCompareAndSwap(
247 UInt32 oldValue,
248 UInt32 newValue,
249 volatile UInt32 * address);
250#define OSCompareAndSwap(a, b, c) \
251 (OSCompareAndSwap(a, b, __SAFE_CAST_PTR(volatile UInt32*,c)))
252
253/*!
254 * @function OSCompareAndSwapPtr
255 *
256 * @abstract
257 * Compare and swap operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
258 *
259 * @discussion
260 * The OSCompareAndSwapPtr function compares the pointer-sized value at the specified address with oldVal. The value of newValue is written to the address only if oldValue and the value at the address are equal. OSCompareAndSwapPtr returns true if newValue is written to the address; otherwise, it returns false.
261 *
262 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Additionally, this function incorporates a memory barrier on systems with weakly-ordered memory architectures.
263 * @param oldValue The pointer value to compare at address.
264 * @param newValue The pointer value to write to address if oldValue compares true.
265 * @param address The pointer-size aligned address of the data to update atomically.
266 * @result true if newValue was written to the address.
267 */
268extern Boolean OSCompareAndSwapPtr(
269 void * oldValue,
270 void * newValue,
271 void * volatile * address);
272#define OSCompareAndSwapPtr(a, b, c) \
273 (OSCompareAndSwapPtr(a, b, __SAFE_CAST_PTR(void * volatile *,c)))
274
275/*!
276 * @function OSAddAtomic
277 *
278 * @abstract
279 * 32-bit add operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
280 *
281 * @discussion
282 * The OSAddAtomic function adds the specified amount to the value at the specified address and returns the original value.
283 *
284 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Previous incarnations of this function incorporated a memory barrier on systems with weakly-ordered memory architectures, but current versions contain no barriers.
285 * @param amount The amount to add.
286 * @param address The 4-byte aligned address of the value to update atomically.
287 * @result The value before the addition
288 */
289extern SInt32 OSAddAtomic(
290 SInt32 amount,
291 volatile SInt32 * address);
292#define OSAddAtomic(a, b) \
293 (OSAddAtomic(a, __SAFE_CAST_PTR(volatile SInt32*,b)))
294
295/*!
296 * @function OSAddAtomic16
297 *
298 * @abstract
299 * 16-bit add operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
300 *
301 * @discussion
302 * The OSAddAtomic16 function adds the specified amount to the value at the specified address and returns the original value.
303 *
304 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Previous incarnations of this function incorporated a memory barrier on systems with weakly-ordered memory architectures, but current versions contain no barriers.
305 * @param address The 2-byte aligned address of the value to update atomically.
306 * @result The value before the addition
307 */
308extern SInt16 OSAddAtomic16(
309 SInt32 amount,
310 volatile SInt16 * address);
311
312/*!
313 * @function OSAddAtomic8
314 *
315 * @abstract
316 * 8-bit add operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
317 *
318 * @discussion
319 * The OSAddAtomic8 function adds the specified amount to the value at the specified address and returns the original value.
320 *
321 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Previous incarnations of this function incorporated a memory barrier on systems with weakly-ordered memory architectures, but current versions contain no barriers.
322 * @param amount The amount to add.
323 * @param address The address of the value to update atomically.
324 * @result The value before the addition.
325 */
326extern SInt8 OSAddAtomic8(
327 SInt32 amount,
328 volatile SInt8 * address);
329
330/*!
331 * @function OSIncrementAtomic
332 *
333 * @abstract
334 * 32-bit increment operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
335 *
336 * @discussion
337 * The OSIncrementAtomic function increments the value at the specified address by one and returns the original value.
338 *
339 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
340 * @param address The 4-byte aligned address of the value to update atomically.
341 * @result The value before the increment.
342 */
343extern SInt32 OSIncrementAtomic(volatile SInt32 * address);
344#define OSIncrementAtomic(a) \
345 (OSIncrementAtomic(__SAFE_CAST_PTR(volatile SInt32*,a)))
346
347/*!
348 * @function OSIncrementAtomic16
349 *
350 * @abstract
351 * 16-bit increment operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
352 *
353 * @discussion
354 * The OSIncrementAtomic16 function increments the value at the specified address by one and returns the original value.
355 *
356 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Previous incarnations of this function incorporated a memory barrier on systems with weakly-ordered memory architectures, but current versions contain no barriers.
357 * @param address The 2-byte aligned address of the value to update atomically.
358 * @result The value before the increment.
359 */
360extern SInt16 OSIncrementAtomic16(volatile SInt16 * address);
361
362/*!
363 * @function OSIncrementAtomic8
364 *
365 * @abstract
366 * 8-bit increment operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
367 *
368 * @discussion
369 * The OSIncrementAtomic8 function increments the value at the specified address by one and returns the original value.
370 *
371 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Previous incarnations of this function incorporated a memory barrier on systems with weakly-ordered memory architectures, but current versions contain no barriers.
372 * @param address The address of the value to update atomically.
373 * @result The value before the increment.
374 */
375extern SInt8 OSIncrementAtomic8(volatile SInt8 * address);
376
377/*!
378 * @function OSDecrementAtomic
379 *
380 * @abstract
381 * 32-bit decrement operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
382 *
383 * @discussion
384 * The OSDecrementAtomic function decrements the value at the specified address by one and returns the original value.
385 *
386 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Previous incarnations of this function incorporated a memory barrier on systems with weakly-ordered memory architectures, but current versions contain no barriers.
387 * @param address The 4-byte aligned address of the value to update atomically.
388 * @result The value before the decrement.
389 */
390extern SInt32 OSDecrementAtomic(volatile SInt32 * address);
391#define OSDecrementAtomic(a) \
392 (OSDecrementAtomic(__SAFE_CAST_PTR(volatile SInt32*,a)))
393
394/*!
395 * @function OSDecrementAtomic16
396 *
397 * @abstract
398 * 16-bit decrement operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
399 *
400 * @discussion
401 * The OSDecrementAtomic16 function decrements the value at the specified address by one and returns the original value.
402 *
403 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Previous incarnations of this function incorporated a memory barrier on systems with weakly-ordered memory architectures, but current versions contain no barriers.
404 * @param address The 2-byte aligned address of the value to update atomically.
405 * @result The value before the decrement.
406 */
407extern SInt16 OSDecrementAtomic16(volatile SInt16 * address);
408
409/*!
410 * @function OSDecrementAtomic8
411 *
412 * @abstract
413 * 8-bit decrement operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
414 *
415 * @discussion
416 * The OSDecrementAtomic8 function decrements the value at the specified address by one and returns the original value.
417 *
418 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Previous incarnations of this function incorporated a memory barrier on systems with weakly-ordered memory architectures, but current versions contain no barriers.
419 * @param address The address of the value to update atomically.
420 * @result The value before the decrement.
421 */
422extern SInt8 OSDecrementAtomic8(volatile SInt8 * address);
423
424/*!
425 * @function OSBitAndAtomic
426 *
427 * @abstract
428 * 32-bit logical and operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
429 *
430 * @discussion
431 * The OSBitAndAtomic function logically ands the bits of the specified mask into the value at the specified address and returns the original value.
432 *
433 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device. Previous incarnations of this function incorporated a memory barrier on systems with weakly-ordered memory architectures, but current versions contain no barriers..
434 * @param mask The mask to logically and with the value.
435 * @param address The 4-byte aligned address of the value to update atomically.
436 * @result The value before the bitwise operation
437 */
438extern UInt32 OSBitAndAtomic(
439 UInt32 mask,
440 volatile UInt32 * address);
441#define OSBitAndAtomic(a, b) \
442 (OSBitAndAtomic(a, __SAFE_CAST_PTR(volatile UInt32*,b)))
443
444/*!
445 * @function OSBitAndAtomic16
446 *
447 * @abstract
448 * 16-bit logical and operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
449 *
450 * @discussion
451 * The OSBitAndAtomic16 function logically ands the bits of the specified mask into the value at the specified address and returns the original value.
452 *
453 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
454 * @param mask The mask to logically and with the value.
455 * @param address The 2-byte aligned address of the value to update atomically.
456 * @result The value before the bitwise operation.
457 */
458extern UInt16 OSBitAndAtomic16(
459 UInt32 mask,
460 volatile UInt16 * address);
461
462/*!
463 * @function OSBitAndAtomic8
464 *
465 * @abstract
466 * 8-bit logical and operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
467 *
468 * @discussion
469 * The OSBitAndAtomic8 function logically ands the bits of the specified mask into the value at the specified address and returns the original value.
470 *
471 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
472 * @param mask The mask to logically and with the value.
473 * @param address The address of the value to update atomically.
474 * @result The value before the bitwise operation.
475 */
476extern UInt8 OSBitAndAtomic8(
477 UInt32 mask,
478 volatile UInt8 * address);
479
480/*!
481 * @function OSBitOrAtomic
482 *
483 * @abstract
484 * 32-bit logical or operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
485 *
486 * @discussion
487 * The OSBitOrAtomic function logically ors the bits of the specified mask into the value at the specified address and returns the original value.
488 *
489 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
490 * @param mask The mask to logically or with the value.
491 * @param address The 4-byte aligned address of the value to update atomically.
492 * @result The value before the bitwise operation.
493 */
494extern UInt32 OSBitOrAtomic(
495 UInt32 mask,
496 volatile UInt32 * address);
497#define OSBitOrAtomic(a, b) \
498 (OSBitOrAtomic(a, __SAFE_CAST_PTR(volatile UInt32*,b)))
499
500/*!
501 * @function OSBitOrAtomic16
502 *
503 * @abstract
504 * 16-bit logical or operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
505 *
506 * @discussion
507 * The OSBitOrAtomic16 function logically ors the bits of the specified mask into the value at the specified address and returns the original value.
508 *
509 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
510 * @param mask The mask to logically or with the value.
511 * @param address The 2-byte aligned address of the value to update atomically.
512 * @result The value before the bitwise operation.
513 */
514extern UInt16 OSBitOrAtomic16(
515 UInt32 mask,
516 volatile UInt16 * address);
517
518/*!
519 * @function OSBitOrAtomic8
520 *
521 * @abstract
522 * 8-bit logical or operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
523 *
524 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
525 *
526 * @discussion
527 * The OSBitOrAtomic8 function logically ors the bits of the specified mask into the value at the specified address and returns the original value.
528 * @param mask The mask to logically or with the value.
529 * @param address The address of the value to update atomically.
530 * @result The value before the bitwise operation.
531 */
532extern UInt8 OSBitOrAtomic8(
533 UInt32 mask,
534 volatile UInt8 * address);
535
536/*!
537 * @function OSBitXorAtomic
538 *
539 * @abstract
540 * 32-bit logical xor operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
541 *
542 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
543 *
544 * @discussion
545 * The OSBitXorAtomic function logically xors the bits of the specified mask into the value at the specified address and returns the original value.
546 * @param mask The mask to logically or with the value.
547 * @param address The 4-byte aligned address of the value to update atomically.
548 * @result The value before the bitwise operation.
549 */
550extern UInt32 OSBitXorAtomic(
551 UInt32 mask,
552 volatile UInt32 * address);
553#define OSBitXorAtomic(a, b) \
554 (OSBitXorAtomic(a, __SAFE_CAST_PTR(volatile UInt32*,b)))
555
556/*!
557 * @function OSBitXorAtomic16
558 *
559 * @abstract
560 * 16-bit logical xor operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
561 *
562 * @discussion
563 * The OSBitXorAtomic16 function logically xors the bits of the specified mask into the value at the specified address and returns the original value.
564 *
565 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
566 * @param mask The mask to logically or with the value.
567 * @param address The 2-byte aligned address of the value to update atomically.
568 * @result The value before the bitwise operation.
569 */
570extern UInt16 OSBitXorAtomic16(
571 UInt32 mask,
572 volatile UInt16 * address);
573
574/*!
575 * @function OSBitXorAtomic8
576 *
577 * @abstract
578 * 8-bit logical xor operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
579 *
580 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
581 *
582 * @discussion
583 * The OSBitXorAtomic8 function logically xors the bits of the specified mask into the value at the specified address and returns the original value.
584 * @param mask The mask to logically or with the value.
585 * @param address The address of the value to update atomically.
586 * @result The value before the bitwise operation.
587 */
588extern UInt8 OSBitXorAtomic8(
589 UInt32 mask,
590 volatile UInt8 * address);
591
592/*!
593 * @function OSTestAndSet
594 *
595 * @abstract
596 * Bit test and set operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
597 *
598 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
599 *
600 * @discussion
601 * The OSTestAndSet function sets a single bit in a byte at a specified address. It returns true if the bit was already set, false otherwise.
602 * @param bit The bit number in the range 0 through 7. Bit 0 is the most significant.
603 * @param startAddress The address of the byte to update atomically.
604 * @result true if the bit was already set, false otherwise.
605 */
606extern Boolean OSTestAndSet(
607 UInt32 bit,
608 volatile UInt8 * startAddress);
609
610/*!
611 * @function OSTestAndClear
612 *
613 * @abstract
614 * Bit test and clear operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform.
615 *
616 * @discussion
617 * The OSTestAndClear function clears a single bit in a byte at a specified address. It returns true if the bit was already clear, false otherwise.
618 *
619 * This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.
620 * @param bit The bit number in the range 0 through 7. Bit 0 is the most significant.
621 * @param startAddress The address of the byte to update atomically.
622 * @result true if the bit was already clear, false otherwise.
623 */
624extern Boolean OSTestAndClear(
625 UInt32 bit,
626 volatile UInt8 * startAddress);
627
628/*!
629 * @defined OS_SPINLOCK_INIT
630 *
631 * @abstract
632 * The default value for an OSSpinLock.
633 *
634 * @discussion
635 * The convention is that unlocked is zero, locked is nonzero.
636 */
637#define OS_SPINLOCK_INIT 0
638
639/*!
640 * @typedef OSSpinLock
641 *
642 * @abstract
643 * Data type for a spinlock.
644 *
645 * @discussion
646 * You should always initialize a spinlock to OS_SPINLOCK_INIT before using it.
647 */
648typedef SInt32 OSSpinLock;
649
650#ifdef PRIVATE
651/*!
652 * @function OSSpinLockTry
653 *
654 * @abstract
655 * Locks a spinlock if it would not block.
656 *
657 * @discussion
658 * Multiprocessor locks used within the shared memory area between the kernel and event system. These must work in both user and kernel mode.
659 *
660 * @result
661 * Returns false if the lock was already held by another thread, true if it took the lock successfully.
662 */
663extern Boolean OSSpinLockTry(volatile OSSpinLock * lock);
664
665/*!
666 * @function OSSpinLockUnlock
667 *
668 * @abstract
669 * Unlocks a spinlock.
670 *
671 * @discussion
672 * Unlocks a spinlock.
673 */
674extern void OSSpinLockUnlock(volatile OSSpinLock * lock);
675#endif /* PRIVATE */
676
677/*!
678 * @function OSSynchronizeIO
679 *
680 * @abstract
681 * The OSSynchronizeIO routine ensures orderly load and store operations to noncached memory mapped I/O devices.
682 *
683 * @discussion
684 * The OSSynchronizeIO routine ensures orderly load and store operations to noncached memory mapped I/O devices. It executes the eieio instruction on PowerPC processors.
685 */
686#if defined(__arm__) || defined(__arm64__)
687extern void OSSynchronizeIO(void);
688#else
689static __inline__ void
690OSSynchronizeIO(void)
691{
692}
693#endif
694
695#if defined(KERNEL_PRIVATE)
696
697#if defined(__arm__) || defined(__arm64__)
698static inline void
699OSMemoryBarrier(void)
700{
701 __asm__ volatile ("dmb ish" ::: "memory");
702}
703#elif defined(__i386__) || defined(__x86_64__)
704#if defined(XNU_KERNEL_PRIVATE)
705static inline void
706OSMemoryBarrier(void)
707{
708 __asm__ volatile ("mfence" ::: "memory");
709}
710#endif /* XNU_KERNEL_PRIVATE */
711#endif
712
713#endif /* KERNEL_PRIVATE */
714
715#if defined(__cplusplus)
716}
717#endif
718
719#endif /* ! _OS_OSATOMIC_H */
720