X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/224c70764cab4e0e39a26aaf3ad3016552f62f55..1f2f436a38f7ae2d39a943ad2898d8fed4ed2e58:/include/libkern/OSAtomic.h diff --git a/include/libkern/OSAtomic.h b/include/libkern/OSAtomic.h index 56be70d..6a62bd3 100644 --- a/include/libkern/OSAtomic.h +++ b/include/libkern/OSAtomic.h @@ -29,160 +29,603 @@ #include #include -/* These are the preferred versions of the atomic and synchronization operations. +#include + +/*! @header + * These are the preferred versions of the atomic and synchronization operations. * Their implementation is customized at boot time for the platform, including * late-breaking errata fixes as necessary. They are thread safe. * - * WARNING: all addresses passed to these functions must be "naturally aligned", ie - * int32_t's must be 32-bit aligned (low 2 bits of address zero), and int64_t's - * must be 64-bit aligned (low 3 bits of address zero.) + * WARNING: all addresses passed to these functions must be "naturally aligned", + * i.e. * int32_t pointers must be 32-bit aligned (low 2 bits of + * address are zeroes), and int64_t pointers must be 64-bit aligned + * (low 3 bits of address are zeroes.) + * + * Note that some versions of the atomic functions incorporate memory barriers + * and some do not. Barriers strictly order memory access on weakly-ordered + * architectures such as PPC. All loads and stores that appear (in sequential + * program order) before the barrier are guaranteed to complete before any + * load or store that appears after the barrier. * - * Note that some versions of the atomic functions incorporate memory barriers, - * and some do not. 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 expensive on some platforms, - * eg PPC. + * On a uniprocessor system, the barrier operation is typically a no-op. On a + * multiprocessor system, the barrier can be quite expensive on some platforms, + * such as PPC. * - * 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 + * Most code should 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(), + * that the initialization is complete, you must use {@link OSAtomicIncrement32Barrier} + * to ensure that the stores to your data structure complete before the atomic + * increment. + * + * Likewise, the consumer of that data structure must use {@link 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 faster to use OSAtomicIncrement32(). + * counter, then it is safe and potentially faster to use {@link OSAtomicIncrement32}. * * If you are unsure which version to use, prefer the barrier variants as they are * safer. * * The spinlock and queue operations always incorporate a barrier. + * + * For the kernel-space version of this header, see + * {@link //apple_ref/doc/header/OSAtomic.h OSAtomic.h (Kernel Framework)} + * + * @apiuid //apple_ref/doc/header/user_space_OSAtomic.h */ __BEGIN_DECLS -/* Arithmetic functions. They return the new value. +/*! @group Arithmetic functions + All functions in this group return the new value. + */ + +/*! @abstract Atomically adds two 32-bit values. + @discussion + This function adds the value given by __theAmount to the + value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + @result Returns the new value. */ int32_t OSAtomicAdd32( int32_t __theAmount, volatile int32_t *__theValue ); + + +/*! @abstract Atomically adds two 32-bit values. + @discussion + This function adds the value given by __theAmount to the + value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + + This function is equivalent to {@link OSAtomicAdd32} + except that it also introduces a barrier. + @result Returns the new value. + */ int32_t OSAtomicAdd32Barrier( int32_t __theAmount, volatile int32_t *__theValue ); -inline static + +/*! @abstract Atomically increments a 32-bit value. + */ +__inline static int32_t OSAtomicIncrement32( volatile int32_t *__theValue ) { return OSAtomicAdd32( 1, __theValue); } -inline static + + +/*! @abstract Atomically increments a 32-bit value with a barrier. + @discussion + This function is equivalent to {@link OSAtomicIncrement32} + except that it also introduces a barrier. + @result Returns the new value. + */ +__inline static int32_t OSAtomicIncrement32Barrier( volatile int32_t *__theValue ) { return OSAtomicAdd32Barrier( 1, __theValue); } -inline static +/*! @abstract Atomically decrements a 32-bit value. */ +__inline static int32_t OSAtomicDecrement32( volatile int32_t *__theValue ) { return OSAtomicAdd32( -1, __theValue); } -inline static + +/*! @abstract Atomically increments a 32-bit value with a barrier. + @discussion + This function is equivalent to {@link OSAtomicDecrement32} + except that it also introduces a barrier. + @result Returns the new value. + */ +__inline static int32_t OSAtomicDecrement32Barrier( volatile int32_t *__theValue ) { return OSAtomicAdd32Barrier( -1, __theValue); } -#if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) +#if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) + +/*! @abstract Atomically adds two 64-bit values. + @discussion + This function adds the value given by __theAmount to the + value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + */ int64_t OSAtomicAdd64( int64_t __theAmount, volatile int64_t *__theValue ); -int64_t OSAtomicAdd64Barrier( int64_t __theAmount, volatile int64_t *__theValue ); -inline static + +/*! @abstract Atomically adds two 64-bit values with a barrier. + @discussion + This function adds the value given by __theAmount to the + value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + + This function is equivalent to {@link OSAtomicAdd64} + except that it also introduces a barrier. + @result Returns the new value. + */ +int64_t OSAtomicAdd64Barrier( int64_t __theAmount, volatile int64_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_3_2); + + +/*! @abstract Atomically increments a 64-bit value. */ +__inline static int64_t OSAtomicIncrement64( volatile int64_t *__theValue ) { return OSAtomicAdd64( 1, __theValue); } -inline static + +/*! @abstract Atomically increments a 64-bit value with a barrier. + @discussion + This function is equivalent to {@link OSAtomicIncrement64} + except that it also introduces a barrier. + @result Returns the new value. + */ +__inline static int64_t OSAtomicIncrement64Barrier( volatile int64_t *__theValue ) { return OSAtomicAdd64Barrier( 1, __theValue); } -inline static + +/*! @abstract Atomically decrements a 64-bit value. + @discussion + This function is equivalent to {@link OSAtomicIncrement64} + except that it also introduces a barrier. + @result Returns the new value. + */ +__inline static int64_t OSAtomicDecrement64( volatile int64_t *__theValue ) { return OSAtomicAdd64( -1, __theValue); } -inline static + + +/*! @abstract Atomically decrements a 64-bit value with a barrier. + @discussion + This function is equivalent to {@link OSAtomicDecrement64} + except that it also introduces a barrier. + @result Returns the new value. + */ +__inline static int64_t OSAtomicDecrement64Barrier( volatile int64_t *__theValue ) { return OSAtomicAdd64Barrier( -1, __theValue); } -#endif /* defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) */ +#endif /* defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) */ -/* Boolean functions (and, or, xor.) These come in four versions for each operation: - * with and without barriers, and returning the old or new value of the operation. - * The "Orig" versions return the original value, ie before the operation, the non-Orig + +/*! @group Boolean functions (AND, OR, XOR) + * + * @discussion Functions in this group come in four variants for each operation: + * with and without barriers, and functions that return the original value or + * the result value of the operation. + * + * The "Orig" versions return the original value, (before the operation); the non-Orig * versions return the value after the operation. All are layered on top of - * compare-and-swap. + * {@link OSAtomicCompareAndSwap32} and similar. + */ + +/*! @abstract Atomic bitwise OR of two 32-bit values. + @discussion + This function performs the bitwise OR of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + @result Returns the new value. */ int32_t OSAtomicOr32( uint32_t __theMask, volatile uint32_t *__theValue ); + + +/*! @abstract Atomic bitwise OR of two 32-bit values with barrier. + @discussion + This function performs the bitwise OR of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + + This function is equivalent to {@link OSAtomicOr32} + except that it also introduces a barrier. + @result Returns the new value. + */ int32_t OSAtomicOr32Barrier( 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 ); + +/*! @abstract Atomic bitwise OR of two 32-bit values returning original. + @discussion + This function performs the bitwise OR of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + @result Returns the original value referenced by __theValue. + */ +int32_t OSAtomicOr32Orig( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); + + +/*! @abstract Atomic bitwise OR of two 32-bit values returning original with barrier. + @discussion + This function performs the bitwise OR of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + + This function is equivalent to {@link OSAtomicOr32Orig} + except that it also introduces a barrier. + @result Returns the original value referenced by __theValue. + */ +int32_t OSAtomicOr32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); + + + + +/*! @abstract Atomic bitwise AND of two 32-bit values. + @discussion + This function performs the bitwise AND of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + @result Returns the new value. + */ int32_t OSAtomicAnd32( uint32_t __theMask, volatile uint32_t *__theValue ); + + +/*! @abstract Atomic bitwise AND of two 32-bit values with barrier. + @discussion + This function performs the bitwise AND of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + + This function is equivalent to {@link OSAtomicAnd32} + except that it also introduces a barrier. + @result Returns the new value. + */ int32_t OSAtomicAnd32Barrier( 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 ); + +/*! @abstract Atomic bitwise AND of two 32-bit values returning original. + @discussion + This function performs the bitwise AND of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + @result Returns the original value referenced by __theValue. + */ +int32_t OSAtomicAnd32Orig( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); + + +/*! @abstract Atomic bitwise AND of two 32-bit values returning original with barrier. + @discussion + This function performs the bitwise AND of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + + This function is equivalent to {@link OSAtomicAnd32Orig} + except that it also introduces a barrier. + @result Returns the original value referenced by __theValue. + */ +int32_t OSAtomicAnd32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); + + + + +/*! @abstract Atomic bitwise XOR of two 32-bit values. + @discussion + This function performs the bitwise XOR of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + @result Returns the new value. + */ int32_t OSAtomicXor32( uint32_t __theMask, volatile uint32_t *__theValue ); + + +/*! @abstract Atomic bitwise XOR of two 32-bit values with barrier. + @discussion + This function performs the bitwise XOR of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + + This function is equivalent to {@link OSAtomicXor32} + except that it also introduces a barrier. + @result Returns the new value. + */ int32_t OSAtomicXor32Barrier( 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 ); + + +/*! @abstract Atomic bitwise XOR of two 32-bit values returning original. + @discussion + This function performs the bitwise XOR of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + @result Returns the original value referenced by __theValue. + */ +int32_t OSAtomicXor32Orig( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); + + +/*! @abstract Atomic bitwise XOR of two 32-bit values returning original with barrier. + @discussion + This function performs the bitwise XOR of the value given by __theMask + with the value in the memory location referenced by __theValue, + storing the result back to that memory location atomically. + + This function is equivalent to {@link OSAtomicXor32Orig} + except that it also introduces a barrier. + @result Returns the original value referenced by __theValue. + */ +int32_t OSAtomicXor32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2); -/* Compare and swap. They return true if the swap occured. There are several versions, - * depending on data type and whether or not a barrier is used. +/*! @group Compare and swap + * Functions in this group return true if the swap occured. There are several versions, + * depending on data type and on whether or not a barrier is used. + */ + + +/*! @abstract Compare and swap for 32-bit values. + @discussion + This function compares the value in __oldValue to the value + in the memory location referenced by __theValue. If the values + match, this function stores the value from __newValue into + that memory location atomically. + @result Returns TRUE on a match, FALSE otherwise. */ bool OSAtomicCompareAndSwap32( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue ); + + +/*! @abstract Compare and swap for 32-bit values with barrier. + @discussion + This function compares the value in __oldValue to the value + in the memory location referenced by __theValue. If the values + match, this function stores the value from __newValue into + that memory location atomically. + + This function is equivalent to {@link OSAtomicCompareAndSwap32} + except that it also introduces a barrier. + @result Returns TRUE on a match, FALSE otherwise. + */ bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue ); -bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue ); -bool OSAtomicCompareAndSwapPtrBarrier( void *__oldValue, void *__newValue, void * volatile *__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 ); -#if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) +/*! @abstract Compare and swap pointers. + @discussion + This function compares the pointer stored in __oldValue to the pointer + in the memory location referenced by __theValue. If the pointers + match, this function stores the pointer from __newValue into + that memory location atomically. + @result Returns TRUE on a match, FALSE otherwise. + */ +bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); + + +/*! @abstract Compare and swap pointers with barrier. + @discussion + This function compares the pointer stored in __oldValue to the pointer + in the memory location referenced by __theValue. If the pointers + match, this function stores the pointer from __newValue into + that memory location atomically. + + This function is equivalent to {@link OSAtomicCompareAndSwapPtr} + except that it also introduces a barrier. + @result Returns TRUE on a match, FALSE otherwise. + */ +bool OSAtomicCompareAndSwapPtrBarrier( void *__oldValue, void *__newValue, void * volatile *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); + + +/*! @abstract Compare and swap for int values. + @discussion + This function compares the value in __oldValue to the value + in the memory location referenced by __theValue. If the values + match, this function stores the value from __newValue into + that memory location atomically. + + This function is equivalent to {@link OSAtomicCompareAndSwap32}. + @result Returns TRUE on a match, FALSE otherwise. + */ +bool OSAtomicCompareAndSwapInt( int __oldValue, int __newValue, volatile int *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); + + +/*! @abstract Compare and swap for int values. + @discussion + This function compares the value in __oldValue to the value + in the memory location referenced by __theValue. If the values + match, this function stores the value from __newValue into + that memory location atomically. + + This function is equivalent to {@link OSAtomicCompareAndSwapInt} + except that it also introduces a barrier. + + This function is equivalent to {@link OSAtomicCompareAndSwap32Barrier}. + @result Returns TRUE on a match, FALSE otherwise. + */ +bool OSAtomicCompareAndSwapIntBarrier( int __oldValue, int __newValue, volatile int *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); + + +/*! @abstract Compare and swap for long values. + @discussion + This function compares the value in __oldValue to the value + in the memory location referenced by __theValue. If the values + match, this function stores the value from __newValue into + that memory location atomically. + + This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures, + or {@link OSAtomicCompareAndSwap64} on 64-bit architectures. + @result Returns TRUE on a match, FALSE otherwise. + */ +bool OSAtomicCompareAndSwapLong( long __oldValue, long __newValue, volatile long *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); + + +/*! @abstract Compare and swap for long values. + @discussion + This function compares the value in __oldValue to the value + in the memory location referenced by __theValue. If the values + match, this function stores the value from __newValue into + that memory location atomically. + + This function is equivalent to {@link OSAtomicCompareAndSwapLong} + except that it also introduces a barrier. + + This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures, + or {@link OSAtomicCompareAndSwap64} on 64-bit architectures. + @result Returns TRUE on a match, FALSE otherwise. + */ +bool OSAtomicCompareAndSwapLongBarrier( long __oldValue, long __newValue, volatile long *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); + + +#if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) + +/*! @abstract Compare and swap for uint64_t values. + @discussion + This function compares the value in __oldValue to the value + in the memory location referenced by __theValue. If the values + match, this function stores the value from __newValue into + that memory location atomically. + @result Returns TRUE on a match, FALSE otherwise. + */ bool OSAtomicCompareAndSwap64( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue ); -bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue ); -#endif /* defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) */ + +/*! @abstract Compare and swap for uint64_t values. + @discussion + This function compares the value in __oldValue to the value + in the memory location referenced by __theValue. If the values + match, this function stores the value from __newValue into + that memory location atomically. + + This function is equivalent to {@link OSAtomicCompareAndSwap64} + except that it also introduces a barrier. + @result Returns TRUE on a match, FALSE otherwise. + */ +bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_3_2); + +#endif /* defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) */ /* Test and set. They return the original value of the bit, and operate on bit (0x80>>(n&7)) * in byte ((char*)theAddress + (n>>3)). */ +/*! @abstract Atomic test and set + @discussion + This function tests a bit in the value referenced by __theAddress + and if it is not set, sets it. The bit is chosen by the value of __n. + The bits are numbered in order beginning with bit 1 as the lowest order bit. + + For example, if __theAddress points to a 64-bit value, + to compare the value of the highest bit, you would specify 64 for + __n. + @result + Returns the original value of the bit being tested. + */ bool OSAtomicTestAndSet( uint32_t __n, volatile void *__theAddress ); + + +/*! @abstract Atomic test and set with barrier + @discussion + This function tests a bit in the value referenced by __theAddress + and if it is not set, sets it. The bit is chosen by the value of __n. + The bits are numbered in order beginning with bit 1 as the lowest order bit. + + For example, if __theAddress points to a 64-bit value, + to compare the value of the highest bit, you would specify 64 for + __n. + + This function is equivalent to {@link OSAtomicTestAndSet} + except that it also introduces a barrier. + @result + Returns the original value of the bit being tested. + */ + bool OSAtomicTestAndSetBarrier( uint32_t __n, volatile void *__theAddress ); + + + +/*! @abstract Atomic test and clear + @discussion + This function tests a bit in the value referenced by __theAddress + and if it is not cleared, clears it. The bit is chosen by the value of __n. + The bits are numbered in order beginning with bit 1 as the lowest order bit. + + For example, if __theAddress points to a 64-bit value, + to compare the value of the highest bit, you would specify 64 for + __n. + @result + Returns the original value of the bit being tested. + */ bool OSAtomicTestAndClear( uint32_t __n, volatile void *__theAddress ); + + +/*! @abstract Atomic test and clear + @discussion + This function tests a bit in the value referenced by __theAddress + and if it is not cleared, clears it. The bit is chosen by the value of __n. + The bits are numbered in order beginning with bit 1 as the lowest order bit. + + For example, if __theAddress points to a 64-bit value, + to compare the value of the highest bit, you would specify 64 for + __n. + + This function is equivalent to {@link OSAtomicTestAndSet} + except that it also introduces a barrier. + @result + Returns the original value of the bit being tested. + */ bool OSAtomicTestAndClearBarrier( uint32_t __n, volatile void *__theAddress ); -/* Spinlocks. These use memory barriers as required to synchronize access to shared - * memory protected by the lock. The lock operation spins, but employs various strategies - * to back off if the lock is held, making it immune to most priority-inversion livelocks. - * The try operation immediately returns false if the lock was held, true if it took the - * lock. The convention is that unlocked is zero, locked is nonzero. +/*! @group Spinlocks + * These spinlocks use memory barriers as required to synchronize access to shared + * memory protected by the lock. + */ + +/*! @abstract The default value for an OSSpinLock. + @discussion + The convention is that unlocked is zero, locked is nonzero. */ #define OS_SPINLOCK_INIT 0 + +/*! @abstract Data type for a spinlock. + @discussion + You should always initialize a spinlock to {@link OS_SPINLOCK_INIT} before + using it. + */ typedef int32_t OSSpinLock; + +/*! @abstract Locks a spinlock if it would not block + @result + Returns false if the lock was already held by another thread, + true if it took the lock successfully. + */ bool OSSpinLockTry( volatile OSSpinLock *__lock ); + + +/*! @abstract Locks a spinlock + @discussion + Although the lock operation spins, it employs various strategies + to back off if the lock is held, making it immune to most priority-inversion + livelocks. + */ void OSSpinLockLock( volatile OSSpinLock *__lock ); + + +/*! @abstract Unlocks a spinlock */ void OSSpinLockUnlock( volatile OSSpinLock *__lock ); -/* Lockless atomic enqueue and dequeue. These routines manipulate singly - * linked LIFO lists. Ie, a dequeue will return the most recently enqueued - * element, or NULL if the list is empty. The "offset" parameter is the offset - * in bytes of the link field within the data structure being queued. The - * link field should be a pointer type. Memory barriers are incorporated as - * needed to permit thread-safe access to the queue element. +/*! @group Lockless atomic enqueue and dequeue + * These routines manipulate singly-linked LIFO lists. + */ + +/*! @abstract The data structure for a queue head. + @discussion + You should always initialize a queue head structure with the + initialization vector {@link OS_ATOMIC_QUEUE_INIT} before use. */ #if defined(__x86_64__) typedef volatile struct { void *opaque1; long opaque2; -} OSQueueHead __attribute__ ((aligned (16))); +} __attribute__ ((aligned (16))) OSQueueHead; #else @@ -193,16 +636,133 @@ typedef volatile struct { #endif +/*! @abstract The initialization vector for a queue head. */ #define OS_ATOMIC_QUEUE_INIT { NULL, 0 } -void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset); -void* OSAtomicDequeue( OSQueueHead *__list, size_t __offset); +/*! @abstract Enqueue an item onto a list. + @discussion + Memory barriers are incorporated as needed to permit thread-safe access + to the queue element. + @param __list + The list on which you want to enqueue the item. + @param __new + The item to add. + @param __offset + The "offset" parameter is the offset (in bytes) of the link field + from the beginning of the data structure being queued (__new). + The link field should be a pointer type. + The __offset value needs to be same for all enqueuing and + dequeuing operations on the same queue, even if different structure types + are enqueued on that queue. The use of offsetset(), defined in + stddef.h is the common way to specify the __offset + value. + */ +void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_4_0); + + +/*! @abstract Dequeue an item from a list. + @discussion + Memory barriers are incorporated as needed to permit thread-safe access + to the queue element. + @param __list + The list on which you want to enqueue the item. + @param __offset + The "offset" parameter is the offset (in bytes) of the link field + from the beginning of the data structure being queued (__new). + The link field should be a pointer type. + The __offset value needs to be same for all enqueuing and + dequeuing operations on the same queue, even if different structure types + are enqueued on that queue. The use of offsetset(), defined in + stddef.h is the common way to specify the __offset + value. + @result + Returns the most recently enqueued element, or NULL if the + list is empty. + */ +void* OSAtomicDequeue( OSQueueHead *__list, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_4_0); +#if defined(__x86_64__) || defined(__i386__) -/* Memory barrier. It is both a read and write barrier. +/*! @group Lockless atomic fifo enqueue and dequeue + * These routines manipulate singly-linked FIFO lists. */ -void OSMemoryBarrier( void ); +/*! @abstract The data structure for a fifo queue head. + @discussion + You should always initialize a fifo queue head structure with the + initialization vector {@link OS_ATOMIC_FIFO_QUEUE_INIT} before use. + */ +#if defined(__x86_64__) + +typedef volatile struct { + void *opaque1; + void *opaque2; + int opaque3; +} __attribute__ ((aligned (16))) OSFifoQueueHead; + +#else + +typedef volatile struct { + void *opaque1; + void *opaque2; + int opaque3; +} OSFifoQueueHead; + +#endif + +/*! @abstract The initialization vector for a fifo queue head. */ +#define OS_ATOMIC_FIFO_QUEUE_INIT { NULL, NULL, 0 } + +/*! @abstract Enqueue an item onto a list. + @discussion + Memory barriers are incorporated as needed to permit thread-safe access + to the queue element. + @param __list + The list on which you want to enqueue the item. + @param __new + The item to add. + @param __offset + The "offset" parameter is the offset (in bytes) of the link field + from the beginning of the data structure being queued (__new). + The link field should be a pointer type. + The __offset value needs to be same for all enqueuing and + dequeuing operations on the same queue, even if different structure types + are enqueued on that queue. The use of offsetset(), defined in + stddef.h is the common way to specify the __offset + value. + */ +void OSAtomicFifoEnqueue( OSFifoQueueHead *__list, void *__new, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! @abstract Dequeue an item from a list. + @discussion + Memory barriers are incorporated as needed to permit thread-safe access + to the queue element. + @param __list + The list on which you want to enqueue the item. + @param __offset + The "offset" parameter is the offset (in bytes) of the link field + from the beginning of the data structure being queued (__new). + The link field should be a pointer type. + The __offset value needs to be same for all enqueuing and + dequeuing operations on the same queue, even if different structure types + are enqueued on that queue. The use of offsetset(), defined in + stddef.h is the common way to specify the __offset + value. + @result + Returns the oldest enqueued element, or NULL if the + list is empty. + */ +void* OSAtomicFifoDequeue( OSFifoQueueHead *__list, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +#endif /* __i386__ || __x86_64__ */ + +/*! @group Memory barriers */ + +/*! @abstract Memory barrier. + @discussion + This function serves as both a read and write barrier. + */ +void OSMemoryBarrier( void ); __END_DECLS