summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--lib/ovs-atomic.h2
-rw-r--r--m4/openvswitch.m472
3 files changed, 74 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 70fc9df25..89541aaef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,6 +83,7 @@ OVS_CHECK_GROFF
OVS_CHECK_GNU_MAKE
OVS_CHECK_CACHE_TIME
OVS_CHECK_TLS
+OVS_CHECK_GCC4_ATOMICS
OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(1)
OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(2)
OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(4)
diff --git a/lib/ovs-atomic.h b/lib/ovs-atomic.h
index a0a34f30f..3fc9dcb8f 100644
--- a/lib/ovs-atomic.h
+++ b/lib/ovs-atomic.h
@@ -240,7 +240,7 @@
#include "ovs-atomic-c11.h"
#elif __GNUC__ >= 4 && __GNUC_MINOR__ >= 7
#include "ovs-atomic-gcc4.7+.h"
- #elif __GNUC__ >= 4
+ #elif HAVE_GCC4_ATOMICS
#include "ovs-atomic-gcc4+.h"
#else
#include "ovs-atomic-pthreads.h"
diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4
index dbfc7c425..bcdb942b9 100644
--- a/m4/openvswitch.m4
+++ b/m4/openvswitch.m4
@@ -426,6 +426,78 @@ static thread_local int var;], [return var;])],
fi
fi])
+dnl OVS_CHECK_GCC4_ATOMICS
+dnl
+dnl Checks whether the compiler and linker support GCC 4.0+ atomic built-ins.
+dnl A compile-time only check is not enough because the compiler defers
+dnl unimplemented built-ins to libgcc, which sometimes also lacks
+dnl implementations.
+AC_DEFUN([OVS_CHECK_GCC4_ATOMICS],
+ [AC_CACHE_CHECK(
+ [whether $CC supports GCC 4.0+ atomic built-ins],
+ [ovs_cv_gcc4_atomics],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[#include <stdlib.h>
+
+#define ovs_assert(expr) if (!(expr)) abort();
+#define TEST_ATOMIC_TYPE(TYPE) \
+ { \
+ TYPE x = 1; \
+ TYPE orig; \
+ \
+ __sync_synchronize(); \
+ ovs_assert(x == 1); \
+ \
+ __sync_synchronize(); \
+ x = 3; \
+ __sync_synchronize(); \
+ ovs_assert(x == 3); \
+ \
+ orig = __sync_fetch_and_add(&x, 1); \
+ ovs_assert(orig == 3); \
+ __sync_synchronize(); \
+ ovs_assert(x == 4); \
+ \
+ orig = __sync_fetch_and_sub(&x, 2); \
+ ovs_assert(orig == 4); \
+ __sync_synchronize(); \
+ ovs_assert(x == 2); \
+ \
+ orig = __sync_fetch_and_or(&x, 6); \
+ ovs_assert(orig == 2); \
+ __sync_synchronize(); \
+ ovs_assert(x == 6); \
+ \
+ orig = __sync_fetch_and_and(&x, 10); \
+ ovs_assert(orig == 6); \
+ __sync_synchronize(); \
+ ovs_assert(x == 2); \
+ \
+ orig = __sync_fetch_and_xor(&x, 10); \
+ ovs_assert(orig == 2); \
+ __sync_synchronize(); \
+ ovs_assert(x == 8); \
+ }]], [dnl
+TEST_ATOMIC_TYPE(char);
+TEST_ATOMIC_TYPE(unsigned char);
+TEST_ATOMIC_TYPE(signed char);
+TEST_ATOMIC_TYPE(short);
+TEST_ATOMIC_TYPE(unsigned short);
+TEST_ATOMIC_TYPE(int);
+TEST_ATOMIC_TYPE(unsigned int);
+TEST_ATOMIC_TYPE(long int);
+TEST_ATOMIC_TYPE(unsigned long int);
+TEST_ATOMIC_TYPE(long long int);
+TEST_ATOMIC_TYPE(unsigned long long int);
+])],
+ [ovs_cv_gcc4_atomics=yes],
+ [ovs_cv_gcc4_atomics=no])])
+ if test $ovs_cv_gcc4_atomics = yes; then
+ AC_DEFINE([HAVE_GCC4_ATOMICS], [1],
+ [Define to 1 if the C compiler and linker supports the GCC 4.0+
+ atomic built-ins.])
+ fi])
+
dnl OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(SIZE)
dnl
dnl Checks __atomic_always_lock_free(SIZE, 0)