mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-09 23:29:03 +00:00
Prior to this change we would assume the ABI for Apple targets to be GNU which could result in subtle errors in LLVM emitting calls to non-existent system libc provided functions such as `_sincosf` which is a GNU extension and as such is not provided by macOS for example. This would result in linker errors where the linker would not be able to find the said symbol in `libSystem.tbd`. With this change, we now correctly identify macOS (and other Apple platforms) as having ABI `unknown` which translates to unspecified in LLVM under-the-hood: ``` // main.ll target triple = "aarch64-unknown-macos-unknown" ``` Note however that we never suffix the target OS with target version such as `macos11` or `macos12` which means we fail to instruct LLVM of potential optimisations provided by the OS such as the availability of function `___sincosf_stret`. I suggest we investigate that in a follow-up commit.
1266 lines
No EOL
45 KiB
C++
Vendored
1266 lines
No EOL
45 KiB
C++
Vendored
/*
|
|
* 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 <stdatomic.h> resp. C++11 interfaces in <atomic>
|
|
* should be used instead.
|
|
*
|
|
* Define OSATOMIC_USE_INLINED=1 to get inline implementations of these
|
|
* interfaces in terms of the <stdatomic.h> resp. <atomic> primitives.
|
|
* This is intended as a transition convenience, direct use of those primitives
|
|
* is preferred.
|
|
*/
|
|
|
|
#include <Availability.h>
|
|
|
|
#if !(defined(OSATOMIC_USE_INLINED) && OSATOMIC_USE_INLINED)
|
|
|
|
#include <sys/cdefs.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#ifndef OSATOMIC_DEPRECATED
|
|
#define OSATOMIC_DEPRECATED 1
|
|
#ifndef __cplusplus
|
|
#define OSATOMIC_BARRIER_DEPRECATED_MSG(_r) \
|
|
"Use " #_r "() from <stdatomic.h> instead"
|
|
#define OSATOMIC_DEPRECATED_MSG(_r) \
|
|
"Use " #_r "_explicit(memory_order_relaxed) from <stdatomic.h> instead"
|
|
#else
|
|
#define OSATOMIC_BARRIER_DEPRECATED_MSG(_r) \
|
|
"Use std::" #_r "() from <atomic> instead"
|
|
#define OSATOMIC_DEPRECATED_MSG(_r) \
|
|
"Use std::" #_r "_explicit(std::memory_order_relaxed) from <atomic> 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. <code>int32_t</code> pointers must be 32-bit aligned (low 2 bits of
|
|
* address are zeroes), and <code>int64_t</code> pointers must be 64-bit
|
|
* aligned (low 3 bits of address are zeroes.).
|
|
* Note that this is not the default alignment of the <code>int64_t</code> 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 <code>int64_t</code> 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 <code>__theAmount</code> to the
|
|
value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theAmount</code> to the
|
|
value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theAmount</code> to the
|
|
value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theAmount</code> to the
|
|
value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
storing the result back to that memory location atomically.
|
|
@result Returns the original value referenced by <code>__theValue</code>.
|
|
*/
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theValue</code>.
|
|
*/
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
storing the result back to that memory location atomically.
|
|
@result Returns the original value referenced by <code>__theValue</code>.
|
|
*/
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theValue</code>.
|
|
*/
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
storing the result back to that memory location atomically.
|
|
@result Returns the original value referenced by <code>__theValue</code>.
|
|
*/
|
|
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 <code>__theMask</code>
|
|
with the value in the memory location referenced by <code>__theValue</code>,
|
|
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 <code>__theValue</code>.
|
|
*/
|
|
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 <code>__oldValue</code> to the value
|
|
in the memory location referenced by <code>__theValue</code>. If the values
|
|
match, this function stores the value from <code>__newValue</code> 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 <code>__oldValue</code> to the value
|
|
in the memory location referenced by <code>__theValue</code>. If the values
|
|
match, this function stores the value from <code>__newValue</code> 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 <code>__oldValue</code> to the pointer
|
|
in the memory location referenced by <code>__theValue</code>. If the pointers
|
|
match, this function stores the pointer from <code>__newValue</code> 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 <code>__oldValue</code> to the pointer
|
|
in the memory location referenced by <code>__theValue</code>. If the pointers
|
|
match, this function stores the pointer from <code>__newValue</code> 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 <code>int</code> values.
|
|
@discussion
|
|
This function compares the value in <code>__oldValue</code> to the value
|
|
in the memory location referenced by <code>__theValue</code>. If the values
|
|
match, this function stores the value from <code>__newValue</code> 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 <code>int</code> values.
|
|
@discussion
|
|
This function compares the value in <code>__oldValue</code> to the value
|
|
in the memory location referenced by <code>__theValue</code>. If the values
|
|
match, this function stores the value from <code>__newValue</code> 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 <code>long</code> values.
|
|
@discussion
|
|
This function compares the value in <code>__oldValue</code> to the value
|
|
in the memory location referenced by <code>__theValue</code>. If the values
|
|
match, this function stores the value from <code>__newValue</code> 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 <code>long</code> values.
|
|
@discussion
|
|
This function compares the value in <code>__oldValue</code> to the value
|
|
in the memory location referenced by <code>__theValue</code>. If the values
|
|
match, this function stores the value from <code>__newValue</code> 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 <code>uint64_t</code> values.
|
|
@discussion
|
|
This function compares the value in <code>__oldValue</code> to the value
|
|
in the memory location referenced by <code>__theValue</code>. If the values
|
|
match, this function stores the value from <code>__newValue</code> 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 <code>uint64_t</code> values.
|
|
@discussion
|
|
This function compares the value in <code>__oldValue</code> to the value
|
|
in the memory location referenced by <code>__theValue</code>. If the values
|
|
match, this function stores the value from <code>__newValue</code> 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
|
|
<code>__theAddress</code> and if it is not set, sets it.
|
|
|
|
The bit is chosen by the value of <code>__n</code> such that the
|
|
operation will be performed on bit <code>(0x80 >> (__n & 7))</code>
|
|
of byte <code>((char *)__theAddress + (n >> 3))</code>.
|
|
|
|
For example, if <code>__theAddress</code> points to a 64-bit value,
|
|
to compare the value of the most significant bit, you would specify
|
|
<code>56</code> for <code>__n</code>.
|
|
@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 <code>__theAddress</code>
|
|
and if it is not set, sets it.
|
|
|
|
The bit is chosen by the value of <code>__n</code> such that the
|
|
operation will be performed on bit <code>(0x80 >> (__n & 7))</code>
|
|
of byte <code>((char *)__theAddress + (n >> 3))</code>.
|
|
|
|
For example, if <code>__theAddress</code> points to a 64-bit value,
|
|
to compare the value of the most significant bit, you would specify
|
|
<code>56</code> for <code>__n</code>.
|
|
|
|
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 <code>__theAddress</code>
|
|
and if it is not cleared, clears it.
|
|
|
|
The bit is chosen by the value of <code>__n</code> such that the
|
|
operation will be performed on bit <code>(0x80 >> (__n & 7))</code>
|
|
of byte <code>((char *)__theAddress + (n >> 3))</code>.
|
|
|
|
For example, if <code>__theAddress</code> points to a 64-bit value,
|
|
to compare the value of the most significant bit, you would specify
|
|
<code>56</code> for <code>__n</code>.
|
|
|
|
@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 <code>__theAddress</code>
|
|
and if it is not cleared, clears it.
|
|
|
|
The bit is chosen by the value of <code>__n</code> such that the
|
|
operation will be performed on bit <code>(0x80 >> (__n & 7))</code>
|
|
of byte <code>((char *)__theAddress + (n >> 3))</code>.
|
|
|
|
For example, if <code>__theAddress</code> points to a 64-bit value,
|
|
to compare the value of the most significant bit, you would specify
|
|
<code>56</code> for <code>__n</code>.
|
|
|
|
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 <stdatomic.h> resp. C++11 <atomic> primitives.
|
|
* Direct use of those primitives is preferred.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C++" {
|
|
#if !(__has_include(<atomic>) && __has_extension(cxx_atomic))
|
|
#error Cannot use inlined OSAtomic without <atomic> and C++11 atomics
|
|
#endif
|
|
#include <atomic>
|
|
typedef std::atomic<uint8_t> _OSAtomic_uint8_t;
|
|
typedef std::atomic<int32_t> _OSAtomic_int32_t;
|
|
typedef std::atomic<uint32_t> _OSAtomic_uint32_t;
|
|
typedef std::atomic<int64_t> _OSAtomic_int64_t;
|
|
typedef std::atomic<void*> _OSAtomic_void_ptr_t;
|
|
#define OSATOMIC_STD(_a) std::_a
|
|
__BEGIN_DECLS
|
|
#else
|
|
#if !(__has_include(<stdatomic.h>) && __has_extension(c_atomic))
|
|
#error Cannot use inlined OSAtomic without <stdatomic.h> and C11 atomics
|
|
#endif
|
|
#include <stdatomic.h>
|
|
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 (<code>__new</code>).
|
|
The link field should be a pointer type.
|
|
The <code>__offset</code> 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 <code>offsetset()</code>, defined in
|
|
<code>stddef.h</code> is the common way to specify the <code>__offset</code>
|
|
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 (<code>__new</code>).
|
|
The link field should be a pointer type.
|
|
The <code>__offset</code> 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 <code>offsetset()</code>, defined in
|
|
<code>stddef.h</code> is the common way to specify the <code>__offset</code>
|
|
value.
|
|
@result
|
|
Returns the oldest enqueued element, or <code>NULL</code> 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_ */ |