#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