139 lines
3.5 KiB
C
139 lines
3.5 KiB
C
#ifndef UC_ATOMIC_H_
|
|
#define UC_ATOMIC_H_
|
|
|
|
/** @file
|
|
* Atomic functions (macros). The ptr argument must be a pointer to
|
|
* an UC_ATOMIC(integer type)
|
|
* For gcc, see http://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/_005f_005fsync-Builtins.html
|
|
*/
|
|
#ifdef DOXYGEN
|
|
|
|
/**
|
|
* 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)
|
|
|
|
/**
|
|
* Atomically add val to *ptr
|
|
* @return *ptr before the addition
|
|
*/
|
|
#define UC_ATOMIC_ADD(ptr, val)
|
|
|
|
/**
|
|
* Atomically decrement *ptr
|
|
* @return *ptr before the decrement
|
|
*/
|
|
#define UC_ATOMIC_DEC(ptr)
|
|
|
|
/**
|
|
* Atomically increment *ptr
|
|
* @return *ptr before the increment
|
|
*/
|
|
#define UC_ATOMIC_INC(ptr)
|
|
|
|
/**
|
|
* Atomically get the value of *ptr
|
|
* @return value of *ptr
|
|
*/
|
|
#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)
|
|
|
|
/** 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()
|
|
|
|
/** 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
|
|
#error "No atomic operations implemented for this compiler"
|
|
#endif
|
|
|
|
|
|
#endif
|