]> granicus.if.org Git - python/commitdiff
Issue #22038: pyatomic.h now uses stdatomic.h or GCC built-in functions for
authorVictor Stinner <victor.stinner@gmail.com>
Fri, 9 Jan 2015 01:13:19 +0000 (02:13 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Fri, 9 Jan 2015 01:13:19 +0000 (02:13 +0100)
atomic memory access if available. Patch written by Vitor de Lima and Gustavo
Temple.

Include/pyatomic.h
Misc/ACKS
Misc/NEWS
configure
configure.ac
pyconfig.h.in

index d4e19e0070be577cb0d95c265f6ee8845192b4f9..80bd825bd75131c3f57ad848cc28b91cd1c9a9ff 100644 (file)
@@ -1,12 +1,15 @@
 #ifndef Py_LIMITED_API
 #ifndef Py_ATOMIC_H
 #define Py_ATOMIC_H
-/* XXX: When compilers start offering a stdatomic.h with lock-free
-   atomic_int and atomic_address types, include that here and rewrite
-   the atomic operations in terms of it. */
 
 #include "dynamic_annotations.h"
 
+#include "pyconfig.h"
+
+#if defined(HAVE_STD_ATOMIC)
+#include <stdatomic.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -20,6 +23,76 @@ extern "C" {
  * Beware, the implementations here are deep magic.
  */
 
+#if defined(HAVE_STD_ATOMIC)
+
+typedef enum _Py_memory_order {
+    _Py_memory_order_relaxed = memory_order_relaxed,
+    _Py_memory_order_acquire = memory_order_acquire,
+    _Py_memory_order_release = memory_order_release,
+    _Py_memory_order_acq_rel = memory_order_acq_rel,
+    _Py_memory_order_seq_cst = memory_order_seq_cst
+} _Py_memory_order;
+
+typedef struct _Py_atomic_address {
+    _Atomic void *_value;
+} _Py_atomic_address;
+
+typedef struct _Py_atomic_int {
+    atomic_int _value;
+} _Py_atomic_int;
+
+#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) \
+    atomic_signal_fence(ORDER)
+
+#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) \
+    atomic_thread_fence(ORDER)
+
+#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \
+    atomic_store_explicit(&(ATOMIC_VAL)->_value, NEW_VAL, ORDER)
+
+#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \
+    atomic_load_explicit(&(ATOMIC_VAL)->_value, ORDER)
+
+/* Use builtin atomic operations in GCC >= 4.7 */
+#elif defined(HAVE_BUILTIN_ATOMIC)
+
+typedef enum _Py_memory_order {
+    _Py_memory_order_relaxed = __ATOMIC_RELAXED,
+    _Py_memory_order_acquire = __ATOMIC_ACQUIRE,
+    _Py_memory_order_release = __ATOMIC_RELEASE,
+    _Py_memory_order_acq_rel = __ATOMIC_ACQ_REL,
+    _Py_memory_order_seq_cst = __ATOMIC_SEQ_CST
+} _Py_memory_order;
+
+typedef struct _Py_atomic_address {
+    void *_value;
+} _Py_atomic_address;
+
+typedef struct _Py_atomic_int {
+    int _value;
+} _Py_atomic_int;
+
+#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) \
+    __atomic_signal_fence(ORDER)
+
+#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) \
+    __atomic_thread_fence(ORDER)
+
+#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \
+    (assert((ORDER) == __ATOMIC_RELAXED                       \
+            || (ORDER) == __ATOMIC_SEQ_CST                    \
+            || (ORDER) == __ATOMIC_RELEASE),                  \
+     __atomic_store_n(&(ATOMIC_VAL)->_value, NEW_VAL, ORDER))
+
+#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER)           \
+    (assert((ORDER) == __ATOMIC_RELAXED                       \
+            || (ORDER) == __ATOMIC_SEQ_CST                    \
+            || (ORDER) == __ATOMIC_ACQUIRE                    \
+            || (ORDER) == __ATOMIC_CONSUME),                  \
+     __atomic_load_n(&(ATOMIC_VAL)->_value, ORDER))
+
+#else
+
 typedef enum _Py_memory_order {
     _Py_memory_order_relaxed,
     _Py_memory_order_acquire,
@@ -162,6 +235,7 @@ _Py_ANNOTATE_MEMORY_ORDER(const volatile void *address, _Py_memory_order order)
     ((ATOMIC_VAL)->_value)
 
 #endif  /* !gcc x86 */
+#endif
 
 /* Standardized shortcuts. */
 #define _Py_atomic_store(ATOMIC_VAL, NEW_VAL) \
index eae72c7591c2f7598f5926df2a6e82346ad7efb5..42ff010891467e03feb3fe68e7e40367407a909e 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -821,6 +821,7 @@ Ross Light
 Shawn Ligocki
 Martin Ligr
 Gediminas Liktaras
+Vitor de Lima
 Grant Limberg
 Christopher Lindblad
 Ulf A. Lindgren
@@ -1355,6 +1356,7 @@ Steven Taschuk
 Amy Taylor
 Monty Taylor
 Anatoly Techtonik
+Gustavo Temple
 Mikhail Terekhov
 Victor TerrĂ³n
 Richard M. Tew
index ef5f9aae806350404369e77c552ead94bb11f30e..5f550d2a09981d306b3e60ebdb5ab6609f0e73af 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,10 @@ Release date: TBA
 Core and Builtins
 -----------------
 
+- Issue #22038: pyatomic.h now uses stdatomic.h or GCC built-in functions for
+  atomic memory access if available. Patch written by Vitor de Lima and Gustavo
+  Temple.
+
 - Issue #23048: Fix jumping out of an infinite while loop in the pdb.
 
 - Issue #20335: bytes constructor now raises TypeError when encoding or errors
index f9af72d5b565531552e09f8c938b608ee3f04871..1ba0e9410fc2f347a9add78308e8b2eb5810e03b 100755 (executable)
--- a/configure
+++ b/configure
@@ -15703,6 +15703,71 @@ $as_echo "#define HAVE_IPA_PURE_CONST_BUG 1" >>confdefs.h
     esac
 fi
 
+# Check for stdatomic.h
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdatomic.h" >&5
+$as_echo_n "checking for stdatomic.h... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+    #include <stdatomic.h>
+    _Atomic int value = ATOMIC_VAR_INIT(1);
+    int main() {
+      int loaded_value = atomic_load(&value);
+      return 0;
+    }
+
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  have_stdatomic_h=yes
+else
+  have_stdatomic_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_stdatomic_h" >&5
+$as_echo "$have_stdatomic_h" >&6; }
+
+if test "$have_stdatomic_h" = yes; then
+
+$as_echo "#define HAVE_STD_ATOMIC 1" >>confdefs.h
+
+fi
+
+# Check for GCC >= 4.7 __atomic builtins
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC >= 4.7 __atomic builtins" >&5
+$as_echo_n "checking for GCC >= 4.7 __atomic builtins... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+    volatile int val = 1;
+    int main() {
+      __atomic_load_n(&val, __ATOMIC_SEQ_CST);
+      return 0;
+    }
+
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  have_builtin_atomic=yes
+else
+  have_builtin_atomic=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_builtin_atomic" >&5
+$as_echo "$have_builtin_atomic" >&6; }
+
+if test "$have_builtin_atomic" = yes; then
+
+$as_echo "#define HAVE_BUILTIN_ATOMIC 1" >>confdefs.h
+
+fi
+
 # ensurepip option
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ensurepip" >&5
 $as_echo_n "checking for ensurepip... " >&6; }
