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.
This commit is contained in:
parent
b551fac136
commit
4f5366e65a
|
@ -1,12 +1,15 @@
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
#ifndef Py_ATOMIC_H
|
#ifndef Py_ATOMIC_H
|
||||||
#define 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 "dynamic_annotations.h"
|
||||||
|
|
||||||
|
#include "pyconfig.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_STD_ATOMIC)
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,6 +23,76 @@ extern "C" {
|
||||||
* Beware, the implementations here are deep magic.
|
* 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 {
|
typedef enum _Py_memory_order {
|
||||||
_Py_memory_order_relaxed,
|
_Py_memory_order_relaxed,
|
||||||
_Py_memory_order_acquire,
|
_Py_memory_order_acquire,
|
||||||
|
@ -162,6 +235,7 @@ _Py_ANNOTATE_MEMORY_ORDER(const volatile void *address, _Py_memory_order order)
|
||||||
((ATOMIC_VAL)->_value)
|
((ATOMIC_VAL)->_value)
|
||||||
|
|
||||||
#endif /* !gcc x86 */
|
#endif /* !gcc x86 */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Standardized shortcuts. */
|
/* Standardized shortcuts. */
|
||||||
#define _Py_atomic_store(ATOMIC_VAL, NEW_VAL) \
|
#define _Py_atomic_store(ATOMIC_VAL, NEW_VAL) \
|
||||||
|
|
|
@ -821,6 +821,7 @@ Ross Light
|
||||||
Shawn Ligocki
|
Shawn Ligocki
|
||||||
Martin Ligr
|
Martin Ligr
|
||||||
Gediminas Liktaras
|
Gediminas Liktaras
|
||||||
|
Vitor de Lima
|
||||||
Grant Limberg
|
Grant Limberg
|
||||||
Christopher Lindblad
|
Christopher Lindblad
|
||||||
Ulf A. Lindgren
|
Ulf A. Lindgren
|
||||||
|
@ -1355,6 +1356,7 @@ Steven Taschuk
|
||||||
Amy Taylor
|
Amy Taylor
|
||||||
Monty Taylor
|
Monty Taylor
|
||||||
Anatoly Techtonik
|
Anatoly Techtonik
|
||||||
|
Gustavo Temple
|
||||||
Mikhail Terekhov
|
Mikhail Terekhov
|
||||||
Victor Terrón
|
Victor Terrón
|
||||||
Richard M. Tew
|
Richard M. Tew
|
||||||
|
|
|
@ -10,6 +10,10 @@ Release date: TBA
|
||||||
Core and Builtins
|
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 #23048: Fix jumping out of an infinite while loop in the pdb.
|
||||||
|
|
||||||
- Issue #20335: bytes constructor now raises TypeError when encoding or errors
|
- Issue #20335: bytes constructor now raises TypeError when encoding or errors
|
||||||
|
|
|
@ -15703,6 +15703,71 @@ $as_echo "#define HAVE_IPA_PURE_CONST_BUG 1" >>confdefs.h
|
||||||
esac
|
esac
|
||||||
fi
|
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
|
# ensurepip option
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ensurepip" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ensurepip" >&5
|
||||||
$as_echo_n "checking for ensurepip... " >&6; }
|
$as_echo_n "checking for ensurepip... " >&6; }
|
||||||
|
|
39
configure.ac
39
configure.ac
|
@ -4884,6 +4884,45 @@ if test "$have_gcc_asm_for_x87" = yes; then
|
||||||
esac
|
esac
|
||||||
fi
|
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
|
# ensurepip option
|
||||||
AC_MSG_CHECKING(for ensurepip)
|
AC_MSG_CHECKING(for ensurepip)
|
||||||
AC_ARG_WITH(ensurepip,
|
AC_ARG_WITH(ensurepip,
|
||||||
|
|
|
@ -101,6 +101,9 @@
|
||||||
/* Define if `unsetenv` does not return an int. */
|
/* Define if `unsetenv` does not return an int. */
|
||||||
#undef HAVE_BROKEN_UNSETENV
|
#undef HAVE_BROKEN_UNSETENV
|
||||||
|
|
||||||
|
/* Has builtin atomics */
|
||||||
|
#undef HAVE_BUILTIN_ATOMIC
|
||||||
|
|
||||||
/* Define this if you have the type _Bool. */
|
/* Define this if you have the type _Bool. */
|
||||||
#undef HAVE_C99_BOOL
|
#undef HAVE_C99_BOOL
|
||||||
|
|
||||||
|
@ -877,6 +880,9 @@
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
#undef HAVE_STDLIB_H
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Has stdatomic.h */
|
||||||
|
#undef HAVE_STD_ATOMIC
|
||||||
|
|
||||||
/* Define to 1 if you have the `strdup' function. */
|
/* Define to 1 if you have the `strdup' function. */
|
||||||
#undef HAVE_STRDUP
|
#undef HAVE_STRDUP
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue