commit f40c4026253e65cfda3e0c8e6cfced4933aa48d4 Author: Nathan Froyd Date: Wed May 6 14:45:45 2015 -0400 support new-style __atomic_* primitives Recent versions of GCC/clang feature a new set of compiler intrinsics for performing atomic operations, motivated by the operations needed to support the C++11 memory model. These intrinsics are more flexible than the old __sync_* intrinstics and offer efficient support for atomic load and store operations. diff --git a/configure.ac b/configure.ac index 965a06c..3c736a6 100644 --- a/configure.ac +++ b/configure.ac @@ -387,6 +387,22 @@ AM_CONDITIONAL(HAVE_CORETEXT, $have_coretext) dnl =========================================================================== +AC_CACHE_CHECK([for C++11 atomic primitives], hb_cv_have_cxx11_atomic_primitives, [ + hb_cv_have_cxx11_atomic_primitives=false + AC_TRY_LINK([ + void memory_barrier (void) { __sync_synchronize (); } + int atomic_add (int *i) { return __atomic_fetch_add (i, 1, __ATOMIC_SEQ_CST); } + int mutex_trylock (int *m) { return __atomic_test_and_set (m, __ATOMIC_SEQ_CST); } + void mutex_unlock (int *m) { __atomic_clear (m, __ATOMIC_SEQ_CST); } + ], [], hb_cv_have_cxx11_atomic_primitives=true + ) +]) +if $hb_cv_have_cxx11_atomic_primitives; then + AC_DEFINE(HAVE_CXX11_ATOMIC_PRIMITIVES, 1, [Have C++11 __atomic_* atomic primitives]) +fi + +dnl =========================================================================== + AC_CACHE_CHECK([for Intel atomic primitives], hb_cv_have_intel_atomic_primitives, [ hb_cv_have_intel_atomic_primitives=false AC_TRY_LINK([ diff --git a/src/hb-atomic-private.hh b/src/hb-atomic-private.hh index 8179571..8581cc4 100644 --- a/src/hb-atomic-private.hh +++ b/src/hb-atomic-private.hh @@ -96,6 +96,26 @@ typedef int32_t hb_atomic_int_impl_t; #endif +/* Must come before the HAVE_INTEL_ATOMIC_PRIMITIVES check because the Intel + * primitives and the CXX11 primitives can coexist in the same compiler and + * we prefer the CXX11 primitives. */ +#elif !defined(HB_NO_MT) && defined(HAVE_CXX11_ATOMIC_PRIMITIVES) + +typedef int hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) __atomic_fetch_add(&(AI), (V), __ATOMIC_SEQ_CST) + +#define hb_atomic_ptr_impl_get(P) __atomic_load_n((P), __ATOMIC_SEQ_CST) + +static inline bool +hb_atomic_ptr_impl_cmplexch_impl(void **ptr, void *oldv, void *newv) +{ + void *expected = oldv; + return __atomic_compare_exchange_n(ptr, &expected, newv, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); +} +#define hb_atomic_ptr_impl_cmpexch(P,O,N) hb_atomic_ptr_impl_cmplexch_impl((void**)(P), (void*)(O), (void*)(N)) + + #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) typedef int hb_atomic_int_impl_t;