Skip to content

Commit e838a93

Browse files
authored
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.
1 parent b4b5386 commit e838a93

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

Include/internal/pycore_pystate.h

+18-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,18 @@ _Py_ThreadCanHandlePendingCalls(void)
4949
/* Variable and macro for in-line access to current thread
5050
and interpreter state */
5151

52-
static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *runtime) {
52+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
53+
PyAPI_FUNC(PyThreadState*) _PyThreadState_GetTSS(void);
54+
#endif
55+
56+
static inline PyThreadState*
57+
_PyRuntimeState_GetThreadState(_PyRuntimeState *runtime)
58+
{
59+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
60+
return _PyThreadState_GetTSS();
61+
#else
5362
return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->gilstate.tstate_current);
63+
#endif
5464
}
5565

5666
/* Get the current Python thread state.
@@ -62,8 +72,14 @@ static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *run
6272
The caller must hold the GIL.
6373
6474
See also PyThreadState_Get() and PyThreadState_GET(). */
65-
static inline PyThreadState *_PyThreadState_GET(void) {
75+
static inline PyThreadState*
76+
_PyThreadState_GET(void)
77+
{
78+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
79+
return _PyThreadState_GetTSS();
80+
#else
6681
return _PyRuntimeState_GetThreadState(&_PyRuntime);
82+
#endif
6783
}
6884

6985
/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */

Python/ceval.c

+13
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,13 @@ PyEval_AcquireThread(PyThreadState *tstate)
380380
take_gil(tstate);
381381

382382
struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate;
383+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
384+
(void)_PyThreadState_Swap(gilstate, tstate);
385+
#else
383386
if (_PyThreadState_Swap(gilstate, tstate) != NULL) {
384387
Py_FatalError("non-NULL old thread state");
385388
}
389+
#endif
386390
}
387391

388392
void
@@ -443,7 +447,12 @@ PyThreadState *
443447
PyEval_SaveThread(void)
444448
{
445449
_PyRuntimeState *runtime = &_PyRuntime;
450+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
451+
PyThreadState *old_tstate = _PyThreadState_GET();
452+
PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, old_tstate);
453+
#else
446454
PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL);
455+
#endif
447456
ensure_tstate_not_null(__func__, tstate);
448457

449458
struct _ceval_runtime_state *ceval = &runtime->ceval;
@@ -866,9 +875,13 @@ eval_frame_handle_pending(PyThreadState *tstate)
866875

867876
take_gil(tstate);
868877

878+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
879+
(void)_PyThreadState_Swap(&runtime->gilstate, tstate);
880+
#else
869881
if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) {
870882
Py_FatalError("orphan tstate");
871883
}
884+
#endif
872885
}
873886

874887
/* Check for asynchronous exception. */

Python/pystate.c

+17
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,14 @@ _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate)
956956
}
957957

958958

959+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
960+
PyThreadState*
961+
_PyThreadState_GetTSS(void) {
962+
return PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey);
963+
}
964+
#endif
965+
966+
959967
PyThreadState *
960968
_PyThreadState_UncheckedGet(void)
961969
{
@@ -975,7 +983,11 @@ PyThreadState_Get(void)
975983
PyThreadState *
976984
_PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts)
977985
{
986+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
987+
PyThreadState *oldts = _PyThreadState_GetTSS();
988+
#else
978989
PyThreadState *oldts = _PyRuntimeGILState_GetThreadState(gilstate);
990+
#endif
979991

980992
_PyRuntimeGILState_SetThreadState(gilstate, newts);
981993
/* It should not be possible for more than one thread state
@@ -993,6 +1005,9 @@ _PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *new
9931005
Py_FatalError("Invalid thread state for this thread");
9941006
errno = err;
9951007
}
1008+
#endif
1009+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
1010+
PyThread_tss_set(&gilstate->autoTSSkey, newts);
9961011
#endif
9971012
return oldts;
9981013
}
@@ -1363,7 +1378,9 @@ PyGILState_Ensure(void)
13631378

13641379
/* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been
13651380
called by Py_Initialize() */
1381+
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
13661382
assert(_PyEval_ThreadsInitialized(runtime));
1383+
#endif
13671384
assert(gilstate->autoInterpreterState);
13681385

13691386
PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey);

0 commit comments

Comments
 (0)