The following built-in functions approximately match the requirements for C++11 memory model. Many are similar to the ‘__sync’ prefixed built-in functions, but all also have a memory model parameter. These are all identified by being prefixed with ‘__atomic’, and most are overloaded such that they work with multiple types.
GCC will allow any integral scalar or pointer type that is 1, 2, 4, or 8 bytes in length. 16-byte integral types are also allowed if ‘__int128’ (see __int128) is supported by the architecture.
Target architectures are encouraged to provide their own patterns for each of these built-in functions. If no target is provided, the original non-memory model set of ‘__sync’ atomic built-in functions will be utilized, along with any required synchronization fences surrounding it in order to achieve the proper behaviour. Execution in this case is subject to the same restrictions as those built-in functions.
If there is no pattern or mechanism to provide a lock free instruction sequence, a call is made to an external routine with the same parameters to be resolved at runtime.
The four non-arithmetic functions (load, store, exchange, and compare_exchange) all have a generic version as well. This generic version will work on any data type. If the data type size maps to one of the integral sizes which may have lock free support, the generic version will utilize the lock free built-in function. Otherwise an external call is left to be resolved at runtime. This external call will be the same format with the addition of a ‘size_t’ parameter inserted as the first parameter indicating the size of the object being pointed to. All objects must be the same size.
There are 6 different memory models which can be specified. These map to the same names in the C++11 standard. Refer there or to the GCC wiki on atomic synchronization for more detailed definitions. These memory models integrate both barriers to code motion as well as synchronization requirements with other threads. These are listed in approximately ascending order of strength.
__ATOMIC_RELAXED
__ATOMIC_CONSUME
__ATOMIC_ACQUIRE
__ATOMIC_RELEASE
__ATOMIC_ACQ_REL
__ATOMIC_SEQ_CST
When implementing patterns for these built-in functions , the memory model
parameter can be ignored as long as the pattern implements the most
restrictive __ATOMIC_SEQ_CST
model. Any of the other memory models
will execute correctly with this memory model but they may not execute as
efficiently as they could with a more appropriate implemention of the
relaxed requirements.
Note that the C++11 standard allows for the memory model parameter to be
determined at runtime rather than at compile time. These built-in
functions will map any runtime value to __ATOMIC_SEQ_CST
rather
than invoke a runtime library call or inline a switch statement. This is
standard compliant, safe, and the simplest approach for now.
The memory model parameter is a signed int, but only the lower 8 bits are reserved for the memory model. The remainder of the signed int is reserved for future use and should be 0. Use of the predefined atomic values will ensure proper usage.
This built-in function implements an atomic load operation. It returns the contents of
*
ptr.The valid memory model variants are
__ATOMIC_RELAXED
,__ATOMIC_SEQ_CST
,__ATOMIC_ACQUIRE
, and__ATOMIC_CONSUME
.
This is the generic version of an atomic load. It will return the contents of
*
ptr in*
ret.
This built-in function implements an atomic store operation. It writes val into
*
ptr.The valid memory model variants are
__ATOMIC_RELAXED
,__ATOMIC_SEQ_CST
, and__ATOMIC_RELEASE
.
This is the generic version of an atomic store. It will store the value of
*
val into*
ptr.
This built-in function implements an atomic exchange operation. It writes val into
*
ptr, and returns the previous contents of*
ptr.The valid memory model variants are
__ATOMIC_RELAXED
,__ATOMIC_SEQ_CST
,__ATOMIC_ACQUIRE
,__ATOMIC_RELEASE
, and__ATOMIC_ACQ_REL
.
This is the generic version of an atomic exchange. It will store the contents of
*
val into*
ptr. The original value of*
ptr will be copied into*
ret.
This built-in function implements an atomic compare and exchange operation. This compares the contents of
*
ptr with the contents of*
expected and if equal, writes desired into*
ptr. If they are not equal, the current contents of*
ptr is written into*
expected. weak is true for weak compare_exchange, and false for the strong variation. Many targets only offer the strong variation and ignore the parameter. When in doubt, use the strong variation.True is returned if desired is written into
*
ptr and the execution is considered to conform to the memory model specified by success_memmodel. There are no restrictions on what memory model can be used here.False is returned otherwise, and the execution is considered to conform to failure_memmodel. This memory model cannot be
__ATOMIC_RELEASE
nor__ATOMIC_ACQ_REL
. It also cannot be a stronger model than that specified by success_memmodel.
This built-in function implements the generic version of
__atomic_compare_exchange
. The function is virtually identical to__atomic_compare_exchange_n
, except the desired value is also a pointer.
These built-in functions perform the operation suggested by the name, and return the result of the operation. That is,
{ *ptr op= val; return *ptr; }All memory models are valid.
These built-in functions perform the operation suggested by the name, and return the value that had previously been in
*
ptr. That is,{ tmp = *ptr; *ptr op= val; return tmp; }All memory models are valid.
This built-in function performs an atomic test-and-set operation on the byte at
*
ptr. The byte is set to some implementation defined non-zero "set" value and the return value istrue
if and only if the previous contents were "set".All memory models are valid.
This built-in function performs an atomic clear operation on
*
ptr. After the operation,*
ptr will contain 0.The valid memory model variants are
__ATOMIC_RELAXED
,__ATOMIC_SEQ_CST
, and__ATOMIC_RELEASE
.
This built-in function acts as a synchronization fence between threads based on the specified memory model.
All memory orders are valid.
This built-in function acts as a synchronization fence between a thread and signal handlers based in the same thread.
All memory orders are valid.
This built-in function returns true if objects of size bytes will always generate lock free atomic instructions for the target architecture. size must resolve to a compile time constant and the result also resolves to compile time constant.
ptr is an optional pointer to the object which may be used to determine alignment. A value of 0 indicates typical alignment should be used. The compiler may also ignore this parameter.
if (_atomic_always_lock_free (sizeof (long long), 0))
This built-in function returns true if objects of size bytes will always generate lock free atomic instructions for the target architecture. If it is not known to be lock free a call is made to a runtime routine named
__atomic_is_lock_free
.ptr is an optional pointer to the object which may be used to determine alignment. A value of 0 indicates typical alignment should be used. The compiler may also ignore this parameter.