index c7504a27dd0e66887e32e039943d0cace53e1cf1..da096a7c883c3166766ffbb9d2543383ba9f1f2c 100644 (file)
@@ -4884,6 +4884,45 @@ if test "$have_gcc_asm_for_x87" = yes; then
     esac
 fi
 
+# Check for stdatomic.h
+AC_MSG_CHECKING(for stdatomic.h)
+AC_LINK_IFELSE(
+[
+  AC_LANG_SOURCE([[
+    #include <stdatomic.h>
+    _Atomic int value = ATOMIC_VAR_INIT(1);
+    int main() {
+      int loaded_value = atomic_load(&value);
+      return 0;
+    }
+  ]])
+],[have_stdatomic_h=yes],[have_stdatomic_h=no])
+
+AC_MSG_RESULT($have_stdatomic_h)
+
+if test "$have_stdatomic_h" = yes; then
+    AC_DEFINE(HAVE_STD_ATOMIC, 1, [Has stdatomic.h])
+fi
+
+# Check for GCC >= 4.7 __atomic builtins
+AC_MSG_CHECKING(for GCC >= 4.7 __atomic builtins)
+AC_LINK_IFELSE(
+[
+  AC_LANG_SOURCE([[
+    volatile int val = 1;
+    int main() {
+      __atomic_load_n(&val, __ATOMIC_SEQ_CST);
+      return 0;
+    }
+  ]])
+],[have_builtin_atomic=yes],[have_builtin_atomic=no])
+
+AC_MSG_RESULT($have_builtin_atomic)
+
+if test "$have_builtin_atomic" = yes; then
+    AC_DEFINE(HAVE_BUILTIN_ATOMIC, 1, [Has builtin atomics])
+fi
+
 # ensurepip option
 AC_MSG_CHECKING(for ensurepip)
 AC_ARG_WITH(ensurepip,
index 8107c3af7486569ad2c0d0cd5a5f8196e02032ff..10d5f4a5f4bc61587449ed7fceeb26d24434ebad 100644 (file)
 /* Define if `unsetenv` does not return an int. */
 #undef HAVE_BROKEN_UNSETENV
 
+/* Has builtin atomics */
+#undef HAVE_BUILTIN_ATOMIC
+
 /* Define this if you have the type _Bool. */
 #undef HAVE_C99_BOOL
 
 /* Define to 1 if you have the <stdlib.h> header file. */
 #undef HAVE_STDLIB_H
 
+/* Has stdatomic.h */
+#undef HAVE_STD_ATOMIC
+
 /* Define to 1 if you have the `strdup' function. */
 #undef HAVE_STRDUP