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:
Victor Stinner 2015-01-09 02:13:19 +01:00
parent b551fac136
commit 4f5366e65a
6 changed files with 193 additions and 3 deletions

View 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) \

View file

@ -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

View file

@ -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

65
configure vendored
View file

@ -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; }

View 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,

View file

@ -101,6 +101,9 @@
/* 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
@ -877,6 +880,9 @@
/* 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