]> git.saurik.com Git - apple/libc.git/blobdiff - sys/atomic.3
Libc-498.1.7.tar.gz
[apple/libc.git] / sys / atomic.3
index a7bb0fbe4a336cb33e3068ae19569c179d9e92a6..6af9721323c20d88776e6a9ae7f0b77923d55123 100644 (file)
 .Nm OSAtomicDecrement32Barrier ,
 .Nm OSAtomicOr32 ,
 .Nm OSAtomicOr32Barrier ,
+.Nm OSAtomicOr32Orig ,
+.Nm OSAtomicOr32OrigBarrier ,
 .Nm OSAtomicAnd32 ,
 .Nm OSAtomicAnd32Barrier ,
+.Nm OSAtomicAnd32Orig ,
+.Nm OSAtomicAnd32OrigBarrier ,
 .Nm OSAtomicXor32 ,
 .Nm OSAtomicXor32Barrier ,
+.Nm OSAtomicXor32Orig ,
+.Nm OSAtomicXor32OrigBarrier ,
 .Nm OSAtomicAdd64 ,
 .Nm OSAtomicAdd64Barrier ,
 .Nm OSAtomicIncrement64 ,
 .Nm OSAtomicIncrement64Barrier ,
 .Nm OSAtomicDecrement64 ,
 .Nm OSAtomicDecrement64Barrier ,
+.Nm OSAtomicCompareAndSwapInt ,
+.Nm OSAtomicCompareAndSwapIntBarrier ,
+.Nm OSAtomicCompareAndSwapLong ,
+.Nm OSAtomicCompareAndSwapLongBarrier ,
+.Nm OSAtomicCompareAndSwapPtr ,
+.Nm OSAtomicCompareAndSwapPtrBarrier ,
 .Nm OSAtomicCompareAndSwap32 ,
 .Nm OSAtomicCompareAndSwap32Barrier ,
 .Nm OSAtomicCompareAndSwap64 ,
 .Nm OSAtomicTestAndSet ,
 .Nm OSAtomicTestAndSetBarrier ,
 .Nm OSAtomicTestAndClear ,
-.Nm OSAtomicTestAndClearBarrier
-.Nd atomic add, increment, decrement, or, and, xor, compare and swap, test and set, and test and clear
+.Nm OSAtomicTestAndClearBarrier ,
+.Nm OSSpinLockTry ,
+.Nm OSSpinLockLock ,
+.Nm OSSpinLockUnlock ,
+.Nm OSAtomicEnqueue ,
+.Nm OSAtomicDequeue
+.Nd atomic add, increment, decrement, or, and, xor, compare and swap, test and set, test and clear, spinlocks, and lockless queues 
 .Sh LIBRARY
 .Lb libc
 .Sh SYNOPSIS
 .In libkern/OSAtomic.h
 .Ft int32_t
-.Fn OSAtomicAdd32 "int32_t theAmount, int32_t *theValue"
+.Fn OSAtomicAdd32 "int32_t theAmount" "volatile int32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicAdd32Barrier "int32_t theAmount, int32_t *theValue"
+.Fn OSAtomicAdd32Barrier "int32_t theAmount" "volatile int32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicIncrement32 "int32_t *theValue"
+.Fn OSAtomicIncrement32 "volatile int32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicIncrement32Barrier "int32_t *theValue"
+.Fn OSAtomicIncrement32Barrier "volatile int32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicDecrement32 "int32_t *theValue"
+.Fn OSAtomicDecrement32 "volatile int32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicDecrement32Barrier "int32_t *theValue"
+.Fn OSAtomicDecrement32Barrier "volatile int32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicOr32 "uint32_t theMask, uint32_t *theValue"
+.Fn OSAtomicOr32 "uint32_t theMask" "volatile uint32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicOr32Barrier "uint32_t theMask, uint32_t *theValue"
+.Fn OSAtomicOr32Barrier "uint32_t theMask" "volatile uint32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicAnd32 "uint32_t theMask, uint32_t *theValue"
+.Fn OSAtomicAnd32 "uint32_t theMask" "volatile uint32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicAnd32Barrier "uint32_t theMask, uint32_t *theValue"
+.Fn OSAtomicAnd32Barrier "uint32_t theMask" "volatile uint32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicXor32 "uint32_t theMask, uint32_t *theValue"
+.Fn OSAtomicXor32 "uint32_t theMask" "volatile uint32_t *theValue"
 .Ft int32_t
