diff options
author | Stefan Metzmacher <metze@samba.org> | 2018-06-21 14:17:35 +0200 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2018-07-24 17:38:26 +0200 |
commit | 5fa5764f30c47b46f12ceb7637985e8def0190ca (patch) | |
tree | dd339ab817291e511076a07bf86d8e9f4ece65e0 /lib | |
parent | 6f8c1b6736875d63c11f8630ecf1c8d3dcd70fc5 (diff) | |
download | samba-5fa5764f30c47b46f12ceb7637985e8def0190ca.tar.gz |
replace: add checks for atomic_thread_fence(memory_order_seq_cst) and add possible fallbacks
This implements a full memory barrier.
On ubuntu amd64 with results in an 'mfence' instruction.
This is required to syncronization between threads, where
there's typically only one write of a memory that should be
synced between all threads with the barrier.
Much more details can be found here:
https://gcc.gnu.org/onlinedocs/gcc-7.3.0/gcc/_005f_005fatomic-Builtins.html#g_t_005f_005fatomic-Builtins
https://gcc.gnu.org/onlinedocs/gcc-7.3.0/gcc/_005f_005fsync-Builtins.html#g_t_005f_005fsync-Builtins
The main one we use seems to be in C11 via stdatomic.h,
the oldest fallback is __sync_synchronize(), which is available
since 2005 in gcc.
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/replace/system/threads.h | 27 | ||||
-rw-r--r-- | lib/replace/wscript | 19 |
2 files changed, 45 insertions, 1 deletions
diff --git a/lib/replace/system/threads.h b/lib/replace/system/threads.h index fe6d0fbac54..d189ed620c5 100644 --- a/lib/replace/system/threads.h +++ b/lib/replace/system/threads.h @@ -42,4 +42,31 @@ #define pthread_mutex_consistent pthread_mutex_consistent_np #endif +#ifdef HAVE_STDATOMIC_H +#include <stdatomic.h> +#endif + +#ifndef HAVE_ATOMIC_THREAD_FENCE +#ifdef HAVE___ATOMIC_THREAD_FENCE +#define atomic_thread_fence(__ignore_order) __atomic_thread_fence(__ATOMIC_SEQ_CST) +#define HAVE_ATOMIC_THREAD_FENCE 1 +#endif /* HAVE___ATOMIC_THREAD_FENCE */ +#endif /* not HAVE_ATOMIC_THREAD_FENCE */ + +#ifndef HAVE_ATOMIC_THREAD_FENCE +#ifdef HAVE___SYNC_SYNCHRONIZE +#define atomic_thread_fence(__ignore_order) __sync_synchronize() +#define HAVE_ATOMIC_THREAD_FENCE 1 +#endif /* HAVE___SYNC_SYNCHRONIZE */ +#endif /* not HAVE_ATOMIC_THREAD_FENCE */ + +#ifndef HAVE_ATOMIC_THREAD_FENCE +#ifdef HAVE_ATOMIC_THREAD_FENCE_SUPPORT +#error mismatch_error_between_configure_test_and_header +#endif +/* make sure the build fails if someone uses it without checking the define */ +#define atomic_thread_fence(__order) \ + __function__atomic_thread_fence_not_available_on_this_platform__() +#endif /* not HAVE_ATOMIC_THREAD_FENCE */ + #endif diff --git a/lib/replace/wscript b/lib/replace/wscript index 02d98c59e47..5b53461f844 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -113,7 +113,7 @@ def configure(conf): conf.CHECK_HEADERS('sys/extattr.h sys/ea.h sys/proplist.h sys/cdefs.h') conf.CHECK_HEADERS('utmp.h utmpx.h lastlog.h') conf.CHECK_HEADERS('syscall.h sys/syscall.h inttypes.h') - conf.CHECK_HEADERS('sys/atomic.h') + conf.CHECK_HEADERS('sys/atomic.h stdatomic.h') conf.CHECK_HEADERS('libgen.h') if conf.CHECK_CFLAGS('-Wno-format-truncation'): @@ -260,6 +260,23 @@ def configure(conf): headers='stdint.h sys/atomic.h', msg='Checking for atomic_add_32 compiler builtin') + # Check for thread fence. */ + tf = conf.CHECK_CODE('atomic_thread_fence(memory_order_seq_cst);', + 'HAVE_ATOMIC_THREAD_FENCE', + headers='stdatomic.h', + msg='Checking for atomic_thread_fence(memory_order_seq_cst) in stdatomic.h') + if not tf: + tf = conf.CHECK_CODE('__atomic_thread_fence(__ATOMIC_SEQ_CST);', + 'HAVE___ATOMIC_THREAD_FENCE', + msg='Checking for __atomic_thread_fence(__ATOMIC_SEQ_CST)') + if not tf: + # __sync_synchronize() is available since 2005 in gcc. + tf = conf.CHECK_CODE('__sync_synchronize();', + 'HAVE___SYNC_SYNCHRONIZE', + msg='Checking for __sync_synchronize') + if tf: + conf.DEFINE('HAVE_ATOMIC_THREAD_FENCE_SUPPORT', 1) + conf.CHECK_CODE(''' #define FALL_THROUGH __attribute__((fallthrough)) |