Skip to content

Commit 7be4e35

Browse files
authored
bpo-40513: Per-interpreter GIL (GH-19943)
In the experimental isolated subinterpreters build mode, the GIL is now per-interpreter. Move gil from _PyRuntimeState.ceval to PyInterpreterState.ceval. new_interpreter() always get the config from the main interpreter.
1 parent 0dd5e7a commit 7be4e35

File tree

6 files changed

+82
-5
lines changed

6 files changed

+82
-5
lines changed

Include/internal/pycore_ceval.h

+4
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ extern PyObject *_PyEval_EvalCode(
5050
PyObject *kwdefs, PyObject *closure,
5151
PyObject *name, PyObject *qualname);
5252

53+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
54+
extern int _PyEval_ThreadsInitialized(PyInterpreterState *interp);
55+
#else
5356
extern int _PyEval_ThreadsInitialized(struct pyruntimestate *runtime);
57+
#endif
5458
extern PyStatus _PyEval_InitGIL(PyThreadState *tstate);
5559
extern void _PyEval_FiniGIL(PyThreadState *tstate);
5660

Include/internal/pycore_interp.h

+3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ struct _ceval_state {
4646
/* Request for dropping the GIL */
4747
_Py_atomic_int gil_drop_request;
4848
struct _pending_calls pending;
49+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
50+
struct _gil_runtime_state gil;
51+
#endif
4952
};
5053

5154

Include/internal/pycore_runtime.h

+2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ struct _ceval_runtime_state {
1919
the main thread of the main interpreter can handle signals: see
2020
_Py_ThreadCanHandleSignals(). */
2121
_Py_atomic_int signals_pending;
22+
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
2223
struct _gil_runtime_state gil;
24+
#endif
2325
};
2426

2527
/* GIL state */

Python/ceval.c

+46-2
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,21 @@ ensure_tstate_not_null(const char *func, PyThreadState *tstate)
250250
}
251251

252252

253+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
254+
int
255+
_PyEval_ThreadsInitialized(PyInterpreterState *interp)
256+
{
257+
return gil_created(&interp->ceval.gil);
258+
}
259+
260+
int
261+
PyEval_ThreadsInitialized(void)
262+
{
263+
// Fatal error if there is no current interpreter
264+
PyInterpreterState *interp = PyInterpreterState_Get();
265+
return _PyEval_ThreadsInitialized(interp);
266+
}
267+
#else
253268
int
254269
_PyEval_ThreadsInitialized(_PyRuntimeState *runtime)
255270
{
@@ -262,18 +277,25 @@ PyEval_ThreadsInitialized(void)
262277
_PyRuntimeState *runtime = &_PyRuntime;
263278
return _PyEval_ThreadsInitialized(runtime);
264279
}
280+
#endif
265281

