/* * Copyright (c) 2004-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef _OSATOMIC_DEPRECATED_H_ #define _OSATOMIC_DEPRECATED_H_ /*! @header * These are deprecated legacy interfaces for atomic operations. * The C11 interfaces in resp. C++11 interfaces in * should be used instead. * * Define OSATOMIC_USE_INLINED=1 to get inline implementations of these * interfaces in terms of the resp. primitives. * This is intended as a transition convenience, direct use of those primitives * is preferred. */ #include #if !(defined(OSATOMIC_USE_INLINED) && OSATOMIC_USE_INLINED) #include #include #include #include #ifndef OSATOMIC_DEPRECATED #define OSATOMIC_DEPRECATED 1 #ifndef __cplusplus #define OSATOMIC_BARRIER_DEPRECATED_MSG(_r) \ "Use " #_r "() from instead" #define OSATOMIC_DEPRECATED_MSG(_r) \ "Use " #_r "_explicit(memory_order_relaxed) from instead" #else #define OSATOMIC_BARRIER_DEPRECATED_MSG(_r) \ "Use std::" #_r "() from instead" #define OSATOMIC_DEPRECATED_MSG(_r) \ "Use std::" #_r "_explicit(std::memory_order_relaxed) from instead" #endif #define OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(_r) \ __OS_AVAILABILITY_MSG(macosx, deprecated=10.12, OSATOMIC_BARRIER_DEPRECATED_MSG(_r)) \ __OS_AVAILABILITY_MSG(ios, deprecated=10.0, OSATOMIC_BARRIER_DEPRECATED_MSG(_r)) \ __OS_AVAILABILITY_MSG(tvos, deprecated=10.0, OSATOMIC_BARRIER_DEPRECATED_MSG(_r)) \ __OS_AVAILABILITY_MSG(watchos, deprecated=3.0, OSATOMIC_BARRIER_DEPRECATED_MSG(_r)) #define OSATOMIC_DEPRECATED_REPLACE_WITH(_r) \ __OS_AVAILABILITY_MSG(macosx, deprecated=10.12, OSATOMIC_DEPRECATED_MSG(_r)) \ __OS_AVAILABILITY_MSG(ios, deprecated=10.0, OSATOMIC_DEPRECATED_MSG(_r)) \ __OS_AVAILABILITY_MSG(tvos, deprecated=10.0, OSATOMIC_DEPRECATED_MSG(_r)) \ __OS_AVAILABILITY_MSG(watchos, deprecated=3.0, OSATOMIC_DEPRECATED_MSG(_r)) #else #undef OSATOMIC_DEPRECATED #define OSATOMIC_DEPRECATED 0 #define OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(_r) #define OSATOMIC_DEPRECATED_REPLACE_WITH(_r) #endif /* * 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 this is not the default alignment of the int64_t type * in the iOS ARMv7 ABI, see * {@link //apple_ref/doc/uid/TP40009021-SW8 iPhoneOSABIReference} * * 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 ARM. 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. * * The barrier operation is typically a no-op on uniprocessor systems and * fully enabled on multiprocessor systems. On some platforms, such as ARM, * the barrier can be quite expensive. * * 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, 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 * {@link OSAtomicIncrement32}. * * If you are unsure which version to use, prefer the barrier variants as they * are safer. * * 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 /*! @typedef OSAtomic_int64_aligned64_t * 64-bit aligned int64_t type. * Use for variables whose addresses are passed to OSAtomic*64() functions to * get the compiler to generate the required alignment. */ #if __has_attribute(aligned) typedef int64_t __attribute__((__aligned__((sizeof(int64_t))))) OSAtomic_int64_aligned64_t; #else typedef int64_t OSAtomic_int64_aligned64_t; #endif /*! @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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_add) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) 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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_add) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) int32_t OSAtomicAdd32Barrier( int32_t __theAmount, volatile int32_t *__theValue ); #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_1 || TARGET_OS_DRIVERKIT /*! @abstract Atomically increments a 32-bit value. @result Returns the new value. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_add) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_1) int32_t OSAtomicIncrement32( volatile int32_t *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_add) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_1) int32_t OSAtomicIncrement32Barrier( volatile int32_t *__theValue ); /*! @abstract Atomically decrements a 32-bit value. @result Returns the new value. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_sub) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_1) int32_t OSAtomicDecrement32( volatile int32_t *__theValue ); /*! @abstract Atomically decrements 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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_sub) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_1) int32_t OSAtomicDecrement32Barrier( volatile int32_t *__theValue ); #else __inline static int32_t OSAtomicIncrement32( volatile int32_t *__theValue ) { return OSAtomicAdd32( 1, __theValue); } __inline static int32_t OSAtomicIncrement32Barrier( volatile int32_t *__theValue ) { return OSAtomicAdd32Barrier( 1, __theValue); } __inline static int32_t OSAtomicDecrement32( volatile int32_t *__theValue ) { return OSAtomicAdd32( -1, __theValue); } __inline static int32_t OSAtomicDecrement32Barrier( volatile int32_t *__theValue ) { return OSAtomicAdd32Barrier( -1, __theValue); } #endif /*! @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. @result Returns the new value. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_add) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) int64_t OSAtomicAdd64( int64_t __theAmount, volatile OSAtomic_int64_aligned64_t *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_add) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_3_2) int64_t OSAtomicAdd64Barrier( int64_t __theAmount, volatile OSAtomic_int64_aligned64_t *__theValue ); #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_1 || TARGET_OS_DRIVERKIT /*! @abstract Atomically increments a 64-bit value. @result Returns the new value. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_add) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_1) int64_t OSAtomicIncrement64( volatile OSAtomic_int64_aligned64_t *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_add) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_1) int64_t OSAtomicIncrement64Barrier( volatile OSAtomic_int64_aligned64_t *__theValue ); /*! @abstract Atomically decrements a 64-bit value. @result Returns the new value. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_sub) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_1) int64_t OSAtomicDecrement64( volatile OSAtomic_int64_aligned64_t *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_sub) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_1) int64_t OSAtomicDecrement64Barrier( volatile OSAtomic_int64_aligned64_t *__theValue ); #else __inline static int64_t OSAtomicIncrement64( volatile OSAtomic_int64_aligned64_t *__theValue ) { return OSAtomicAdd64( 1, __theValue); } __inline static int64_t OSAtomicIncrement64Barrier( volatile OSAtomic_int64_aligned64_t *__theValue ) { return OSAtomicAdd64Barrier( 1, __theValue); } __inline static int64_t OSAtomicDecrement64( volatile OSAtomic_int64_aligned64_t *__theValue ) { return OSAtomicAdd64( -1, __theValue); } __inline static int64_t OSAtomicDecrement64Barrier( volatile OSAtomic_int64_aligned64_t *__theValue ) { return OSAtomicAdd64Barrier( -1, __theValue); } #endif /*! @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 * {@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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_or) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) 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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_or) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) int32_t OSAtomicOr32Barrier( 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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_or) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2) int32_t OSAtomicOr32Orig( uint32_t __theMask, volatile uint32_t *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_or) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2) int32_t OSAtomicOr32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ); /*! @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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_and) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) 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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_and) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) int32_t OSAtomicAnd32Barrier( 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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_and) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2) int32_t OSAtomicAnd32Orig( uint32_t __theMask, volatile uint32_t *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_and) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2) int32_t OSAtomicAnd32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ); /*! @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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_xor) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) 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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_xor) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) int32_t OSAtomicXor32Barrier( 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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_xor) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2) int32_t OSAtomicXor32Orig( uint32_t __theMask, volatile uint32_t *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_xor) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2) int32_t OSAtomicXor32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ); /*! @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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) 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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue ); /*! @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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0) bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0) bool OSAtomicCompareAndSwapPtrBarrier( void *__oldValue, void *__newValue, void * volatile *__theValue ); /*! @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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0) bool OSAtomicCompareAndSwapInt( int __oldValue, int __newValue, volatile int *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0) bool OSAtomicCompareAndSwapIntBarrier( int __oldValue, int __newValue, volatile int *__theValue ); /*! @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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0) bool OSAtomicCompareAndSwapLong( long __oldValue, long __newValue, volatile long *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0) bool OSAtomicCompareAndSwapLongBarrier( long __oldValue, long __newValue, volatile long *__theValue ); /*! @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. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) bool OSAtomicCompareAndSwap64( int64_t __oldValue, int64_t __newValue, volatile OSAtomic_int64_aligned64_t *__theValue ); /*! @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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_3_2) bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile OSAtomic_int64_aligned64_t *__theValue ); /* 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 such that the operation will be performed on bit (0x80 >> (__n & 7)) of byte ((char *)__theAddress + (n >> 3)). For example, if __theAddress points to a 64-bit value, to compare the value of the most significant bit, you would specify 56 for __n. @result Returns the original value of the bit being tested. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_or) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) 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 such that the operation will be performed on bit (0x80 >> (__n & 7)) of byte ((char *)__theAddress + (n >> 3)). For example, if __theAddress points to a 64-bit value, to compare the value of the most significant bit, you would specify 56 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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_or) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) 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 such that the operation will be performed on bit (0x80 >> (__n & 7)) of byte ((char *)__theAddress + (n >> 3)). For example, if __theAddress points to a 64-bit value, to compare the value of the most significant bit, you would specify 56 for __n. @result Returns the original value of the bit being tested. */ OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_fetch_and) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) 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 such that the operation will be performed on bit (0x80 >> (__n & 7)) of byte ((char *)__theAddress + (n >> 3)). For example, if __theAddress points to a 64-bit value, to compare the value of the most significant bit, you would specify 56 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. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_fetch_and) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) bool OSAtomicTestAndClearBarrier( uint32_t __n, volatile void *__theAddress ); /*! @group Memory barriers */ /*! @abstract Memory barrier. @discussion This function serves as both a read and write barrier. */ OSATOMIC_BARRIER_DEPRECATED_REPLACE_WITH(atomic_thread_fence) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0) void OSMemoryBarrier( void ); __END_DECLS #else // defined(OSATOMIC_USE_INLINED) && OSATOMIC_USE_INLINED /* * Inline implementations of the legacy OSAtomic interfaces in terms of * C11 resp. C++11 primitives. * Direct use of those primitives is preferred. */ #include #include #include #include #ifdef __cplusplus extern "C++" { #if !(__has_include() && __has_extension(cxx_atomic)) #error Cannot use inlined OSAtomic without and C++11 atomics #endif #include typedef std::atomic _OSAtomic_uint8_t; typedef std::atomic _OSAtomic_int32_t; typedef std::atomic _OSAtomic_uint32_t; typedef std::atomic _OSAtomic_int64_t; typedef std::atomic _OSAtomic_void_ptr_t; #define OSATOMIC_STD(_a) std::_a __BEGIN_DECLS #else #if !(__has_include() && __has_extension(c_atomic)) #error Cannot use inlined OSAtomic without and C11 atomics #endif #include typedef _Atomic(uint8_t) _OSAtomic_uint8_t; typedef _Atomic(int32_t) _OSAtomic_int32_t; typedef _Atomic(uint32_t) _OSAtomic_uint32_t; typedef _Atomic(int64_t) _OSAtomic_int64_t; typedef _Atomic(void*) _OSAtomic_void_ptr_t; #define OSATOMIC_STD(_a) _a #endif #if __has_extension(c_alignof) && __has_attribute(aligned) typedef int64_t __attribute__((__aligned__(_Alignof(_OSAtomic_int64_t)))) OSAtomic_int64_aligned64_t; #elif __has_attribute(aligned) typedef int64_t __attribute__((__aligned__((sizeof(_OSAtomic_int64_t))))) OSAtomic_int64_aligned64_t; #else typedef int64_t OSAtomic_int64_aligned64_t; #endif #if __has_attribute(always_inline) #define OSATOMIC_INLINE static __inline __attribute__((__always_inline__)) #else #define OSATOMIC_INLINE static __inline #endif OSATOMIC_INLINE int32_t OSAtomicAdd32(int32_t __theAmount, volatile int32_t *__theValue) { return (OSATOMIC_STD(atomic_fetch_add_explicit)( (volatile _OSAtomic_int32_t*) __theValue, __theAmount, OSATOMIC_STD(memory_order_relaxed)) + __theAmount); } OSATOMIC_INLINE int32_t OSAtomicAdd32Barrier(int32_t __theAmount, volatile int32_t *__theValue) { return (OSATOMIC_STD(atomic_fetch_add_explicit)( (volatile _OSAtomic_int32_t*) __theValue, __theAmount, OSATOMIC_STD(memory_order_seq_cst)) + __theAmount); } OSATOMIC_INLINE int32_t OSAtomicIncrement32(volatile int32_t *__theValue) { return OSAtomicAdd32(1, __theValue); } OSATOMIC_INLINE int32_t OSAtomicIncrement32Barrier(volatile int32_t *__theValue) { return OSAtomicAdd32Barrier(1, __theValue); } OSATOMIC_INLINE int32_t OSAtomicDecrement32(volatile int32_t *__theValue) { return OSAtomicAdd32(-1, __theValue); } OSATOMIC_INLINE int32_t OSAtomicDecrement32Barrier(volatile int32_t *__theValue) { return OSAtomicAdd32Barrier(-1, __theValue); } OSATOMIC_INLINE int64_t OSAtomicAdd64(int64_t __theAmount, volatile OSAtomic_int64_aligned64_t *__theValue) { return (OSATOMIC_STD(atomic_fetch_add_explicit)( (volatile _OSAtomic_int64_t*) __theValue, __theAmount, OSATOMIC_STD(memory_order_relaxed)) + __theAmount); } OSATOMIC_INLINE int64_t OSAtomicAdd64Barrier(int64_t __theAmount, volatile OSAtomic_int64_aligned64_t *__theValue) { return (OSATOMIC_STD(atomic_fetch_add_explicit)( (volatile _OSAtomic_int64_t*) __theValue, __theAmount, OSATOMIC_STD(memory_order_seq_cst)) + __theAmount); } OSATOMIC_INLINE int64_t OSAtomicIncrement64(volatile OSAtomic_int64_aligned64_t *__theValue) { return OSAtomicAdd64(1, __theValue); } OSATOMIC_INLINE int64_t OSAtomicIncrement64Barrier(volatile OSAtomic_int64_aligned64_t *__theValue) { return OSAtomicAdd64Barrier(1, __theValue); } OSATOMIC_INLINE int64_t OSAtomicDecrement64(volatile OSAtomic_int64_aligned64_t *__theValue) { return OSAtomicAdd64(-1, __theValue); } OSATOMIC_INLINE int64_t OSAtomicDecrement64Barrier(volatile OSAtomic_int64_aligned64_t *__theValue) { return OSAtomicAdd64Barrier(-1, __theValue); } OSATOMIC_INLINE int32_t OSAtomicOr32(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_or_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_relaxed)) | __theMask); } OSATOMIC_INLINE int32_t OSAtomicOr32Barrier(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_or_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_seq_cst)) | __theMask); } OSATOMIC_INLINE int32_t OSAtomicOr32Orig(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_or_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE int32_t OSAtomicOr32OrigBarrier(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_or_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_seq_cst))); } OSATOMIC_INLINE int32_t OSAtomicAnd32(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_and_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_relaxed)) & __theMask); } OSATOMIC_INLINE int32_t OSAtomicAnd32Barrier(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_and_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_seq_cst)) & __theMask); } OSATOMIC_INLINE int32_t OSAtomicAnd32Orig(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_and_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE int32_t OSAtomicAnd32OrigBarrier(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_and_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_seq_cst))); } OSATOMIC_INLINE int32_t OSAtomicXor32(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_xor_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_relaxed)) ^ __theMask); } OSATOMIC_INLINE int32_t OSAtomicXor32Barrier(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_xor_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_seq_cst)) ^ __theMask); } OSATOMIC_INLINE int32_t OSAtomicXor32Orig(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_xor_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE int32_t OSAtomicXor32OrigBarrier(uint32_t __theMask, volatile uint32_t *__theValue) { return (int32_t)(OSATOMIC_STD(atomic_fetch_xor_explicit)( (volatile _OSAtomic_uint32_t*)__theValue, __theMask, OSATOMIC_STD(memory_order_seq_cst))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwap32(int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile _OSAtomic_int32_t*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_relaxed), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwap32Barrier(int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile _OSAtomic_int32_t*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_seq_cst), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwapPtr(void *__oldValue, void *__newValue, void * volatile *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile _OSAtomic_void_ptr_t*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_relaxed), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwapPtrBarrier(void *__oldValue, void *__newValue, void * volatile *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile _OSAtomic_void_ptr_t*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_seq_cst), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwapInt(int __oldValue, int __newValue, volatile int *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile OSATOMIC_STD(atomic_int)*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_relaxed), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwapIntBarrier(int __oldValue, int __newValue, volatile int *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile OSATOMIC_STD(atomic_int)*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_seq_cst), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwapLong(long __oldValue, long __newValue, volatile long *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile OSATOMIC_STD(atomic_long)*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_relaxed), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwapLongBarrier(long __oldValue, long __newValue, volatile long *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile OSATOMIC_STD(atomic_long)*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_seq_cst), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwap64(int64_t __oldValue, int64_t __newValue, volatile OSAtomic_int64_aligned64_t *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile _OSAtomic_int64_t*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_relaxed), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicCompareAndSwap64Barrier(int64_t __oldValue, int64_t __newValue, volatile OSAtomic_int64_aligned64_t *__theValue) { return (OSATOMIC_STD(atomic_compare_exchange_strong_explicit)( (volatile _OSAtomic_int64_t*)__theValue, &__oldValue, __newValue, OSATOMIC_STD(memory_order_seq_cst), OSATOMIC_STD(memory_order_relaxed))); } OSATOMIC_INLINE bool OSAtomicTestAndSet(uint32_t __n, volatile void *__theAddress) { uintptr_t a = (uintptr_t)__theAddress + (__n >> 3); uint8_t v = (0x80u >> (__n & 7)); return (OSATOMIC_STD(atomic_fetch_or_explicit)((_OSAtomic_uint8_t*)a, v, OSATOMIC_STD(memory_order_relaxed)) & v); } OSATOMIC_INLINE bool OSAtomicTestAndSetBarrier(uint32_t __n, volatile void *__theAddress) { uintptr_t a = (uintptr_t)__theAddress + (__n >> 3); uint8_t v = (0x80u >> (__n & 7)); return (OSATOMIC_STD(atomic_fetch_or_explicit)((_OSAtomic_uint8_t*)a, v, OSATOMIC_STD(memory_order_seq_cst)) & v); } OSATOMIC_INLINE bool OSAtomicTestAndClear(uint32_t __n, volatile void *__theAddress) { uintptr_t a = (uintptr_t)__theAddress + (__n >> 3); uint8_t v = (0x80u >> (__n & 7)); return (OSATOMIC_STD(atomic_fetch_and_explicit)((_OSAtomic_uint8_t*)a, (uint8_t)~v, OSATOMIC_STD(memory_order_relaxed)) & v); } OSATOMIC_INLINE bool OSAtomicTestAndClearBarrier(uint32_t __n, volatile void *__theAddress) { uintptr_t a = (uintptr_t)__theAddress + (__n >> 3); uint8_t v = (0x80u >> (__n & 7)); return (OSATOMIC_STD(atomic_fetch_and_explicit)((_OSAtomic_uint8_t*)a, (uint8_t)~v, OSATOMIC_STD(memory_order_seq_cst)) & v); } OSATOMIC_INLINE void OSMemoryBarrier(void) { OSATOMIC_STD(atomic_thread_fence)(OSATOMIC_STD(memory_order_seq_cst)); } #undef OSATOMIC_INLINE #undef OSATOMIC_STD #ifdef __cplusplus __END_DECLS } // extern "C++" #endif #endif // defined(OSATOMIC_USE_INLINED) && OSATOMIC_USE_INLINED #if TARGET_OS_OSX || TARGET_OS_DRIVERKIT __BEGIN_DECLS /*! @group Lockless atomic fifo enqueue and dequeue * These routines manipulate singly-linked FIFO lists. * * This API is deprecated and no longer recommended */ /*! @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(__LP64__) 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 element 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 element. @param __new The element 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 list, even if different structure types are enqueued on that list. The use of offsetset(), defined in stddef.h is the common way to specify the __offset value. @note This API is deprecated and no longer recommended */ __API_DEPRECATED("No longer supported", macos(10.7, 11.0)) void OSAtomicFifoEnqueue( OSFifoQueueHead *__list, void *__new, size_t __offset); /*! @abstract Dequeue an element from a list. @discussion Memory barriers are incorporated as needed to permit thread-safe access to the queue element. @param __list The list from which you want to dequeue an element. @param __offset The "offset" parameter is the offset (in bytes) of the link field from the beginning of the data structure being dequeued (__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 list, even if different structure types are enqueued on that list. 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. @note This API is deprecated and no longer recommended */ __API_DEPRECATED("No longer supported", macos(10.7, 11.0)) void* OSAtomicFifoDequeue( OSFifoQueueHead *__list, size_t __offset); __END_DECLS #endif /* TARGET_OS_OSX || TARGET_OS_DRIVERKIT */ #endif /* _OSATOMIC_DEPRECATED_H_ */