diff options
author | Victor Stinner <vstinner@redhat.com> | 2018-11-01 00:51:40 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-01 00:51:40 (GMT) |
commit | 50b48572d9a90c5bb36e2bef6179548ea927a35a (patch) | |
tree | 3b77efe6c7182a3e0b98fcba9854198dbeca3a98 /Include | |
parent | 27e2d1f21975dfb8c0ddcb192fa0f45a51b7977e (diff) | |
download | cpython-50b48572d9a90c5bb36e2bef6179548ea927a35a.zip cpython-50b48572d9a90c5bb36e2bef6179548ea927a35a.tar.gz cpython-50b48572d9a90c5bb36e2bef6179548ea927a35a.tar.bz2 |
bpo-35081: Add _PyThreadState_GET() internal macro (GH-10266)
If Py_BUILD_CORE is defined, the PyThreadState_GET() macro access
_PyRuntime which comes from the internal pycore_state.h header.
Public headers must not require internal headers.
Move PyThreadState_GET() and _PyInterpreterState_GET_UNSAFE() from
Include/pystate.h to Include/internal/pycore_state.h, and rename
PyThreadState_GET() to _PyThreadState_GET() there.
The PyThreadState_GET() macro of pystate.h is now redefined when
pycore_state.h is included, to use the fast _PyThreadState_GET().
Changes:
* Add _PyThreadState_GET() macro
* Replace "PyThreadState_GET()->interp" with
_PyInterpreterState_GET_UNSAFE()
* Replace PyThreadState_GET() with _PyThreadState_GET() in internal C
files (compiled with Py_BUILD_CORE defined), but keep
PyThreadState_GET() in the public header files.
* _testcapimodule.c: replace PyThreadState_GET() with
PyThreadState_Get(); the module is not compiled with Py_BUILD_CORE
defined.
* pycore_state.h now requires Py_BUILD_CORE to be defined.
Diffstat (limited to 'Include')
-rw-r--r-- | Include/internal/pycore_state.h | 34 | ||||
-rw-r--r-- | Include/pystate.h | 56 |
2 files changed, 65 insertions, 25 deletions
diff --git a/Include/internal/pycore_state.h b/Include/internal/pycore_state.h index ff25d2e..9a084f7 100644 --- a/Include/internal/pycore_state.h +++ b/Include/internal/pycore_state.h @@ -4,6 +4,10 @@ extern "C" { #endif +#ifndef Py_BUILD_CORE +# error "Py_BUILD_CORE must be defined to include this header" +#endif + #include "pystate.h" #include "pythread.h" @@ -214,6 +218,36 @@ PyAPI_FUNC(_PyInitError) _PyRuntime_Initialize(void); (_PyRuntime.finalizing == tstate) +/* Variable and macro for in-line access to current thread + and interpreter state */ + +/* Get the current Python thread state. + + Efficient macro reading directly the 'gilstate.tstate_current' atomic + variable. The macro is unsafe: it does not check for error and it can + return NULL. + + The caller must hold the GIL. + + See also PyThreadState_Get() and PyThreadState_GET(). */ +#define _PyThreadState_GET() \ + ((PyThreadState*)_Py_atomic_load_relaxed(&_PyRuntime.gilstate.tstate_current)) + +/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */ +#undef PyThreadState_GET +#define PyThreadState_GET() _PyThreadState_GET() + +/* Get the current interpreter state. + + The macro is unsafe: it does not check for error and it can return NULL. + + The caller must hold the GIL. + + See also _PyInterpreterState_Get() + and _PyGILState_GetInterpreterStateUnsafe(). */ +#define _PyInterpreterState_GET_UNSAFE() (_PyThreadState_GET()->interp) + + /* Other */ PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *); diff --git a/Include/pystate.h b/Include/pystate.h index 7fc921e..b30c318 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -245,15 +245,17 @@ typedef struct _ts { PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void); PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *); PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *); + #if !defined(Py_LIMITED_API) +/* Get the current interpreter state. + + Issue a fatal error if there no current Python thread state or no current + interpreter. It cannot return NULL. + + The caller must hold the GIL.*/ PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void); #endif -#ifdef Py_BUILD_CORE - /* Macro which should only be used for performance critical code. - Need "#include "pycore_state.h". See also _PyInterpreterState_Get() - and _PyGILState_GetInterpreterStateUnsafe(). */ -# define _PyInterpreterState_GET_UNSAFE() (PyThreadState_GET()->interp) -#endif + #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 /* New in 3.7 */ PyAPI_FUNC(int64_t) PyInterpreterState_GetID(PyInterpreterState *); @@ -286,11 +288,27 @@ PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void); PyAPI_FUNC(void) _PyGILState_Reinit(void); #endif /* !Py_LIMITED_API */ -/* Return the current thread state. The global interpreter lock must be held. - * When the current thread state is NULL, this issues a fatal error (so that - * the caller needn't check for NULL). */ +/* Get the current thread state. + + When the current thread state is NULL, this issues a fatal error (so that + the caller needn't check for NULL). + + The caller must hold the GIL. + + See also PyThreadState_GET() and _PyThreadState_GET(). */ PyAPI_FUNC(PyThreadState *) PyThreadState_Get(void); +/* Get the current Python thread state. + + Macro using PyThreadState_Get() or _PyThreadState_GET() depending if + pycore_state.h is included or not (this header redefines the macro). + + If PyThreadState_Get() is used, issue a fatal error if the current thread + state is NULL. + + See also PyThreadState_Get() and _PyThreadState_GET(). */ +#define PyThreadState_GET() PyThreadState_Get() + #ifndef Py_LIMITED_API /* Similar to PyThreadState_Get(), but don't issue a fatal error * if it is NULL. */ @@ -301,18 +319,6 @@ PyAPI_FUNC(PyThreadState *) PyThreadState_Swap(PyThreadState *); PyAPI_FUNC(PyObject *) PyThreadState_GetDict(void); PyAPI_FUNC(int) PyThreadState_SetAsyncExc(unsigned long, PyObject *); - -/* Variable and macro for in-line access to current thread state */ - -/* Assuming the current thread holds the GIL, this is the - PyThreadState for the current thread. */ -#ifdef Py_BUILD_CORE -# define PyThreadState_GET() \ - ((PyThreadState*)_Py_atomic_load_relaxed(&_PyRuntime.gilstate.tstate_current)) -#else -# define PyThreadState_GET() PyThreadState_Get() -#endif - typedef enum {PyGILState_LOCKED, PyGILState_UNLOCKED} PyGILState_STATE; @@ -366,11 +372,11 @@ PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void); The function returns 1 if _PyGILState_check_enabled is non-zero. */ PyAPI_FUNC(int) PyGILState_Check(void); -/* Unsafe function to get the single PyInterpreterState used by this process' - GILState implementation. +/* Get the single PyInterpreterState used by this process' GILState + implementation. - Return NULL before _PyGILState_Init() is called and after _PyGILState_Fini() - is called. + This function doesn't check for error. Return NULL before _PyGILState_Init() + is called and after _PyGILState_Fini() is called. See also _PyInterpreterState_Get() and _PyInterpreterState_GET_UNSAFE(). */ PyAPI_FUNC(PyInterpreterState *) _PyGILState_GetInterpreterStateUnsafe(void); |