Mac OS X Manual Page For OSAtomicIncrement32Barrier(3) (original) (raw)
ATOMIC(3) BSD Library Functions Manual ATOMIC(3)
NAME 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, OSSpinLockTry, OSSpinLockLock, OSSpinLockUnlock, OSAtomicEnqueue, OSAtomicDequeue -- atomic add, incre-ment, increment, ment, decrement, or, and, xor, compare and swap, test and set, test and clear, spinlocks, and lockless queues
LIBRARY Standard C Library (libc, -lc)
SYNOPSIS #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 int64**_**t *theValue);
int64**_**t
**OSAtomicAdd64Barrier**(int64**_**t theAmount, volatile int64**_**t *theValue);
int64**_**t
**OSAtomicIncrement64**(volatile int64**_**t *theValue);
int64**_**t
**OSAtomicIncrement64Barrier**(volatile int64**_**t *theValue);
int64**_**t
**OSAtomicDecrement64**(volatile int64**_**t *theValue);
int64**_**t
**OSAtomicDecrement64Barrier**(volatile int64**_**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 int64**_**t *theValue);
bool
**OSAtomicCompareAndSwap64Barrier**(int64**_**t oldValue, int64**_**t newValue,
volatile int64**_**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
**OSSpinLockTry**(OSSpinLock *lock);
void
**OSSpinLockLock**(OSSpinLock *lock);
void
**OSSpinLockUnlock**(OSSpinLock *lock);
void
**OSAtomicEnqueue**(OSQueueHead *list, void *new, size**_**t offset);
void*
**OSAtomicDequeue**(OSQueueHead *list, size**_**t offset);
DESCRIPTION These functions are thread and multiprocessor safe. For each function, there is a version that does and another that does not incorporate a mem-ory memory ory barrier. Barriers strictly order memory access on a weakly-ordered architecture such as PPC. All loads and stores executed in sequential program order before the barrier will complete before any load or store executed after the barrier. On a uniprocessor, the barrier operation is typically a nop. On a multiprocessor, the barrier can be quite expen-sive. expensive. sive.
Most code will want to use the barrier functions to insure 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 OSAtomicIn-crement32(). OSAtomicIncrement32().
crement32(). 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, ie 32-bit aligned
for 32-bit operations and 64-bit aligned for 64-bit operations.
The 64-bit operations are not implemented for 32-bit processes on PPC
platforms.
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 routines **OSAtomicEnqueue**() and **OSAtomicDequeue**() operate on singly
linked LIFO queues. Ie, a dequeue operation will return the most
recently enqueued element, or NULL if the list is empty. The operations
are lockless, and barriers are used as necessary to permit thread-safe
access to the queue element. offset is the offset in bytes to the link
field in the queue element. For example:
typedef struct elem {
long data1;
struct elem *link;
int data2;
} elem_t;
elem_t fred, mary, *p;
OSQueueHead q = OS_ATOMIC_QUEUE_INIT;
OSAtomicEnqueue( &q, &fred, offsetof(elem_t,link) );
OSAtomicEnqueue( &q, &mary, offsetof(elem_t,link) );
p = OSAtomicDequeue( &q, offsetof(elem_t,link) );
In this example, the call of **OSAtomicDequeue**() will return a ptr to mary.
RETURN VALUES 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. The dequeue operation returns the most recently enqueued element, or NULL if the list in empty.
SEE ALSO spinlock(3), barrier(3)
HISTORY 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, and lockless enqueue/dequeue first appeared in Mac OS 10.5 (Leopard).
Darwin May 26, 2004 Darwin