From 601976dede1271acbcae9e43c6f3a287d6c71571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Fri, 28 Apr 2017 11:47:46 +0300 Subject: [PATCH] Use __atomic builtins only where they are supported Use the newer __atomic builtins only with GCC >= 4.7. The older __sync builtins are used elsewhere. --- include/maxscale/atomic.h | 17 ++++++++++++++++ server/core/atomic.cc | 42 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/include/maxscale/atomic.h b/include/maxscale/atomic.h index c5d8c8cc4..bfcd1067d 100644 --- a/include/maxscale/atomic.h +++ b/include/maxscale/atomic.h @@ -20,6 +20,17 @@ MXS_BEGIN_DECLS +/** + * Pre 4.7 GCC doesn't support the __atomic builtin functions. The older __sync + * builtins don't have proper store/load functionality so we use a somewhat ugly + * hack to emulate the store/load. + */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) +#ifndef MXS_USE_ATOMIC_BUILTINS +#define MXS_USE_ATOMIC_BUILTINS 1 +#endif +#endif + /** * Implementation of an atomic add operations for the GCC environment. * @@ -76,7 +87,13 @@ void atomic_store_uint64(uint64_t *variable, uint64_t value); static inline void atomic_synchronize() { #ifdef __GNUC__ + +#ifdef MXS_USE_ATOMIC_BUILTINS + __atomic_thread_fence(__ATOMIC_SEQ_CST); +#else __sync_synchronize(); /* Memory barrier. */ +#endif + #else #error "No GNUC atomics available." #endif diff --git a/server/core/atomic.cc b/server/core/atomic.cc index 549431724..ea9afc819 100644 --- a/server/core/atomic.cc +++ b/server/core/atomic.cc @@ -19,45 +19,81 @@ int atomic_add(int *variable, int value) { +#ifdef MXS_USE_ATOMIC_BUILTINS + return __atomic_add_fetch(variable, value, __ATOMIC_SEQ_CST); +#else return __sync_fetch_and_add(variable, value); +#endif } int64_t atomic_add_int64(int64_t *variable, int64_t value) { +#ifdef MXS_USE_ATOMIC_BUILTINS + return __atomic_add_fetch(variable, value, __ATOMIC_SEQ_CST); +#else return __sync_fetch_and_add(variable, value); +#endif } uint64_t atomic_add_uint64(uint64_t *variable, int64_t value) { +#ifdef MXS_USE_ATOMIC_BUILTINS + return __atomic_add_fetch(variable, value, __ATOMIC_SEQ_CST); +#else return __sync_fetch_and_add(variable, value); +#endif } int atomic_load_int32(int *variable) { +#ifdef MXS_USE_ATOMIC_BUILTINS return __atomic_load_n(variable, __ATOMIC_SEQ_CST); +#else + return __sync_fetch_and_or(variable, 0); +#endif } int64_t atomic_load_int64(int64_t *variable) { +#ifdef MXS_USE_ATOMIC_BUILTINS return __atomic_load_n(variable, __ATOMIC_SEQ_CST); +#else + return __sync_fetch_and_or(variable, 0); +#endif } uint64_t atomic_load_uint64(uint64_t *variable) { +#ifdef MXS_USE_ATOMIC_BUILTINS return __atomic_load_n(variable, __ATOMIC_SEQ_CST); +#else + return __sync_fetch_and_or(variable, 0); +#endif } void atomic_store_int32(int *variable, int value) { - return __atomic_store_n(variable, value, __ATOMIC_SEQ_CST); +#ifdef MXS_USE_ATOMIC_BUILTINS + __atomic_store_n(variable, value, __ATOMIC_SEQ_CST); +#else + __sync_lock_test_and_set(variable, value); +#endif } void atomic_store_int64(int64_t *variable, int64_t value) { - return __atomic_store_n(variable, value, __ATOMIC_SEQ_CST); +#ifdef MXS_USE_ATOMIC_BUILTINS + __atomic_store_n(variable, value, __ATOMIC_SEQ_CST); +#else + __sync_lock_test_and_set(variable, value); +#endif } void atomic_store_uint64(uint64_t *variable, uint64_t value) { - return __atomic_store_n(variable, value, __ATOMIC_SEQ_CST); +#ifdef MXS_USE_ATOMIC_BUILTINS + __atomic_store_n(variable, value, __ATOMIC_SEQ_CST); +#else + __sync_lock_test_and_set(variable, value); +#endif }