From ba79566ce9043b30301189cf6205c5e7082ccace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 2 Sep 2014 23:17:14 +0200 Subject: [PATCH] Better atomic support for gcc and clang --- include/ucore/atomic.h | 92 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/include/ucore/atomic.h b/include/ucore/atomic.h index bb9194d..ca5495b 100644 --- a/include/ucore/atomic.h +++ b/include/ucore/atomic.h @@ -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