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:
parent
0dd5e7a718
commit
7be4e350aa
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue