#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
* 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,
((ATOMIC_VAL)->_value)
#endif /* !gcc x86 */
+#endif
/* Standardized shortcuts. */
#define _Py_atomic_store(ATOMIC_VAL, NEW_VAL) \
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; }
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,