-.Fn OSAtomicXor32Barrier "uint32_t theMask, uint32_t *theValue"
+.Fn OSAtomicXor32Barrier "uint32_t theMask" "volatile uint32_t *theValue"
+.Ft int32_t
+.Fn OSAtomicOr32Orig "uint32_t theMask" "volatile uint32_t *theValue"
+.Ft int32_t
+.Fn OSAtomicOr32OrigBarrier "uint32_t theMask" "volatile uint32_t *theValue"
+.Ft int32_t
+.Fn OSAtomicAnd32Orig "uint32_t theMask" "volatile uint32_t *theValue"
+.Ft int32_t
+.Fn OSAtomicAnd32OrigBarrier "uint32_t theMask" "volatile uint32_t *theValue"
+.Ft int32_t
+.Fn OSAtomicXor32Orig "uint32_t theMask" "volatile uint32_t *theValue"
+.Ft int32_t
+.Fn OSAtomicXor32OrigBarrier "uint32_t theMask" "volatile uint32_t *theValue"
 .Ft int64_t
-.Fn OSAtomicAdd64 "int64_t theAmount, int64_t *theValue"
+.Fn OSAtomicAdd64 "int64_t theAmount" "volatile int64_t *theValue"
 .Ft int64_t
-.Fn OSAtomicAdd64Barrier "int64_t theAmount, int64_t *theValue"
+.Fn OSAtomicAdd64Barrier "int64_t theAmount" "volatile int64_t *theValue"
 .Ft int64_t
-.Fn OSAtomicIncrement64 "int64_t *theValue"
+.Fn OSAtomicIncrement64 "volatile int64_t *theValue"
 .Ft int64_t
-.Fn OSAtomicIncrement64Barrier "int64_t *theValue"
+.Fn OSAtomicIncrement64Barrier "volatile int64_t *theValue"
 .Ft int64_t
-.Fn OSAtomicDecrement64 "int64_t *theValue"
+.Fn OSAtomicDecrement64 "volatile int64_t *theValue"
 .Ft int64_t
-.Fn OSAtomicDecrement64Barrier "int64_t *theValue"
+.Fn OSAtomicDecrement64Barrier "volatile int64_t *theValue"
+.Ft bool
+.Fn OSAtomicCompareAndSwapInt "int oldValue" "int newValue" "volatile int *theValue"
+.Ft bool
+.Fn OSAtomicCompareAndSwapIntBarrier "int oldValue" "int newValue" "volatile int *theValue"
+.Ft bool
+.Fn OSAtomicCompareAndSwapLong "long oldValue" "long newValue" "volatile long *theValue"
 .Ft bool
-.Fn OSAtomicCompareAndSwap32 "int32_t oldValue" "int32_t newValue" "int32_t *theValue"
+.Fn OSAtomicCompareAndSwapLongBarrier "long oldValue" "long newValue" "volatile long *theValue"
 .Ft bool
-.Fn OSAtomicCompareAndSwap32Barrier "int32_t oldValue" "int32_t newValue" "int32_t *theValue"
+.Fn OSAtomicCompareAndSwapPtr "void* oldValue" "void* newValue" "void* volatile *theValue"
 .Ft bool
-.Fn OSAtomicCompareAndSwap64 "int64_t oldValue" "int64_t newValue" "int64_t *theValue"
+.Fn OSAtomicCompareAndSwapPtrBarrier "void* oldValue" "void* newValue" "void* volatile *theValue"
 .Ft bool