266282
PyStatus
267283
_PyEval_InitGIL(PyThreadState *tstate)
268284
{
285+
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
269286
if (!_Py_IsMainInterpreter(tstate)) {
270287
/* Currently, the GIL is shared by all interpreters,
271288
and only the main interpreter is responsible to create
272289
and destroy it. */
273290
return _PyStatus_OK();
274291
}
292+
#endif
275293

294+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
295+
struct _gil_runtime_state *gil = &tstate->interp->ceval.gil;
296+
#else
276297
struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
298+
#endif
277299
assert(!gil_created(gil));
278300

279301
PyThread_init_thread();
@@ -288,14 +310,20 @@ _PyEval_InitGIL(PyThreadState *tstate)
288310
void
289311
_PyEval_FiniGIL(PyThreadState *tstate)
290312
{
313+
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
291314
if (!_Py_IsMainInterpreter(tstate)) {
292315
/* Currently, the GIL is shared by all interpreters,
293316
and only the main interpreter is responsible to create
294317
and destroy it. */
295318
return;
296319
}
320+
#endif
297321

322+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
323+
struct _gil_runtime_state *gil = &tstate->interp->ceval.gil;
324+
#else
298325
struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
326+
#endif
299327
if (!gil_created(gil)) {
300328
/* First Py_InitializeFromConfig() call: the GIL doesn't exist
301329
yet: do nothing. */
@@ -413,13 +441,18 @@ PyEval_ReleaseThread(PyThreadState *tstate)
413441
void
414442
_PyEval_ReInitThreads(_PyRuntimeState *runtime)
415443
{
444+
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
445+
ensure_tstate_not_null(__func__, tstate);
446+
447+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
448+
struct _gil_runtime_state *gil = &tstate->interp->ceval.gil;
449+
#else
416450
struct _gil_runtime_state *gil = &runtime->ceval.gil;
451+
#endif
417452
if (!gil_created(gil)) {
418453
return;
419454
}
420455
recreate_gil(gil);
421-
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
422-
ensure_tstate_not_null(__func__, tstate);
423456

424457
take_gil(tstate);
425458

@@ -457,7 +490,11 @@ PyEval_SaveThread(void)
457490

458491
struct _ceval_runtime_state *ceval = &runtime->ceval;
459492
struct _ceval_state *ceval2 = &tstate->interp->ceval;
493+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
494+
assert(gil_created(&ceval2->gil));
495+
#else
460496
assert(gil_created(&ceval->gil));
497+
#endif
461498
drop_gil(ceval, ceval2, tstate);
462499
return tstate;
463500
}
@@ -716,7 +753,9 @@ void
716753
_PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
717754
{
718755
_Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT;
756+
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
719757
_gil_initialize(&ceval->gil);
758+
#endif
720759
}
721760

722761
int
@@ -731,6 +770,11 @@ _PyEval_InitState(struct _ceval_state *ceval)
731770
if (pending->lock == NULL) {
732771
return -1;
733772
}
773+
774+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
775+
_gil_initialize(&ceval->gil);
776+
#endif
777+
734778
return 0;
735779
}
736780

Python/ceval_gil.h

+22-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,11 @@ static void
144144
drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2,
145145
PyThreadState *tstate)
146146
{
147+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
148+
struct _gil_runtime_state *gil = &ceval2->gil;
149+
#else
147150
struct _gil_runtime_state *gil = &ceval->gil;
151+
#endif
148152
if (!_Py_atomic_load_relaxed(&gil->locked)) {
149153
Py_FatalError("drop_gil: GIL is not locked");
150154
}
@@ -228,7 +232,11 @@ take_gil(PyThreadState *tstate)
228232
PyInterpreterState *interp = tstate->interp;
229233
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
230234
struct _ceval_state *ceval2 = &interp->ceval;
235+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
236+
struct _gil_runtime_state *gil = &ceval2->gil;
237+
#else
231238
struct _gil_runtime_state *gil = &ceval->gil;
239+
#endif
232240

233241
/* Check that _PyEval_InitThreads() was called to create the lock */
234242
assert(gil_created(gil));
@@ -320,10 +328,22 @@ take_gil(PyThreadState *tstate)
320328

321329
void _PyEval_SetSwitchInterval(unsigned long microseconds)
322330
{
323-
_PyRuntime.ceval.gil.interval = microseconds;
331+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
332+
PyInterpreterState *interp = PyInterpreterState_Get();
333+
struct _gil_runtime_state *gil = &interp->ceval.gil;
334+
#else
335+
struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
336+
#endif
337+
gil->interval = microseconds;
324338
}
325339

326340
unsigned long _PyEval_GetSwitchInterval()
327341
{
328-
return _PyRuntime.ceval.gil.interval;
342+
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
343+
PyInterpreterState *interp = PyInterpreterState_Get();
344+
struct _gil_runtime_state *gil = &interp->ceval.gil;
345+
#else
346+
struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
347+
#endif
348+
return gil->interval;
329349
}

Python/pylifecycle.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -1561,9 +1561,13 @@ new_interpreter(PyThreadState **tstate_p, int isolated_subinterpreter)
15611561

15621562
/* Copy the current interpreter config into the new interpreter */
15631563
const PyConfig *config;
1564+
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
15641565
if (save_tstate != NULL) {
15651566
config = _PyInterpreterState_GetConfig(save_tstate->interp);
1566-
} else {
1567+
}
1568+
else
1569+
#endif
1570+
{
15671571
/* No current thread state, copy from the main interpreter */
15681572
PyInterpreterState *main_interp = PyInterpreterState_Main();
15691573
config = _PyInterpreterState_GetConfig(main_interp);

0 commit comments

Comments
 (0)