ATOMIC_DEPRECATED(3) | Library Functions Manual | ATOMIC_DEPRECATED(3) |
OSAtomicAdd32
,
OSAtomicAdd32Barrier
,
OSAtomicIncrement32
,
OSAtomicIncrement32Barrier
,
OSAtomicDecrement32
,
OSAtomicDecrement32Barrier
,
OSAtomicOr32
,
OSAtomicOr32Barrier
,
OSAtomicOr32Orig
,
OSAtomicOr32OrigBarrier
,
OSAtomicAnd32
,
OSAtomicAnd32Barrier
,
OSAtomicAnd32Orig
,
OSAtomicAnd32OrigBarrier
,
OSAtomicXor32
,
OSAtomicXor32Barrier
,
OSAtomicXor32Orig
,
OSAtomicXor32OrigBarrier
,
OSAtomicAdd64
,
OSAtomicAdd64Barrier
,
OSAtomicIncrement64
,
OSAtomicIncrement64Barrier
,
OSAtomicDecrement64
,
OSAtomicDecrement64Barrier
,
OSAtomicCompareAndSwapInt
,
OSAtomicCompareAndSwapIntBarrier
,
OSAtomicCompareAndSwapLong
,
OSAtomicCompareAndSwapLongBarrier
,
OSAtomicCompareAndSwapPtr
,
OSAtomicCompareAndSwapPtrBarrier
,
OSAtomicCompareAndSwap32
,
OSAtomicCompareAndSwap32Barrier
,
OSAtomicCompareAndSwap64
,
OSAtomicCompareAndSwap64Barrier
,
OSAtomicTestAndSet
,
OSAtomicTestAndSetBarrier
,
OSAtomicTestAndClear
,
OSAtomicTestAndClearBarrier
,
OSMemoryBarrier
— deprecated
atomic add, increment, decrement, or, and, xor, compare and swap, test and
set, test and clear, and memory barrier
#include
<libkern/OSAtomic.h>
int32_t
OSAtomicAdd32
(int32_t
theAmount, volatile
int32_t *theValue);
int32_t
OSAtomicAdd32Barrier
(int32_t
theAmount, volatile
int32_t *theValue);
int32_t
OSAtomicIncrement32
(volatile
int32_t *theValue);
int32_t
OSAtomicIncrement32Barrier
(volatile
int32_t *theValue);
int32_t
OSAtomicDecrement32
(volatile
int32_t *theValue);
int32_t
OSAtomicDecrement32Barrier
(volatile
int32_t *theValue);
int32_t
OSAtomicOr32
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicOr32Barrier
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicAnd32
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicAnd32Barrier
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicXor32
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicXor32Barrier
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicOr32Orig
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicOr32OrigBarrier
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicAnd32Orig
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicAnd32OrigBarrier
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicXor32Orig
(uint32_t
theMask, volatile
uint32_t *theValue);
int32_t
OSAtomicXor32OrigBarrier
(uint32_t
theMask, volatile
uint32_t *theValue);
int64_t
OSAtomicAdd64
(int64_t
theAmount, volatile
OSAtomic_int64_aligned64_t *theValue);
int64_t
OSAtomicAdd64Barrier
(int64_t
theAmount, volatile
OSAtomic_int64_aligned64_t *theValue);
int64_t
OSAtomicIncrement64
(volatile
OSAtomic_int64_aligned64_t *theValue);
int64_t
OSAtomicIncrement64Barrier
(volatile
OSAtomic_int64_aligned64_t *theValue);
int64_t
OSAtomicDecrement64
(volatile
OSAtomic_int64_aligned64_t *theValue);
int64_t
OSAtomicDecrement64Barrier
(volatile
OSAtomic_int64_aligned64_t *theValue);
bool
OSAtomicCompareAndSwapInt
(int
oldValue, int
newValue, volatile int
*theValue);
bool
OSAtomicCompareAndSwapIntBarrier
(int
oldValue, int
newValue, volatile int
*theValue);
bool
OSAtomicCompareAndSwapLong
(long
oldValue, long
newValue, volatile long
*theValue);
bool
OSAtomicCompareAndSwapLongBarrier
(long
oldValue, long
newValue, volatile long
*theValue);
bool
OSAtomicCompareAndSwapPtr
(void*
oldValue, void*
newValue, void* volatile
*theValue);
bool
OSAtomicCompareAndSwapPtrBarrier
(void*
oldValue, void*
newValue, void* volatile
*theValue);
bool
OSAtomicCompareAndSwap32
(int32_t
oldValue, int32_t
newValue, volatile
int32_t *theValue);
bool
OSAtomicCompareAndSwap32Barrier
(int32_t
oldValue, int32_t
newValue, volatile
int32_t *theValue);
bool
OSAtomicCompareAndSwap64
(int64_t
oldValue, int64_t
newValue, volatile
OSAtomic_int64_aligned64_t *theValue);
bool
OSAtomicCompareAndSwap64Barrier
(int64_t
oldValue, int64_t
newValue, volatile
OSAtomic_int64_aligned64_t *theValue);
bool
OSAtomicTestAndSet
(uint32_t
n, volatile void
*theAddress);
bool
OSAtomicTestAndSetBarrier
(uint32_t
n, volatile void
*theAddress);
bool
OSAtomicTestAndClear
(uint32_t
n, volatile void
*theAddress);
bool
OSAtomicTestAndClearBarrier
(uint32_t
n, volatile void
*theAddress);
bool
OSAtomicEnqueue
(OSQueueHead
*list, void *new,
size_t offset);
void*
OSAtomicDequeue
(OSQueueHead
*list, size_t
offset);
void
OSMemoryBarrier
(void);
<stdatomic.h>
interfaces
described in stdatomic(3).These functions are thread and multiprocessor safe. For each function, there is a version which incorporates a memory barrier and another version which does not. Barriers strictly order memory access on a weakly-ordered architecture such as ARM. All loads and stores executed in sequential program order before the barrier will complete before any load or store executed after the barrier. On some platforms, such as ARM, the barrier operation can be quite expensive.
Most code will want to use the
barrier functions to ensure that memory shared between threads is properly
synchronized. For example, if you want to initialize a shared data structure
and then atomically increment a variable to indicate that the initialization
is complete, then you must use
OSAtomicIncrement32Barrier
()
to ensure that the stores to your data structure complete before the atomic
add. Likewise, the consumer of that data structure must use
OSAtomicDecrement32Barrier
(),
in order to ensure that their loads of the structure are not executed before
the atomic decrement. On the other hand, if you are simply incrementing a
global counter, then it is safe and potentially much faster to use
OSAtomicIncrement32
().
If you are unsure which version to use, prefer the barrier variants as they
are safer.
The logical (and, or, xor) and bit
test operations are layered on top of the
OSAtomicCompareAndSwap
()
primitives. There are four versions of each logical operation, depending on
whether or not there is a barrier, and whether the return value is the
result of the operation (eg,
OSAtomicOr32
()
) or the original value before the operation (eg,
OSAtomicOr32Orig
()
).
The memory address theValue must be "naturally aligned", i.e. 32-bit aligned for 32-bit operations and 64-bit aligned for 64-bit operations. Note that this is not the default alignment of the int64_t in the iOS ARMv7 ABI, the OSAtomic_int64_aligned64_t type can be used to declare variables with the required alignment.
The
OSAtomicCompareAndSwap
()
operations compare oldValue to
*theValue, and set *theValue to
newValue if the comparison is equal. The comparison
and assignment occur as one atomic operation.
OSAtomicTestAndSet
()
and
OSAtomicTestAndClear
()
operate on bit (0x80 >> ( n & 7)) of byte
((char*) theAddress + ( n
>> 3)). They set the named bit to either 1 or 0, respectively.
theAddress need not be aligned.
The
OSMemoryBarrier
()
function strictly orders memory accesses in a weakly ordered memory model
such as with ARM, by creating a barrier. All loads and stores executed in
sequential program order before the barrier will complete with respect to
the memory coherence mechanism, before any load or store executed after the
barrier. Used with an atomic operation, the barrier can be used to create
custom synchronization protocols as an alternative to the spinlock or
queue/dequeue operations. Note that this barrier does not order uncached
loads and stores. On a uniprocessor, the barrier operation is typically
optimized into a no-op.
The arithmetic operations return the new value, after the operation has been performed. The boolean operations come in two styles, one of which returns the new value, and one of which (the "Orig" versions) returns the old. The compare-and-swap operations return true if the comparison was equal, ie if the swap occured. The bit test and set/clear operations return the original value of the bit.
Most of these functions first appeared in Mac OS 10.4 (Tiger). The "Orig" forms of the boolean operations, the "int", "long" and "ptr" forms of compare-and-swap first appeared in Mac OS 10.5 (Leopard).
March 7, 2016 | Darwin |