-.Fn OSAtomicCompareAndSwap64Barrier "int64_t oldValue" "int64_t newValue" "int64_t *theValue"
+.Fn OSAtomicCompareAndSwap32 "int32_t oldValue" "int32_t newValue" "volatile int32_t *theValue"
 .Ft bool
-.Fn OSAtomicTestAndSet "uint32_t n, void *theAddress"
+.Fn OSAtomicCompareAndSwap32Barrier "int32_t oldValue" "int32_t newValue" "volatile int32_t *theValue"
 .Ft bool
-.Fn OSAtomicTestAndSetBarrier "uint32_t n, void *theAddress"
+.Fn OSAtomicCompareAndSwap64 "int64_t oldValue" "int64_t newValue" "volatile int64_t *theValue"
 .Ft bool
-.Fn OSAtomicTestAndClear "uint32_t n, void *theAddress"
+.Fn OSAtomicCompareAndSwap64Barrier "int64_t oldValue" "int64_t newValue" "volatile int64_t *theValue"
 .Ft bool
-.Fn OSAtomicTestAndClearBarrier "uint32_t n, void *theAddress"
+.Fn OSAtomicTestAndSet "uint32_t n" "volatile void *theAddress"
+.Ft bool
+.Fn OSAtomicTestAndSetBarrier "uint32_t n" "volatile void *theAddress"
+.Ft bool
+.Fn OSAtomicTestAndClear "uint32_t n" "volatile void *theAddress"
+.Ft bool
+.Fn OSAtomicTestAndClearBarrier "uint32_t n" "volatile void *theAddress"
+.Ft bool
+.Fn OSSpinLockTry "OSSpinLock *lock"
+.Ft void
+.Fn OSSpinLockLock "OSSpinLock *lock"
+.Ft void
+.Fn OSSpinLockUnlock "OSSpinLock *lock"
+.Ft void
+.Fn OSAtomicEnqueue "OSQueueHead *list" "void *new" "size_t offset"
+.Ft void*
+.Fn OSAtomicDequeue "OSQueueHead *list" "size_t offset"
 .Sh DESCRIPTION
 These functions are thread and multiprocessor safe.  For each function, there
-is a version that does and anoother that does not incorporate a memory barrier.
+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
@@ -97,9 +148,9 @@ On a multiprocessor, the barrier can be quite expensive.
 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()
+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(),
+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
@@ -108,20 +159,24 @@ the barrier variants as they are safer.
 .Pp
 The logical (and, or, xor) and bit test operations are layered on top of the
 .Fn OSAtomicCompareAndSwap
-primitives.
+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,
+.Fn OSAtomicOr32
+) or the original value before the operation (eg,
+.Fn OSAtomicOr32Orig
+).
 .Pp
 The memory address
 .Fa theValue
 must be naturally aligned, ie 32-bit aligned for 32-bit operations and 64-bit
 aligned for 64-bit operations.
 .Pp
-The 64-bit operations are only implemented for
-64-bit processes.
+The 64-bit operations are not implemented for 32-bit processes on PPC platforms.
 .Pp
-.Fn OSAtomicCompareAndSwap32
-and
-.Fn OSAtomicCompareAndSwap64
-compare
+The 
+.Fn OSAtomicCompareAndSwap
+operations compare
 .Fa oldValue
 to
 .Fa *theValue ,
@@ -144,11 +199,48 @@ operate on bit (0x80 >> (
 >> 3)).  They set the named bit to either 1 or 0, respectively.
 .Fa theAddress
 need not be aligned.
+.Pp
+The routines
+.Fn OSAtomicEnqueue
+and
+.Fn 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.
+.Fa offset
+is the offset in bytes to the link field in the queue element.  For example:
+.Bd -literal -offset indent
+       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) );
+       
+.Ed
+In this example, the call of
+.Fn OSAtomicDequeue
+will return a ptr to mary.
 .Sh RETURN VALUES
-The arithmetic and logical operations return the new value, after the operation has been performed.
+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.
 .Sh SEE ALSO
-.Xr atomicqueue 3 ,
 .Xr spinlock 3 ,
 .Xr barrier 3
+.Sh 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).