Add support for C11 stdatomic atomics
This fixes deprecation warnings when building for macOS >= 10.12 systems. Additionally, using stdatomic.h (or the more modern __atomic_ builtins) is required when targeting CHERI-enabled architectures such as CHERI-RISC-V or Arm's Morello since the compiler rejects __sync_* atomic for pointer types (they only work with integers).
This commit is contained in:
parent
ab4761ff87
commit
012ffaac75
16
configure.ac
16
configure.ac
|
@ -663,6 +663,22 @@ dnl ===========================================================================
|
||||||
# Thread-safety primitives
|
# Thread-safety primitives
|
||||||
#
|
#
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([stdatomic.h atomic primitives], fc_cv_have_stdatomic_atomic_primitives, [
|
||||||
|
fc_cv_have_stdatomic_atomic_primitives=false
|
||||||
|
AC_TRY_LINK([
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
void memory_barrier (void) { atomic_thread_fence (memory_order_acq_rel); }
|
||||||
|
int atomic_add (atomic_int *i) { return atomic_fetch_add_explicit (i, 1, memory_order_relaxed); }
|
||||||
|
int mutex_trylock (atomic_flag *m) { return atomic_flag_test_and_set_explicit (m, memory_order_acquire); }
|
||||||
|
void mutex_unlock (atomic_flag *m) { atomic_flag_clear_explicit (m, memory_order_release); }
|
||||||
|
], [], fc_cv_have_stdatomic_atomic_primitives=true
|
||||||
|
)
|
||||||
|
])
|
||||||
|
if $fc_cv_have_stdatomic_atomic_primitives; then
|
||||||
|
AC_DEFINE(HAVE_STDATOMIC_PRIMITIVES, 1, [Have Intel __sync_* atomic primitives])
|
||||||
|
fi
|
||||||
|
|
||||||
AC_CACHE_CHECK([for Intel atomic primitives], fc_cv_have_intel_atomic_primitives, [
|
AC_CACHE_CHECK([for Intel atomic primitives], fc_cv_have_intel_atomic_primitives, [
|
||||||
fc_cv_have_intel_atomic_primitives=false
|
fc_cv_have_intel_atomic_primitives=false
|
||||||
AC_TRY_LINK([
|
AC_TRY_LINK([
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
void memory_barrier (void) { atomic_thread_fence (memory_order_acq_rel); }
|
||||||
|
int atomic_add (atomic_int *i) { return atomic_fetch_add_explicit (i, 1, memory_order_relaxed); }
|
||||||
|
int mutex_trylock (atomic_flag *m) { return atomic_flag_test_and_set_explicit (m, memory_order_acquire); }
|
||||||
|
void mutex_unlock (atomic_flag *m) { atomic_flag_clear_explicit (m, memory_order_release); }
|
||||||
|
|
||||||
|
int main(void) { return 0;}
|
|
@ -190,6 +190,10 @@ else
|
||||||
conf.set('FLEXIBLE_ARRAY_MEMBER', 1)
|
conf.set('FLEXIBLE_ARRAY_MEMBER', 1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if cc.links(files('meson-cc-tests/stdatomic-primitives-test.c'), name: 'stdatomic.h atomics')
|
||||||
|
conf.set('HAVE_STDATOMIC_PRIMITIVES', 1)
|
||||||
|
endif
|
||||||
|
|
||||||
if cc.links(files('meson-cc-tests/intel-atomic-primitives-test.c'), name: 'Intel atomics')
|
if cc.links(files('meson-cc-tests/intel-atomic-primitives-test.c'), name: 'Intel atomics')
|
||||||
conf.set('HAVE_INTEL_ATOMIC_PRIMITIVES', 1)
|
conf.set('HAVE_INTEL_ATOMIC_PRIMITIVES', 1)
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -51,6 +51,25 @@ typedef <type> fc_atomic_int_t;
|
||||||
#define fc_atomic_ptr_cmpexch(P,O,N) *(P) == (O) ? (*(P) = (N), FcTrue) : FcFalse // atomic release
|
#define fc_atomic_ptr_cmpexch(P,O,N) *(P) == (O) ? (*(P) = (N), FcTrue) : FcFalse // atomic release
|
||||||
|
|
||||||
|
|
||||||
|
#elif !defined(FC_NO_MT) && defined(HAVE_STDATOMIC_PRIMITIVES)
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
typedef atomic_int fc_atomic_int_t;
|
||||||
|
#define FC_ATOMIC_INT_FORMAT "d"
|
||||||
|
#define fc_atomic_int_add(AI, V) atomic_fetch_add (&(AI), (V))
|
||||||
|
|
||||||
|
#define fc_atomic_ptr_get(P) atomic_load ((_Atomic(void *)*) (P))
|
||||||
|
static inline FcBool _fc_atomic_ptr_cmpexch(_Atomic(void *)*P, void * O, _Atomic(void *) N) {
|
||||||
|
return atomic_compare_exchange_strong(P, &O, N);
|
||||||
|
}
|
||||||
|
#define fc_atomic_ptr_cmpexch(P,O,N) _fc_atomic_ptr_cmpexch ((_Atomic(void *)*) (P), (O), (N))
|
||||||
|
|
||||||
|
/* Casting -1 to _Atomic(int) produces a compiler error with Clang (but not GCC)
|
||||||
|
* so we have to override FC_REF_CONSTANT_VALUE for stdatomic.h atomics.
|
||||||
|
* See https://bugs.llvm.org/show_bug.cgi?id=40249. */
|
||||||
|
#define FC_REF_CONSTANT_VALUE (-1)
|
||||||
|
|
||||||
#elif !defined(FC_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__)
|
#elif !defined(FC_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
|
||||||
#include "fcwindows.h"
|
#include "fcwindows.h"
|
||||||
|
@ -137,7 +156,9 @@ typedef int fc_atomic_int_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* reference count */
|
/* reference count */
|
||||||
|
#ifndef FC_REF_CONSTANT_VALUE
|
||||||
#define FC_REF_CONSTANT_VALUE ((fc_atomic_int_t) -1)
|
#define FC_REF_CONSTANT_VALUE ((fc_atomic_int_t) -1)
|
||||||
|
#endif
|
||||||
#define FC_REF_CONSTANT {FC_REF_CONSTANT_VALUE}
|
#define FC_REF_CONSTANT {FC_REF_CONSTANT_VALUE}
|
||||||
typedef struct _FcRef { fc_atomic_int_t count; } FcRef;
|
typedef struct _FcRef { fc_atomic_int_t count; } FcRef;
|
||||||
static inline void FcRefInit (FcRef *r, int v) { r->count = v; }
|
static inline void FcRefInit (FcRef *r, int v) { r->count = v; }
|
||||||
|
|
|
@ -135,7 +135,7 @@ FcCacheIsMmapSafe (int fd)
|
||||||
status = use ? MMAP_USE : MMAP_DONT_USE;
|
status = use ? MMAP_USE : MMAP_DONT_USE;
|
||||||
else
|
else
|
||||||
status = MMAP_CHECK_FS;
|
status = MMAP_CHECK_FS;
|
||||||
(void) fc_atomic_ptr_cmpexch (&static_status, NULL, (void *) status);
|
(void) fc_atomic_ptr_cmpexch (&static_status, NULL, (void *) (intptr_t) status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == MMAP_CHECK_FS)
|
if (status == MMAP_CHECK_FS)
|
||||||
|
|
Loading…
Reference in New Issue