configure: Add configure-time check for GCC 4.0+ atomic built-ins.
authorBen Pfaff <blp@nicira.com>
Mon, 15 Jul 2013 21:13:53 +0000 (14:13 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 31 Jul 2013 15:56:36 +0000 (08:56 -0700)
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 <blp@nicira.com>
Acked-by: Ethan Jackson <ethan@nicira.com>
configure.ac
lib/ovs-atomic.h
m4/openvswitch.m4

index 70fc9df..89541aa 100644 (file)
@@ -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)
index a0a34f3..3fc9dcb 100644 (file)
         #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"
index dbfc7c4..bcdb942 100644 (file)
@@ -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)