Skip to content

Commit 0f39f69

Browse files
Actually make the GIL per-interpreter!
1 parent 3104796 commit 0f39f69

File tree

7 files changed

+20
-52
lines changed

7 files changed

+20
-52
lines changed

Include/internal/pycore_ceval.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ struct _ceval_runtime_state;
2121

2222

2323
extern void _Py_FinishPendingCalls(PyThreadState *tstate);
24-
extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *);
25-
extern void _PyEval_InitState(struct _ceval_state *, PyThread_type_lock);
24+
extern void _PyEval_InitState(PyInterpreterState *, PyThread_type_lock);
2625
extern void _PyEval_FiniState(struct _ceval_state *ceval);
2726
PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp);
2827
PyAPI_FUNC(int) _PyEval_AddPendingCall(

Include/internal/pycore_ceval_state.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ struct _ceval_runtime_state {
4949
the main thread of the main interpreter can handle signals: see
5050
_Py_ThreadCanHandleSignals(). */
5151
_Py_atomic_int signals_pending;
52-
53-
/* This is (only) used indirectly through PyInterpreterState.ceval.gil. */
54-
struct _gil_runtime_state gil;
5552
};
5653

5754
#ifdef PY_HAVE_PERF_TRAMPOLINE

Include/internal/pycore_interp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ struct _is {
178178
basis. Also see _PyRuntimeState regarding the various mutex fields.
179179
*/
180180

181+
/* The per-interpreter GIL, which might not be used. */
182+
struct _gil_runtime_state _gil;
183+
181184
/* the initial PyInterpreterState.threads.head */
182185
PyThreadState _initial_thread;
183186
};

Include/internal/pycore_runtime.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ struct _getargs_runtime_state {
3232
struct _PyArg_Parser *static_parsers;
3333
};
3434

35-
/* ceval state */
36-
3735
/* GIL state */
3836

3937
struct _gilstate_runtime_state {

Python/ceval_gil.c

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -464,17 +464,15 @@ take_gil(PyThreadState *tstate)
464464

465465
void _PyEval_SetSwitchInterval(unsigned long microseconds)
466466
{
467-
/* XXX per-interpreter GIL */
468-
PyInterpreterState *interp = _PyInterpreterState_Main();
467+
PyInterpreterState *interp = _PyInterpreterState_Get();
469468
struct _gil_runtime_state *gil = interp->ceval.gil;
470469
assert(gil != NULL);
471470
gil->interval = microseconds;
472471
}
473472

474473
unsigned long _PyEval_GetSwitchInterval(void)
475474
{
476-
/* XXX per-interpreter GIL */
477-
PyInterpreterState *interp = _PyInterpreterState_Main();
475+
PyInterpreterState *interp = _PyInterpreterState_Get();
478476
struct _gil_runtime_state *gil = interp->ceval.gil;
479477
assert(gil != NULL);
480478
return gil->interval;
@@ -484,7 +482,9 @@ unsigned long _PyEval_GetSwitchInterval(void)
484482
int
485483
_PyEval_ThreadsInitialized(void)
486484
{
487-
/* XXX per-interpreter GIL */
485+
/* XXX This is only needed for an assert in PyGILState_Ensure(),
486+
* which currently does not work with subinterpreters.
487+
* Thus we only use the main interpreter. */
488488
PyInterpreterState *interp = _PyInterpreterState_Main();
489489
if (interp == NULL) {
490490
return 0;
@@ -532,27 +532,16 @@ _PyEval_InitGIL(PyThreadState *tstate, int own_gil)
532532
assert(tstate->interp->ceval.gil == NULL);
533533
int locked;
534534
if (!own_gil) {
535+
/* The interpreter will share the main interpreter's instead. */
535536
PyInterpreterState *main_interp = _PyInterpreterState_Main();
536537
assert(tstate->interp != main_interp);
537538
struct _gil_runtime_state *gil = main_interp->ceval.gil;
538539
init_shared_gil(tstate->interp, gil);
539540
locked = current_thread_holds_gil(gil, tstate);
540541
}
541-
/* XXX per-interpreter GIL */
542-
else if (!_Py_IsMainInterpreter(tstate->interp)) {
543-
/* Currently, the GIL is shared by all interpreters,
544-
and only the main interpreter is responsible to create
545-
and destroy it. */
546-
struct _gil_runtime_state *main_gil = _PyInterpreterState_Main()->ceval.gil;
547-
init_shared_gil(tstate->interp, main_gil);
548-
// XXX For now we lie.
549-
tstate->interp->ceval.own_gil = 1;
550-
locked = current_thread_holds_gil(main_gil, tstate);
551-
}
552542
else {
553543
PyThread_init_thread();
554-
// XXX per-interpreter GIL: switch to interp->_gil.
555-
init_own_gil(tstate->interp, &tstate->interp->runtime->ceval.gil);
544+
init_own_gil(tstate->interp, &tstate->interp->_gil);
556545
locked = 0;
557546
}
558547
if (!locked) {
@@ -565,30 +554,20 @@ _PyEval_InitGIL(PyThreadState *tstate, int own_gil)
565554
void
566555
_PyEval_FiniGIL(PyInterpreterState *interp)
567556
{
568-
if (interp->ceval.gil == NULL) {
557+
struct _gil_runtime_state *gil = interp->ceval.gil;
558+
if (gil == NULL) {
569559
/* It was already finalized (or hasn't been initialized yet). */
570560
assert(!interp->ceval.own_gil);
571561
return;
572562
}
573563
else if (!interp->ceval.own_gil) {
574564
PyInterpreterState *main_interp = _PyInterpreterState_Main();
575-
assert(interp != main_interp);
565+
assert(main_interp != NULL && interp != main_interp);
576566
assert(interp->ceval.gil == main_interp->ceval.gil);
577567
interp->ceval.gil = NULL;
578568
return;
579569
}
580570

581-
/* XXX per-interpreter GIL */
582-
struct _gil_runtime_state *gil = &interp->runtime->ceval.gil;
583-
if (!_Py_IsMainInterpreter(interp)) {
584-
/* Currently, the GIL is shared by all interpreters,
585-
and only the main interpreter is responsible to create
586-
and destroy it. */
587-
assert(interp->ceval.gil == gil);
588-
interp->ceval.gil = NULL;
589-
return;
590-
}
591-
592571
if (!gil_created(gil)) {
593572
/* First Py_InitializeFromConfig() call: the GIL doesn't exist
594573
yet: do nothing. */
@@ -972,21 +951,13 @@ Py_MakePendingCalls(void)
972951
return 0;
973952
}
974953

975-
/* The interpreter's recursion limit */
976-
977954
void
978-
_PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
955+
_PyEval_InitState(PyInterpreterState *interp, PyThread_type_lock pending_lock)
979956
{
980-
/* XXX per-interpreter GIL */
981-
_gil_initialize(&ceval->gil);
982-
}
957+
_gil_initialize(&interp->_gil);
983958

984-
void
985-
_PyEval_InitState(struct _ceval_state *ceval, PyThread_type_lock pending_lock)
986-
{
987-
struct _pending_calls *pending = &ceval->pending;
959+
struct _pending_calls *pending = &interp->ceval.pending;
988960
assert(pending->lock == NULL);
989-
990961
pending->lock = pending_lock;
991962
}
992963

Python/pylifecycle.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2039,6 +2039,8 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config)
20392039
/* Copy the current interpreter config into the new interpreter */
20402040
const PyConfig *src_config;
20412041
if (save_tstate != NULL) {
2042+
// XXX Might new_interpreter() have been called without the GIL held?
2043+
_PyEval_ReleaseLock(save_tstate);
20422044
src_config = _PyInterpreterState_GetConfig(save_tstate->interp);
20432045
}
20442046
else

Python/pystate.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,6 @@ init_runtime(_PyRuntimeState *runtime,
425425
runtime->open_code_userdata = open_code_userdata;
426426
runtime->audit_hook_head = audit_hook_head;
427427

428-
_PyEval_InitRuntimeState(&runtime->ceval);
429-
430428
PyPreConfig_InitPythonConfig(&runtime->preconfig);
431429

432430
PyThread_type_lock *lockptrs[NUMLOCKS] = {
@@ -682,7 +680,7 @@ init_interpreter(PyInterpreterState *interp,
682680
memcpy(&interp->obmalloc.pools.used, temp, sizeof(temp));
683681
}
684682

685-
_PyEval_InitState(&interp->ceval, pending_lock);
683+
_PyEval_InitState(interp, pending_lock);
686684
_PyGC_InitState(&interp->gc);
687685
PyConfig_InitPythonConfig(&interp->config);
688686
_PyType_InitCache(interp);

0 commit comments

Comments
 (0)