Better atomic support for gcc and clang
This commit is contained in:
+82
-10
@@ -3,59 +3,131 @@
|
||||
|
||||
/** @file
|
||||
* Atomic functions (macros). The ptr argument must be a pointer to
|
||||
* an integer type.
|
||||
* an UC_ATOMIC(integer type)
|
||||
* For gcc, see http://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/_005f_005fsync-Builtins.html
|
||||
*/
|
||||
#ifdef DOXYGEN
|
||||
|
||||
#ifdef __GNUC__
|
||||
/**
|
||||
* Define an atomic type.
|
||||
* e.g UC_ATOMIC(int) foo;
|
||||
*/
|
||||
#define UC_ATOMIC(type)
|
||||
|
||||
/**
|
||||
* Atomically subtract val from *ptr
|
||||
* @return *ptr before the subtraction
|
||||
*/
|
||||
#define UC_ATOMIC_SUB(ptr, val) __sync_fetch_and_add((ptr), -(val))
|
||||
#define UC_ATOMIC_SUB(ptr, val)
|
||||
|
||||
/**
|
||||
* Atomically add val to *ptr
|
||||
* @return *ptr before the addition
|
||||
*/
|
||||
#define UC_ATOMIC_ADD(ptr, val) __sync_fetch_and_add((ptr), (val))
|
||||
|
||||
#define UC_ATOMIC_ADD(ptr, val)
|
||||
|
||||
/**
|
||||
* Atomically decrement *ptr
|
||||
* @return *ptr before the decrement
|
||||
*/
|
||||
#define UC_ATOMIC_DEC(ptr) UC_ATOMIC_SUB((ptr), 1)
|
||||
#define UC_ATOMIC_DEC(ptr)
|
||||
|
||||
/**
|
||||
* Atomically increment *ptr
|
||||
* @return *ptr before the increment
|
||||
*/
|
||||
#define UC_ATOMIC_INC(ptr) UC_ATOMIC_ADD((ptr), 1)
|
||||
#define UC_ATOMIC_INC(ptr)
|
||||
|
||||
/**
|
||||
* Atomically get the value of *ptr
|
||||
* @return value of *ptr
|
||||
*/
|
||||
#define UC_ATOMIC_GET(ptr) UC_ATOMIC_ADD((ptr), 0)
|
||||
#define UC_ATOMIC_GET(ptr)
|
||||
|
||||
/**
|
||||
* Atomic Compare-And-Swap. If *ptr is oldval, write newwal to *ptr.
|
||||
* @return *ptr that was before the operation.
|
||||
*/
|
||||
#define UC_ATOMIC_CAS(ptr, oldval, newval) __sync_val_compare_and_swap((ptr), (oldval), (newval))
|
||||
#define UC_ATOMIC_CAS(ptr, oldval, newval)
|
||||
|
||||
/** Issue a full (hardware) memory barrier.
|
||||
* preventing the cpu to move load/stores across
|
||||
* the barrier. (This implies a compiler barrier as well)
|
||||
* */
|
||||
#define UC_MEM_BARRIER() __sync_synchronize()
|
||||
#define UC_MEM_BARRIER()
|
||||
|
||||
/** Issue a full compiler/software only memory barrier
|
||||
* preventing compiler optimization to move load/stores across
|
||||
* the barrier.
|
||||
* */
|
||||
#define UC_COMPILER_BARRIER()
|
||||
|
||||
/* clang with atomic extensions */
|
||||
#elif __clang__
|
||||
|
||||
/* clang defines 0 to be memory_order_relaxed and 5 to be memory_order_seq_cst */
|
||||
#define UC_ORDER_RELAXED 0
|
||||
#define UC_ORDER_CST 5
|
||||
|
||||
#define UC_ATOMIC(type) _Atomic(type)
|
||||
|
||||
#define UC_ATOMIC_SUB(ptr, val) __c11_atomic_fetch_sub((ptr), (val), UC_ORDER_CST)
|
||||
|
||||
#define UC_ATOMIC_ADD(ptr, val) __c11_atomic_fetch_add((ptr), (val), UC_ORDER_CST)
|
||||
|
||||
#define UC_ATOMIC_DEC(ptr) UC_ATOMIC_SUB((ptr), 1)
|
||||
|
||||
#define UC_ATOMIC_INC(ptr) UC_ATOMIC_ADD((ptr), 1)
|
||||
|
||||
#define UC_ATOMIC_GET(ptr) __c11_atomic_load((ptr), UC_ORDER_CST)
|
||||
|
||||
#define UC_ATOMIC_CAS(ptr, oldval, newval) __atomic_compare_exchange((ptr), (oldval), (newval),0, UC_ORDER_CST, UC_ORDER_CST)
|
||||
|
||||
#define UC_MEM_BARRIER() __c11_atomic_thread_fence(UC_ORDER_CST)
|
||||
|
||||
#define UC_COMPILER_BARRIER() __asm__ __volatile__("": : :"memory")
|
||||
|
||||
/* gcc 4.7 or later */
|
||||
#elif __GNUC_ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
|
||||
|
||||
#define UC_ATOMIC(type) type
|
||||
|
||||
#define UC_ATOMIC_SUB(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST)
|
||||
|
||||
#define UC_ATOMIC_ADD(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST)
|
||||
|
||||
#define UC_ATOMIC_DEC(ptr) UC_ATOMIC_SUB((ptr), 1)
|
||||
|
||||
#define UC_ATOMIC_INC(ptr) UC_ATOMIC_ADD((ptr), 1)
|
||||
|
||||
#define UC_ATOMIC_GET(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST)
|
||||
|
||||
#define UC_ATOMIC_CAS(ptr, oldval, newval) __atomic_compare_exchange((ptr), (oldval), (newval),0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define UC_MEM_BARRIER() __atomic_thread_fence(__ATOMIC_SEQ_CST)
|
||||
|
||||
#define UC_COMPILER_BARRIER() __asm__ __volatile__("": : :"memory")
|
||||
|
||||
|
||||
/* Earlier gcc versions */
|
||||
#elif __GNUC__
|
||||
|
||||
#define UC_ATOMIC(type) type
|
||||
|
||||
#define UC_ATOMIC_SUB(ptr, val) __sync_fetch_and_sub((ptr), (val))
|
||||
|
||||
#define UC_ATOMIC_ADD(ptr, val) __sync_fetch_and_add((ptr), (val))
|
||||
|
||||
#define UC_ATOMIC_DEC(ptr) UC_ATOMIC_SUB((ptr), 1)
|
||||
|
||||
#define UC_ATOMIC_INC(ptr) UC_ATOMIC_ADD((ptr), 1)
|
||||
|
||||
#define UC_ATOMIC_GET(ptr) UC_ATOMIC_ADD((ptr), 0)
|
||||
|
||||
#define UC_ATOMIC_CAS(ptr, oldval, newval) __sync_val_compare_and_swap((ptr), (oldval), (newval))
|
||||
|
||||
#define UC_MEM_BARRIER() __sync_synchronize()
|
||||
|
||||
#define UC_COMPILER_BARRIER() __asm__ __volatile__("": : :"memory")
|
||||
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user