Files
libucore/include/ucore/atomic.h
T
2014-09-12 01:11:41 +02:00

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