Skip to content

Commit 8bb3230

Browse files
authored
bpo-36710: Add runtime parameter to _PyThreadState_Init() (GH-12935)
* Add 'runtime' parameter to _PyThreadState_Init() * Add 'gilstate' parameter to _PyGILState_NoteThreadState() * Move _PyThreadState_Init() and _PyThreadState_DeleteExcept() to the internal C API.
1 parent 6c44fde commit 8bb3230

File tree

4 files changed

+80
-67
lines changed

4 files changed

+80
-67
lines changed

‎Include/cpython/pystate.h‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,6 @@ PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
155155
PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*);
156156
PyAPI_FUNC(void) _PyState_ClearModules(void);
157157
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
158-
PyAPI_FUNC(void) _PyThreadState_Init(PyThreadState *);
159-
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
160158
PyAPI_FUNC(void) _PyGILState_Reinit(void);
161159

162160
/* Similar to PyThreadState_Get(), but don't issue a fatal error

‎Include/internal/pycore_pystate.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,11 @@ PyAPI_FUNC(void) _PyRuntime_Finalize(void);
231231

232232
/* Other */
233233

234+
PyAPI_FUNC(void) _PyThreadState_Init(
235+
_PyRuntimeState *runtime,
236+
PyThreadState *tstate);
237+
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
238+
234239
PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *);
235240
PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(void);
236241

‎Modules/_threadmodule.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ t_bootstrap(void *boot_raw)
994994

995995
tstate = boot->tstate;
996996
tstate->thread_id = PyThread_get_thread_ident();
997-
_PyThreadState_Init(tstate);
997+
_PyThreadState_Init(&_PyRuntime, tstate);
998998
PyEval_AcquireThread(tstate);
999999
tstate->interp->num_threads++;
10001000
res = PyObject_Call(boot->func, boot->args, boot->keyw);

‎Python/pystate.c‎

Lines changed: 74 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ _PyRuntimeState_ReInitThreads(void)
133133
WAIT_LOCK)
134134
#define HEAD_UNLOCK() PyThread_release_lock(_PyRuntime.interpreters.mutex)
135135

136-
static void _PyGILState_NoteThreadState(PyThreadState* tstate);
136+
/* Forward declaration */
137+
static void _PyGILState_NoteThreadState(
138+
struct _gilstate_runtime_state *gilstate, PyThreadState* tstate);
137139

138140
_PyInitError
139141
_PyInterpreterState_Enable(_PyRuntimeState *runtime)
@@ -487,71 +489,74 @@ static PyThreadState *
487489
new_threadstate(PyInterpreterState *interp, int init)
488490
{
489491
PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState));
492+
if (tstate == NULL) {
493+
return NULL;
494+
}
490495

491-
if (_PyThreadState_GetFrame == NULL)
496+
if (_PyThreadState_GetFrame == NULL) {
492497
_PyThreadState_GetFrame = threadstate_getframe;
498+
}
493499

494-
if (tstate != NULL) {
495-
tstate->interp = interp;
496-
497-
tstate->frame = NULL;
498-
tstate->recursion_depth = 0;
499-
tstate->overflowed = 0;
500-
tstate->recursion_critical = 0;
501-
tstate->stackcheck_counter = 0;
502-
tstate->tracing = 0;
503-
tstate->use_tracing = 0;
504-
tstate->gilstate_counter = 0;
505-
tstate->async_exc = NULL;
506-
tstate->thread_id = PyThread_get_thread_ident();
500+
tstate->interp = interp;
507501

508-
tstate->dict = NULL;
502+
tstate->frame = NULL;
503+
tstate->recursion_depth = 0;
504+
tstate->overflowed = 0;
505+
tstate->recursion_critical = 0;
506+
tstate->stackcheck_counter = 0;
507+
tstate->tracing = 0;
508+
tstate->use_tracing = 0;
509+
tstate->gilstate_counter = 0;
510+
tstate->async_exc = NULL;
511+
tstate->thread_id = PyThread_get_thread_ident();
509512

510-
tstate->curexc_type = NULL;
511-
tstate->curexc_value = NULL;
512-
tstate->curexc_traceback = NULL;
513+
tstate->dict = NULL;
513514

514-
tstate->exc_state.exc_type = NULL;
515-
tstate->exc_state.exc_value = NULL;
516-
tstate->exc_state.exc_traceback = NULL;
517-
tstate->exc_state.previous_item = NULL;
518-
tstate->exc_info = &tstate->exc_state;
515+
tstate->curexc_type = NULL;
516+
tstate->curexc_value = NULL;
517+
tstate->curexc_traceback = NULL;
519518

520-
tstate->c_profilefunc = NULL;
521-
tstate->c_tracefunc = NULL;
522-
tstate->c_profileobj = NULL;
523-
tstate->c_traceobj = NULL;
519+
tstate->exc_state.exc_type = NULL;
520+
tstate->exc_state.exc_value = NULL;
521+
tstate->exc_state.exc_traceback = NULL;
522+
tstate->exc_state.previous_item = NULL;
523+
tstate->exc_info = &tstate->exc_state;
524524

525-
tstate->trash_delete_nesting = 0;
526-
tstate->trash_delete_later = NULL;
527-
tstate->on_delete = NULL;
528-
tstate->on_delete_data = NULL;
525+
tstate->c_profilefunc = NULL;
526+
tstate->c_tracefunc = NULL;
527+
tstate->c_profileobj = NULL;
528+
tstate->c_traceobj = NULL;
529529

530-
tstate->coroutine_origin_tracking_depth = 0;
530+
tstate->trash_delete_nesting = 0;
531+
tstate->trash_delete_later = NULL;
532+
tstate->on_delete = NULL;
533+
tstate->on_delete_data = NULL;
531534

532-
tstate->coroutine_wrapper = NULL;
533-
tstate->in_coroutine_wrapper = 0;
535+
tstate->coroutine_origin_tracking_depth = 0;
534536

535-
tstate->async_gen_firstiter = NULL;
536-
tstate->async_gen_finalizer = NULL;
537+
tstate->coroutine_wrapper = NULL;
538+
tstate->in_coroutine_wrapper = 0;
537539

538-
tstate->context = NULL;
539-
tstate->context_ver = 1;
540+
tstate->async_gen_firstiter = NULL;
541+
tstate->async_gen_finalizer = NULL;
540542

541-
tstate->id = ++interp->tstate_next_unique_id;
543+
tstate->context = NULL;
544+
tstate->context_ver = 1;
542545

543-
if (init)
544-
_PyThreadState_Init(tstate);
546+
tstate->id = ++interp->tstate_next_unique_id;
545547

546-
HEAD_LOCK();
547-
tstate->prev = NULL;
548-
tstate->next = interp->tstate_head;
549-
if (tstate->next)
550-
tstate->next->prev = tstate;
551-
interp->tstate_head = tstate;
552-
HEAD_UNLOCK();
548+
if (init) {
549+
_PyThreadState_Init(&_PyRuntime, tstate);
553550
}
554551

552+
HEAD_LOCK();
553+
tstate->prev = NULL;
554+
tstate->next = interp->tstate_head;
555+
if (tstate->next)
556+
tstate->next->prev = tstate;
557+
interp->tstate_head = tstate;
558+
HEAD_UNLOCK();
559+
555560
return tstate;
556561
}
557562

@@ -568,9 +573,9 @@ _PyThreadState_Prealloc(PyInterpreterState *interp)
568573
}
569574

570575
void
571-
_PyThreadState_Init(PyThreadState *tstate)
576+
_PyThreadState_Init(_PyRuntimeState *runtime, PyThreadState *tstate)
572577
{
573-
_PyGILState_NoteThreadState(tstate);
578+
_PyGILState_NoteThreadState(&runtime->gilstate, tstate);
574579
}
575580

576581
PyObject*
@@ -1037,17 +1042,23 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
10371042
Py_Initialize/Py_FinalizeEx
10381043
*/
10391044
void
1040-
_PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
1045+
_PyGILState_Init(PyInterpreterState *interp, PyThreadState *tstate)
10411046
{
1042-
assert(i && t); /* must init with valid states */
1043-
if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) {
1047+
/* must init with valid states */
1048+
assert(interp != NULL);
1049+
assert(tstate != NULL);
1050+
1051+
_PyRuntimeState *runtime = &_PyRuntime;
1052+
struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
1053+
1054+
if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) {
10441055
Py_FatalError("Could not allocate TSS entry");
10451056
}
1046-
_PyRuntime.gilstate.autoInterpreterState = i;
1047-
assert(PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL);
1048-
assert(t->gilstate_counter == 0);
1057+
gilstate->autoInterpreterState = interp;
1058+
assert(PyThread_tss_get(&gilstate->autoTSSkey) == NULL);
1059+
assert(tstate->gilstate_counter == 0);
10491060

1050-
_PyGILState_NoteThreadState(t);
1061+
_PyGILState_NoteThreadState(gilstate, tstate);
10511062
}
10521063

10531064
PyInterpreterState *
@@ -1104,13 +1115,14 @@ _PyGILState_Reinit(void)
11041115
a better fix for SF bug #1010677 than the first one attempted).
11051116
*/
11061117
static void
1107-
_PyGILState_NoteThreadState(PyThreadState* tstate)
1118+
_PyGILState_NoteThreadState(struct _gilstate_runtime_state *gilstate, PyThreadState* tstate)
11081119
{
11091120
/* If autoTSSkey isn't initialized, this must be the very first
11101121
threadstate created in Py_Initialize(). Don't do anything for now
11111122
(we'll be back here when _PyGILState_Init is called). */
1112-
if (!_PyRuntime.gilstate.autoInterpreterState)
1123+
if (!gilstate->autoInterpreterState) {
11131124
return;
1125+
}
11141126

11151127
/* Stick the thread state for this thread in thread specific storage.
11161128
@@ -1124,10 +1136,8 @@ _PyGILState_NoteThreadState(PyThreadState* tstate)
11241136
The first thread state created for that given OS level thread will
11251137
"win", which seems reasonable behaviour.
11261138
*/
1127-
if (PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL) {
1128-
if ((PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate)
1129-
) != 0)
1130-
{
1139+
if (PyThread_tss_get(&gilstate->autoTSSkey) == NULL) {
1140+
if ((PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate)) != 0) {
11311141
Py_FatalError("Couldn't create autoTSSkey mapping");
11321142
}
11331143
}

0 commit comments

Comments
 (0)