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.
This commit is contained in:
Victor Stinner 2020-05-05 20:27:47 +02:00 committed by GitHub
parent 0dd5e7a718
commit 7be4e350aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 5 deletions

View File

@ -50,7 +50,11 @@ extern PyObject *_PyEval_EvalCode(
PyObject *kwdefs, PyObject *closure, PyObject *kwdefs, PyObject *closure,
PyObject *name, PyObject *qualname); PyObject *name, PyObject *qualname);
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
extern int _PyEval_ThreadsInitialized(PyInterpreterState *interp);
#else
extern int _PyEval_ThreadsInitialized(struct pyruntimestate *runtime); extern int _PyEval_ThreadsInitialized(struct pyruntimestate *runtime);
#endif
extern PyStatus _PyEval_InitGIL(PyThreadState *tstate); extern PyStatus _PyEval_InitGIL(PyThreadState *tstate);
extern void _PyEval_FiniGIL(PyThreadState *tstate); extern void _PyEval_FiniGIL(PyThreadState *tstate);

View File

@ -46,6 +46,9 @@ struct _ceval_state {
/* Request for dropping the GIL */ /* Request for dropping the GIL */
_Py_atomic_int gil_drop_request; _Py_atomic_int gil_drop_request;
struct _pending_calls pending; struct _pending_calls pending;
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
struct _gil_runtime_state gil;
#endif
}; };

View File

@ -19,7 +19,9 @@ struct _ceval_runtime_state {
the main thread of the main interpreter can handle signals: see the main thread of the main interpreter can handle signals: see
_Py_ThreadCanHandleSignals(). */ _Py_ThreadCanHandleSignals(). */
_Py_atomic_int signals_pending; _Py_atomic_int signals_pending;
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
struct _gil_runtime_state gil; struct _gil_runtime_state gil;
#endif
}; };
/* GIL state */ /* GIL state */

View File

