ADC Home > Reference Library > Reference > Mac OS X > Mac OS X Man Pages

 

This document is a Mac OS X manual page. Manual pages are a command-line technology for providing documentation. You can view these manual pages locally using the man(1) command. These manual pages come from many different sources, and thus, have a variety of writing styles.

For more information about the manual page format, see the manual page for manpages(5).



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 memory 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 uniproces-sor, uniprocessor,
     sor, 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 prop-erly properly
     erly 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 OSAtomicIncre-ment32Barrier() OSAtomicIncrement32Barrier()
     ment32Barrier() to ensure that the stores to your data structure complete before the atomic add.  Like-wise, Likewise,
     wise, 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 orig-inal original
     inal 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" ver-sions) versions)
     sions) 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 opera-tions, operations,
     tions, 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

Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.