bpo-40522: _PyThreadState_Swap() sets autoTSSkey (GH-19939)

In the experimental isolated subinterpreters build mode,
_PyThreadState_GET() gets the autoTSSkey variable and
_PyThreadState_Swap() sets the autoTSSkey variable.

* Add _PyThreadState_GetTSS()
* _PyRuntimeState_GetThreadState() and _PyThreadState_GET()
  return _PyThreadState_GetTSS()
* PyEval_SaveThread() sets the autoTSSkey variable to current Python
  thread state rather than NULL.
* eval_frame_handle_pending() doesn't check that
  _PyThreadState_Swap() result is NULL.
* _PyThreadState_Swap() gets the current Python thread state with
  _PyThreadState_GetTSS() rather than
  _PyRuntimeGILState_GetThreadState().
* PyGILState_Ensure() no longer checks _PyEval_ThreadsInitialized()
  since it cannot access the current interpreter.
This commit is contained in:
Victor Stinner 2020-05-05 19:56:48 +02:00 committed by GitHub
parent b4b53868d7
commit e838a9324c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 2 deletions

View File

@ -49,8 +49,18 @@ _Py_ThreadCanHandlePendingCalls(void)
/* Variable and macro for in-line access to current thread
and interpreter state */
static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *runtime) {
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
PyAPI_FUNC(PyThreadState*) _PyThreadState_GetTSS(void);
#endif
static inline PyThreadState*
_PyRuntimeState_GetThreadState(_PyRuntimeState *runtime)
{
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
return _PyThreadState_GetTSS();
#else
return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->gilstate.tstate_current);
#endif
}
/* Get the current Python thread state.
@ -62,8 +72,14 @@ static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *run
The caller must hold the GIL.
See also PyThreadState_Get() and PyThreadState_GET(). */
static inline PyThreadState *_PyThreadState_GET(void) {
static inline PyThreadState*
_PyThreadState_GET(void)
{
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
return _PyThreadState_GetTSS();
#else
return _PyRuntimeState_GetThreadState(&_PyRuntime);
#endif
}
/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */

View File

@ -380,9 +380,13 @@ PyEval_AcquireThread(PyThreadState *tstate)
take_gil(tstate);
struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate;
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
(void)_PyThreadState_Swap(gilstate, tstate);
#else
if (_PyThreadState_Swap(gilstate, tstate) != NULL) {
Py_FatalError("non-NULL old thread state");
}
#endif
}
void
@ -443,7 +447,12 @@ PyThreadState *
PyEval_SaveThread(void)
{
_PyRuntimeState *runtime = &_PyRuntime;
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
PyThreadState *old_tstate = _PyThreadState_GET();
PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, old_tstate);
#else
PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL);
#endif
ensure_tstate_not_null(__func__, tstate);
struct _ceval_runtime_state *ceval = &runtime->ceval;
@ -866,9 +875,13 @@ eval_frame_handle_pending(PyThreadState *tstate)
take_gil(tstate);
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
(void)_PyThreadState_Swap(&runtime->gilstate, tstate);
#else
if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) {
Py_FatalError("orphan tstate");
}
#endif
}
/* Check for asynchronous exception. */

View File

@ -956,6 +956,14 @@ _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate)
}
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
PyThreadState*
_PyThreadState_GetTSS(void) {
return PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey);
}
#endif
PyThreadState *
_PyThreadState_UncheckedGet(void)
{
@ -975,7 +983,11 @@ PyThreadState_Get(void)
PyThreadState *
_PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts)
{
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
PyThreadState *oldts = _PyThreadState_GetTSS();
#else
PyThreadState *oldts = _PyRuntimeGILState_GetThreadState(gilstate);
#endif
_PyRuntimeGILState_SetThreadState(gilstate, newts);
/* It should not be possible for more than one thread state
@ -993,6 +1005,9 @@ _PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *new
Py_FatalError("Invalid thread state for this thread");
errno = err;
}
#endif
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
PyThread_tss_set(&gilstate->autoTSSkey, newts);
#endif
return oldts;
}
@ -1363,7 +1378,9 @@ PyGILState_Ensure(void)
/* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been
called by Py_Initialize() */
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
assert(_PyEval_ThreadsInitialized(runtime));
#endif
assert(gilstate->autoInterpreterState);
PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey);