Skip to content

Commit 396e0a8

Browse files
bpo-36818: Add PyInterpreterState.runtime field. (gh-13129)
https://bugs.python.org/issue36818
1 parent 1c263e3 commit 396e0a8

File tree

11 files changed

+99
-103
lines changed

11 files changed

+99
-103
lines changed

Include/cpython/pystate.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ struct _ts {
110110
* if the thread holds the last reference to the lock, decref'ing the
111111
* lock will delete the lock, and that may trigger arbitrary Python code
112112
* if there's a weakref, with a callback, to the lock. But by this time
113-
* _PyRuntime.gilstate.tstate_current is already NULL, so only the simplest
114-
* of C code can be allowed to run (in particular it must not be possible to
115-
* release the GIL).
113+
* _PyRuntimeState.gilstate.tstate_current is already NULL, so only the
114+
* simplest of C code can be allowed to run (in particular it must not be
115+
* possible to release the GIL).
116116
* So instead of holding the lock directly, the tstate holds a weakref to
117117
* the lock: that's the value of on_delete_data below. Decref'ing a
118118
* weakref is harmless.

Include/internal/pycore_object.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ PyAPI_FUNC(int) _PyDict_CheckConsistency(PyObject *mp, int check_content);
1919
* NB: While the object is tracked by the collector, it must be safe to call the
2020
* ob_traverse method.
2121
*
22-
* Internal note: _PyRuntime.gc.generation0->_gc_prev doesn't have any bit flags
23-
* because it's not object header. So we don't use _PyGCHead_PREV() and
24-
* _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations.
22+
* Internal note: _PyRuntimeState.gc.generation0->_gc_prev doesn't have
23+
* any bit flags because it's not object header. So we don't use
24+
* _PyGCHead_PREV() and _PyGCHead_SET_PREV() for it to avoid unnecessary
25+
* bitwise operations.
2526
*
2627
* The PyObject_GC_Track() function is the public version of this macro.
2728
*/

Include/internal/pycore_pylifecycle.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,10 @@ extern PyStatus _PyFaulthandler_Init(int enable);
3939
extern int _PyTraceMalloc_Init(int enable);
4040
extern PyObject * _PyBuiltin_Init(void);
4141
extern PyStatus _PySys_Create(
42-
_PyRuntimeState *runtime,
4342
PyInterpreterState *interp,
4443
PyObject **sysmod_p);
4544
extern PyStatus _PySys_SetPreliminaryStderr(PyObject *sysdict);
46-
extern int _PySys_InitMain(
47-
_PyRuntimeState *runtime,
48-
PyInterpreterState *interp);
45+
extern int _PySys_InitMain(PyInterpreterState *interp);
4946
extern PyStatus _PyImport_Init(PyInterpreterState *interp);
5047
extern PyStatus _PyExc_Init(void);
5148
extern PyStatus _PyErr_Init(void);
@@ -86,10 +83,7 @@ extern void _PyHash_Fini(void);
8683
extern int _PyTraceMalloc_Fini(void);
8784
extern void _PyWarnings_Fini(PyInterpreterState *interp);
8885

89-
extern void _PyGILState_Init(
90-
_PyRuntimeState *runtime,
91-
PyInterpreterState *interp,
92-
PyThreadState *tstate);
86+
extern void _PyGILState_Init(PyThreadState *tstate);
9387
extern void _PyGILState_Fini(_PyRuntimeState *runtime);
9488

9589
PyAPI_FUNC(void) _PyGC_DumpShutdownStats(_PyRuntimeState *runtime);

Include/internal/pycore_pystate.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ extern "C" {
1919
#include "pycore_pymem.h"
2020
#include "pycore_warnings.h"
2121

22+
// forward
23+
struct pyruntimestate;
24+
2225

2326
/* ceval state */
2427

@@ -68,6 +71,7 @@ struct _is {
6871

6972
struct _is *next;
7073
struct _ts *tstate_head;
74+
struct pyruntimestate *runtime;
7175

7276
int64_t id;
7377
int64_t id_refcount;
@@ -296,12 +300,8 @@ PyAPI_FUNC(void) _PyRuntime_Finalize(void);
296300

297301
/* Other */
298302

299-
PyAPI_FUNC(void) _PyThreadState_Init(
300-
_PyRuntimeState *runtime,
301-
PyThreadState *tstate);
302-
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(
303-
_PyRuntimeState *runtime,
304-
PyThreadState *tstate);
303+
PyAPI_FUNC(void) _PyThreadState_Init(PyThreadState *tstate);
304+
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
305305

306306
PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap(
307307
struct _gilstate_runtime_state *gilstate,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add PyInterpreterState.runtime (and use it).

Modules/_threadmodule.c

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

997997
tstate = boot->tstate;
998998
tstate->thread_id = PyThread_get_thread_ident();
999-
_PyThreadState_Init(&_PyRuntime, tstate);
999+
_PyThreadState_Init(tstate);
10001000
PyEval_AcquireThread(tstate);
10011001
tstate->interp->num_threads++;
10021002
res = PyObject_Call(boot->func, boot->args, boot->keyw);

Python/ceval.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,9 @@ _PyEval_FiniThreads(struct _ceval_runtime_state *ceval)
217217
}
218218

219219
static inline void
220-
exit_thread_if_finalizing(_PyRuntimeState *runtime, PyThreadState *tstate)
220+
exit_thread_if_finalizing(PyThreadState *tstate)
221221
{
222+
_PyRuntimeState *runtime = tstate->interp->runtime;
222223
/* _Py_Finalizing is protected by the GIL */
223224
if (runtime->finalizing != NULL && !_Py_CURRENTLY_FINALIZING(runtime, tstate)) {
224225
drop_gil(&runtime->ceval, tstate);
@@ -236,7 +237,7 @@ PyEval_AcquireLock(void)
236237
Py_FatalError("PyEval_AcquireLock: current thread state is NULL");
237238
}
238239
take_gil(ceval, tstate);
239-
exit_thread_if_finalizing(runtime, tstate);
240+
exit_thread_if_finalizing(tstate);
240241
}
241242

242243
void
@@ -257,14 +258,15 @@ PyEval_AcquireThread(PyThreadState *tstate)
257258
if (tstate == NULL) {
258259
Py_FatalError("PyEval_AcquireThread: NULL new thread state");
259260
}
261+
assert(tstate->interp != NULL);
260262

261-
_PyRuntimeState *runtime = &_PyRuntime;
263+
_PyRuntimeState *runtime = tstate->interp->runtime;
262264
struct _ceval_runtime_state *ceval = &runtime->ceval;
263265

264266
/* Check someone has called PyEval_InitThreads() to create the lock */
265267
assert(gil_created(&ceval->gil));
266268
take_gil(ceval, tstate);
267-
exit_thread_if_finalizing(runtime, tstate);
269+
exit_thread_if_finalizing(tstate);
268270
if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) {
269271
Py_FatalError("PyEval_AcquireThread: non-NULL old thread state");
270272
}
@@ -276,8 +278,9 @@ PyEval_ReleaseThread(PyThreadState *tstate)
276278
if (tstate == NULL) {
277279
Py_FatalError("PyEval_ReleaseThread: NULL thread state");
278280
}
281+
assert(tstate->interp != NULL);
279282

280-
_PyRuntimeState *runtime = &_PyRuntime;
283+
_PyRuntimeState *runtime = tstate->interp->runtime;
281284
PyThreadState *new_tstate = _PyThreadState_Swap(&runtime->gilstate, NULL);
282285
if (new_tstate != tstate) {
283286
Py_FatalError("PyEval_ReleaseThread: wrong thread state");
@@ -308,7 +311,7 @@ _PyEval_ReInitThreads(_PyRuntimeState *runtime)
308311
}
309312

310313
/* Destroy all threads except the current one */
311-
_PyThreadState_DeleteExcept(runtime, current_tstate);
314+
_PyThreadState_DeleteExcept(current_tstate);
312315
}
313316

314317
/* This function is used to signal that async exceptions are waiting to be
@@ -337,17 +340,18 @@ PyEval_SaveThread(void)
337340
void
338341
PyEval_RestoreThread(PyThreadState *tstate)
339342
{
340-
_PyRuntimeState *runtime = &_PyRuntime;
341-
struct _ceval_runtime_state *ceval = &runtime->ceval;
342-
343343
if (tstate == NULL) {
344344
Py_FatalError("PyEval_RestoreThread: NULL tstate");
345345
}
346+
assert(tstate->interp != NULL);
347+
348+
_PyRuntimeState *runtime = tstate->interp->runtime;
349+
struct _ceval_runtime_state *ceval = &runtime->ceval;
346350
assert(gil_created(&ceval->gil));
347351

348352
int err = errno;
349353
take_gil(ceval, tstate);
350-
exit_thread_if_finalizing(runtime, tstate);
354+
exit_thread_if_finalizing(tstate);
351355
errno = err;
352356

353357
_PyThreadState_Swap(&runtime->gilstate, tstate);
@@ -1141,7 +1145,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
11411145
take_gil(ceval, tstate);
11421146

11431147
/* Check if we should make a quick exit. */
1144-
exit_thread_if_finalizing(runtime, tstate);
1148+
exit_thread_if_finalizing(tstate);
11451149

11461150
if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) {
11471151
Py_FatalError("ceval: orphan tstate");

Python/import.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,8 @@ PyImport_Cleanup(void)
541541
_PyGC_CollectNoFail();
542542
/* Dump GC stats before it's too late, since it uses the warnings
543543
machinery. */
544-
_PyGC_DumpShutdownStats(&_PyRuntime);
544+
_PyRuntimeState *runtime = interp->runtime;
545+
_PyGC_DumpShutdownStats(runtime);
545546

546547
/* Now, if there are any modules left alive, clear their globals to
547548
minimize potential leaks. All C extension modules actually end

Python/pylifecycle.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
545545
_PyEval_FiniThreads(&runtime->ceval);
546546

547547
/* Auto-thread-state API */
548-
_PyGILState_Init(runtime, interp, tstate);
548+
_PyGILState_Init(tstate);
549549

550550
/* Create the GIL */
551551
PyEval_InitThreads();
@@ -683,7 +683,7 @@ pyinit_config(_PyRuntimeState *runtime,
683683
}
684684

685685
PyObject *sysmod;
686-
status = _PySys_Create(runtime, interp, &sysmod);
686+
status = _PySys_Create(interp, &sysmod);
687687
if (_PyStatus_EXCEPTION(status)) {
688688
return status;
689689
}
@@ -892,8 +892,9 @@ _Py_ReconfigureMainInterpreter(PyInterpreterState *interp)
892892
* non-zero return code.
893893
*/
894894
static PyStatus
895-
pyinit_main(_PyRuntimeState *runtime, PyInterpreterState *interp)
895+
pyinit_main(PyInterpreterState *interp)
896896
{
897+
_PyRuntimeState *runtime = interp->runtime;
897898
if (!runtime->core_initialized) {
898899
return _PyStatus_ERR("runtime core not initialized");
899900
}
@@ -919,7 +920,7 @@ pyinit_main(_PyRuntimeState *runtime, PyInterpreterState *interp)
919920
return _PyStatus_ERR("can't initialize time");
920921
}
921922

922-
if (_PySys_InitMain(runtime, interp) < 0) {
923+
if (_PySys_InitMain(interp) < 0) {
923924
return _PyStatus_ERR("can't finish initializing sys");
924925
}
925926

@@ -999,7 +1000,7 @@ _Py_InitializeMain(void)
9991000
_PyRuntimeState *runtime = &_PyRuntime;
10001001
PyInterpreterState *interp = _PyRuntimeState_GetThreadState(runtime)->interp;
10011002

1002-
return pyinit_main(runtime, interp);
1003+
return pyinit_main(interp);
10031004
}
10041005

10051006

@@ -1026,7 +1027,7 @@ Py_InitializeFromConfig(const PyConfig *config)
10261027
config = &interp->config;
10271028

10281029
if (config->_init_main) {
1029-
status = pyinit_main(runtime, interp);
1030+
status = pyinit_main(interp);
10301031
if (_PyStatus_EXCEPTION(status)) {
10311032
return status;
10321033
}
@@ -1453,7 +1454,7 @@ new_interpreter(PyThreadState **tstate_p)
14531454
}
14541455
Py_INCREF(interp->sysdict);
14551456
PyDict_SetItemString(interp->sysdict, "modules", modules);
1456-
if (_PySys_InitMain(runtime, interp) < 0) {
1457+
if (_PySys_InitMain(interp) < 0) {
14571458
return _PyStatus_ERR("can't finish initializing sys");
14581459
}
14591460
}

0 commit comments

Comments
 (0)