We found out earlier that GCC sometimes produces an error only at link time
for atomic built-ins that are not supported on a platform.  This actually
tries the link at configure time and should thus reliably detect whether
the atomic built-ins are really supported.

Signed-off-by: Ben Pfaff <b...@nicira.com>
---
I thought I'd already sent out these patches, but it looks like they
never made it to ovs-dev or patchwork.

 configure.ac      |    1 +
 lib/ovs-atomic.h  |    2 +-
 m4/openvswitch.m4 |   72 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+), 1 deletions(-)

diff --git a/configure.ac b/configure.ac
index e4f9991..e44ae36 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,6 +82,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 a0a34f3..3fc9dcb 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 ca80506..e6e5d08 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)
-- 
1.7.2.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to