@ -250,6 +250,21 @@ ensure_tstate_not_null(const char *func, PyThreadState *tstate)
} }
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
int
_PyEval_ThreadsInitialized(PyInterpreterState *interp)
{
return gil_created(&interp->ceval.gil);
}
int
PyEval_ThreadsInitialized(void)
{
// Fatal error if there is no current interpreter
PyInterpreterState *interp = PyInterpreterState_Get();
return _PyEval_ThreadsInitialized(interp);
}
#else
int int
_PyEval_ThreadsInitialized(_PyRuntimeState *runtime) _PyEval_ThreadsInitialized(_PyRuntimeState *runtime)
{ {
@ -262,18 +277,25 @@ PyEval_ThreadsInitialized(void)
_PyRuntimeState *runtime = &_PyRuntime; _PyRuntimeState *runtime = &_PyRuntime;
return _PyEval_ThreadsInitialized(runtime); return _PyEval_ThreadsInitialized(runtime);
} }
#endif
PyStatus PyStatus
_PyEval_InitGIL(PyThreadState *tstate) _PyEval_InitGIL(PyThreadState *tstate)
{ {
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
if (!_Py_IsMainInterpreter(tstate)) { if (!_Py_IsMainInterpreter(tstate)) {
/* Currently, the GIL is shared by all interpreters, /* Currently, the GIL is shared by all interpreters,
and only the main interpreter is responsible to create and only the main interpreter is responsible to create
and destroy it. */ and destroy it. */
return _PyStatus_OK(); return _PyStatus_OK();
} }
#endif
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
struct _gil_runtime_state *gil = &tstate->interp->ceval.gil;
#else
struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil; struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
#endif
assert(!gil_created(gil)); assert(!gil_created(gil));
PyThread_init_thread(); PyThread_init_thread();
@ -288,14 +310,20 @@ _PyEval_InitGIL(PyThreadState *tstate)
void void
_PyEval_FiniGIL(PyThreadState *tstate) _PyEval_FiniGIL(PyThreadState *tstate)
{ {
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
if (!_Py_IsMainInterpreter(tstate)) { if (!_Py_IsMainInterpreter(tstate)) {
/* Currently, the GIL is shared by all interpreters, /* Currently, the GIL is shared by all interpreters,
and only the main interpreter is responsible to create and only the main interpreter is responsible to create
and destroy it. */ and destroy it. */
return; return;
} }
#endif
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
struct _gil_runtime_state *gil = &tstate->interp->ceval.gil;
#else
struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil; struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
#endif
if (!gil_created(gil)) { if (!gil_created(gil)) {
/* First Py_InitializeFromConfig() call: the GIL doesn't exist /* First Py_InitializeFromConfig() call: the GIL doesn't exist
yet: do nothing. */ yet: do nothing. */
@ -413,13 +441,18 @@ PyEval_ReleaseThread(PyThreadState *tstate)
void void
_PyEval_ReInitThreads(_PyRuntimeState *runtime) _PyEval_ReInitThreads(_PyRuntimeState *runtime)
{ {
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
ensure_tstate_not_null(__func__, tstate);
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
struct _gil_runtime_state *gil = &tstate->interp->ceval.gil;
#else
struct _gil_runtime_state *gil = &runtime->ceval.gil; struct _gil_runtime_state *gil = &runtime->ceval.gil;
#endif
if (!gil_created(gil)) { if (!gil_created(gil)) {
return; return;
} }
recreate_gil(gil); recreate_gil(gil);
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
ensure_tstate_not_null(__func__, tstate);
take_gil(tstate); take_gil(tstate);
@ -457,7 +490,11 @@ PyEval_SaveThread(void)
struct _ceval_runtime_state *ceval = &runtime->ceval; struct _ceval_runtime_state *ceval = &runtime->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval; struct _ceval_state *ceval2 = &tstate->interp->ceval;
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
assert(gil_created(&ceval2->gil));
#else
assert(gil_created(&ceval->gil)); assert(gil_created(&ceval->gil));
#endif
drop_gil(ceval, ceval2, tstate); drop_gil(ceval, ceval2, tstate);
return tstate; return tstate;
} }
@ -716,7 +753,9 @@ void
_PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval) _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
{ {
_Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT; _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT;
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
_gil_initialize(&ceval->gil); _gil_initialize(&ceval->gil);
#endif
} }
int int
@ -731,6 +770,11 @@ _PyEval_InitState(struct _ceval_state *ceval)
if (pending->lock == NULL) { if (pending->lock == NULL) {
return -1; return -1;
} }
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
_gil_initialize(&ceval->gil);
#endif
return 0; return 0;
} }

View File

@ -144,7 +144,11 @@ static void
drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2, drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2,
PyThreadState *tstate) PyThreadState *tstate)
{ {
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
struct _gil_runtime_state *gil = &ceval2->gil;
#else
struct _gil_runtime_state *gil = &ceval->gil; struct _gil_runtime_state *gil = &ceval->gil;
#endif
if (!_Py_atomic_load_relaxed(&gil->locked)) { if (!_Py_atomic_load_relaxed(&gil->locked)) {
Py_FatalError("drop_gil: GIL is not locked"); Py_FatalError("drop_gil: GIL is not locked");
} }
@ -228,7 +232,11 @@ take_gil(PyThreadState *tstate)
PyInterpreterState *interp = tstate->interp; PyInterpreterState *interp = tstate->interp;
struct _ceval_runtime_state *ceval = &interp->runtime->ceval; struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_state *ceval2 = &interp->ceval; struct _ceval_state *ceval2 = &interp->ceval;
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
struct _gil_runtime_state *gil = &ceval2->gil;
#else
struct _gil_runtime_state *gil = &ceval->gil; struct _gil_runtime_state *gil = &ceval->gil;
#endif
/* Check that _PyEval_InitThreads() was called to create the lock */ /* Check that _PyEval_InitThreads() was called to create the lock */
assert(gil_created(gil)); assert(gil_created(gil));
@ -320,10 +328,22 @@ _ready:
void _PyEval_SetSwitchInterval(unsigned long microseconds) void _PyEval_SetSwitchInterval(unsigned long microseconds)
{ {
_PyRuntime.ceval.gil.interval = microseconds; #ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
PyInterpreterState *interp = PyInterpreterState_Get();
struct _gil_runtime_state *gil = &interp->ceval.gil;
#else
struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
#endif
gil->interval = microseconds;
} }
unsigned long _PyEval_GetSwitchInterval() unsigned long _PyEval_GetSwitchInterval()
{ {
return _PyRuntime.ceval.gil.interval; #ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
PyInterpreterState *interp = PyInterpreterState_Get();
struct _gil_runtime_state *gil = &interp->ceval.gil;
#else
struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
#endif
return gil->interval;
} }

View File

@ -1561,9 +1561,13 @@ new_interpreter(PyThreadState **tstate_p, int isolated_subinterpreter)
/* Copy the current interpreter config into the new interpreter */ /* Copy the current interpreter config into the new interpreter */
const PyConfig *config; const PyConfig *config;
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
if (save_tstate != NULL) { if (save_tstate != NULL) {
config = _PyInterpreterState_GetConfig(save_tstate->interp); config = _PyInterpreterState_GetConfig(save_tstate->interp);
} else { }
else
#endif
{
/* No current thread state, copy from the main interpreter */ /* No current thread state, copy from the main interpreter */
PyInterpreterState *main_interp = PyInterpreterState_Main(); PyInterpreterState *main_interp = PyInterpreterState_Main();
config = _PyInterpreterState_GetConfig(main_interp); config = _PyInterpreterState_GetConfig(main_interp);