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:
Alex Richardson 2021-07-12 14:57:49 +01:00
parent ab4761ff87
commit 012ffaac75
5 changed files with 50 additions and 1 deletions

View File

@ -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([

View File

@ -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;}

View File

@ -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

View File

@ -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; }

View File

@ -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)