diff --git a/acinclude.m4 b/acinclude.m4 index a2135881..4bbd19e6 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -603,6 +603,26 @@ int main (int argc, char *argv []) ) }]) +dnl ################################################################################ +dnl # LIBZMQ_CHECK_ATOMIC_INSTRINSICS([action-if-found], [action-if-not-found]) # +dnl # Check if compiler supoorts __atomic_Xxx intrinsics # +dnl ################################################################################ +AC_DEFUN([LIBZMQ_CHECK_ATOMIC_INTRINSICS], [{ + AC_MSG_CHECKING(whether compiler supports __atomic_Xxx intrinsics) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ +/* atomic intrinsics test */ +int v = 0; +int main (int, char **) +{ + int t = __atomic_add_fetch (&v, 1, __ATOMIC_ACQ_REL); + return t; +} + ])], + [AC_MSG_RESULT(yes) ; libzmq_cv_has_atomic_instrisics="yes" ; $1], + [AC_MSG_RESULT(no) ; libzmq_cv_has_atomic_instrisics="no" ; $2] + ) +}]) + dnl ################################################################################ dnl # LIBZMQ_CHECK_SO_KEEPALIVE([action-if-found], [action-if-not-found]) # dnl # Check if SO_KEEPALIVE is supported # @@ -764,7 +784,7 @@ kqueue(); dnl ################################################################################ dnl # LIBZMQ_CHECK_POLLER_EPOLL_RUN([action-if-found], [action-if-not-found]) # dnl # Checks epoll polling system can actually run # -dnl # For cross-compile, only requires that epoll can link # +dnl # For cross-compile, only requires that epoll can link # dnl ################################################################################ AC_DEFUN([LIBZMQ_CHECK_POLLER_EPOLL], [{ AC_RUN_IFELSE( @@ -794,7 +814,7 @@ return(r < 0); )], [libzmq_cv_have_poller_epoll="yes" ; $1], [libzmq_cv_have_poller_epoll="no" ; $2]) - + ]) }]) diff --git a/configure.ac b/configure.ac index f1a824b6..0c1ced12 100644 --- a/configure.ac +++ b/configure.ac @@ -479,6 +479,15 @@ AM_CONDITIONAL(ON_CYGWIN, test "x$libzmq_on_cygwin" = "xyes") AM_CONDITIONAL(ON_ANDROID, test "x$libzmq_on_android" = "xyes") AM_CONDITIONAL(ON_LINUX, test "x$libzmq_on_linux" = "xyes") +# Check for __atomic_Xxx compiler intrinsics +AC_LANG_PUSH([C++]) +LIBZMQ_CHECK_ATOMIC_INTRINSICS([ + AC_DEFINE([ZMQ_HAVE_ATOMIC_INTRINSICS], + [1], + [Whether compiler has __atomic_Xxx intrinsics.]) + ]) +AC_LANG_POP([C++]) + # Checks for library functions. AC_TYPE_SIGNAL AC_CHECK_FUNCS(perror gettimeofday clock_gettime memset socket getifaddrs freeifaddrs fork posix_memalign) diff --git a/src/atomic_counter.hpp b/src/atomic_counter.hpp index b1f9d9d5..79a49a15 100644 --- a/src/atomic_counter.hpp +++ b/src/atomic_counter.hpp @@ -25,6 +25,8 @@ #if defined ZMQ_FORCE_MUTEXES #define ZMQ_ATOMIC_COUNTER_MUTEX +#elif defined ZMQ_HAVE_ATOMIC_INTRINSICS +#define ZMQ_ATOMIC_INTRINSIC #elif (defined __i386__ || defined __x86_64__) && defined __GNUC__ #define ZMQ_ATOMIC_COUNTER_X86 #elif defined __ARM_ARCH_7A__ && defined __GNUC__ @@ -83,11 +85,13 @@ namespace zmq #if defined ZMQ_ATOMIC_COUNTER_WINDOWS old_value = InterlockedExchangeAdd ((LONG*) &value, increment_); +#elif defined ZMQ_ATOMIC_INTRINSIC + old_value = __atomic_fetch_add(&value, increment_, __ATOMIC_ACQ_REL); #elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H integer_t new_value = atomic_add_32_nv (&value, increment_); old_value = new_value - increment_; #elif defined ZMQ_ATOMIC_COUNTER_TILE - old_value = arch_atomic_add (&value, increment_); + old_value = arch_atomic_add (&value, increment_); #elif defined ZMQ_ATOMIC_COUNTER_X86 __asm__ volatile ( "lock; xadd %0, %1 \n\t" @@ -125,6 +129,9 @@ namespace zmq LONG delta = - ((LONG) decrement); integer_t old = InterlockedExchangeAdd ((LONG*) &value, delta); return old - decrement != 0; +#elif defined ZMQ_ATOMIC_INTRINSIC + integer_t nv = __atomic_sub_fetch(&value, decrement, __ATOMIC_ACQ_REL); + return nv != 0; #elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H int32_t delta = - ((int32_t) decrement); integer_t nv = atomic_add_32_nv (&value, delta); diff --git a/src/atomic_ptr.hpp b/src/atomic_ptr.hpp index ba456af3..dc44a34a 100644 --- a/src/atomic_ptr.hpp +++ b/src/atomic_ptr.hpp @@ -24,6 +24,8 @@ #if defined ZMQ_FORCE_MUTEXES #define ZMQ_ATOMIC_PTR_MUTEX +#elif defined ZMQ_HAVE_ATOMIC_INTRINSICS +#define ZMQ_ATOMIC_PTR_INTRINSIC #elif (defined __i386__ || defined __x86_64__) && defined __GNUC__ #define ZMQ_ATOMIC_PTR_X86 #elif defined __ARM_ARCH_7A__ && defined __GNUC__ @@ -82,6 +84,8 @@ namespace zmq { #if defined ZMQ_ATOMIC_PTR_WINDOWS return (T*) InterlockedExchangePointer ((PVOID*) &ptr, val_); +#elif defined ZMQ_ATOMIC_PTR_INTRINSIC + return (T*) __atomic_exchange_n (&ptr, val_, __ATOMIC_ACQ_REL); #elif defined ZMQ_ATOMIC_PTR_ATOMIC_H return (T*) atomic_swap_ptr (&ptr, val_); #elif defined ZMQ_ATOMIC_PTR_TILE @@ -127,6 +131,11 @@ namespace zmq #if defined ZMQ_ATOMIC_PTR_WINDOWS return (T*) InterlockedCompareExchangePointer ( (volatile PVOID*) &ptr, val_, cmp_); +#elif defined ZMQ_ATOMIC_PTR_INTRINSIC + T *old = cmp_; + __atomic_compare_exchange_n (&ptr, (volatile T**) &old, val_, false, + __ATOMIC_RELEASE, __ATOMIC_ACQUIRE); + return old; #elif defined ZMQ_ATOMIC_PTR_ATOMIC_H return (T*) atomic_cas_ptr (&ptr, cmp_, val_); #elif defined ZMQ_ATOMIC_PTR_TILE