From 2aad06aa8f60e8487de4832309597617f83dcad1 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 10:30:04 -0600 Subject: [PATCH 01/17] Add a comment. --- Include/internal/pycore_gil.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Include/internal/pycore_gil.h b/Include/internal/pycore_gil.h index 8ebad37b686cd4..ff405e13270e01 100644 --- a/Include/internal/pycore_gil.h +++ b/Include/internal/pycore_gil.h @@ -20,6 +20,7 @@ extern "C" { #undef FORCE_SWITCHING #define FORCE_SWITCHING +/* ** The GIL ** */ struct _gil_runtime_state { /* microseconds (the Python API uses seconds, though) */ unsigned long interval; From e55fbdd15b651f3fbef05c630220f624d30edcd8 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 10:42:43 -0600 Subject: [PATCH 02/17] _gil_runtime_state -> _gil_state. --- Include/internal/pycore_gil.h | 2 +- Include/internal/pycore_interp.h | 1 + Include/internal/pycore_runtime.h | 4 ++-- Python/ceval_gil.c | 24 ++++++++++++------------ 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Include/internal/pycore_gil.h b/Include/internal/pycore_gil.h index ff405e13270e01..56bcc1ca2c61ef 100644 --- a/Include/internal/pycore_gil.h +++ b/Include/internal/pycore_gil.h @@ -21,7 +21,7 @@ extern "C" { #define FORCE_SWITCHING /* ** The GIL ** */ -struct _gil_runtime_state { +struct _gil_state { /* microseconds (the Python API uses seconds, though) */ unsigned long interval; /* Last PyThreadState holding / having held the GIL. This helps us diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index e7f914ec2fe521..fea6c8fbffe14b 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -18,6 +18,7 @@ extern "C" { #include "pycore_exceptions.h" // struct _Py_exc_state #include "pycore_floatobject.h" // struct _Py_float_state #include "pycore_genobject.h" // struct _Py_async_gen_state +#include "pycore_gil.h" // struct _gil_state #include "pycore_gc.h" // struct _gc_runtime_state #include "pycore_list.h" // struct _Py_list_state #include "pycore_tuple.h" // struct _Py_tuple_state diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index 2c04ead45869fc..e77c78ec28c9e2 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -9,7 +9,7 @@ extern "C" { #endif #include "pycore_atomic.h" /* _Py_atomic_address */ -#include "pycore_gil.h" // struct _gil_runtime_state +#include "pycore_gil.h" // struct _gil_state #include "pycore_global_objects.h" // struct _Py_global_objects #include "pycore_interp.h" // PyInterpreterState #include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids @@ -26,7 +26,7 @@ struct _ceval_runtime_state { the main thread of the main interpreter can handle signals: see _Py_ThreadCanHandleSignals(). */ _Py_atomic_int signals_pending; - struct _gil_runtime_state gil; + struct _gil_state gil; }; /* GIL state */ diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index a6790866766795..5c4f1cb5811061 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -218,19 +218,19 @@ is_tstate_valid(PyThreadState *tstate) #define DEFAULT_INTERVAL 5000 -static void _gil_initialize(struct _gil_runtime_state *gil) +static void _gil_initialize(struct _gil_state *gil) { _Py_atomic_int uninitialized = {-1}; gil->locked = uninitialized; gil->interval = DEFAULT_INTERVAL; } -static int gil_created(struct _gil_runtime_state *gil) +static int gil_created(struct _gil_state *gil) { return (_Py_atomic_load_explicit(&gil->locked, _Py_memory_order_acquire) >= 0); } -static void create_gil(struct _gil_runtime_state *gil) +static void create_gil(struct _gil_state *gil) { MUTEX_INIT(gil->mutex); #ifdef FORCE_SWITCHING @@ -245,7 +245,7 @@ static void create_gil(struct _gil_runtime_state *gil) _Py_atomic_store_explicit(&gil->locked, 0, _Py_memory_order_release); } -static void destroy_gil(struct _gil_runtime_state *gil) +static void destroy_gil(struct _gil_state *gil) { /* some pthread-like implementations tie the mutex to the cond * and must have the cond destroyed first. @@ -262,7 +262,7 @@ static void destroy_gil(struct _gil_runtime_state *gil) } #ifdef HAVE_FORK -static void recreate_gil(struct _gil_runtime_state *gil) +static void recreate_gil(struct _gil_state *gil) { _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked); /* XXX should we destroy the old OS resources here? */ @@ -274,7 +274,7 @@ static void drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2, PyThreadState *tstate) { - struct _gil_runtime_state *gil = &ceval->gil; + struct _gil_state *gil = &ceval->gil; if (!_Py_atomic_load_relaxed(&gil->locked)) { Py_FatalError("drop_gil: GIL is not locked"); } @@ -358,7 +358,7 @@ take_gil(PyThreadState *tstate) PyInterpreterState *interp = tstate->interp; struct _ceval_runtime_state *ceval = &interp->runtime->ceval; struct _ceval_state *ceval2 = &interp->ceval; - struct _gil_runtime_state *gil = &ceval->gil; + struct _gil_state *gil = &ceval->gil; /* Check that _PyEval_InitThreads() was called to create the lock */ assert(gil_created(gil)); @@ -450,13 +450,13 @@ take_gil(PyThreadState *tstate) void _PyEval_SetSwitchInterval(unsigned long microseconds) { - struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil; + struct _gil_state *gil = &_PyRuntime.ceval.gil; gil->interval = microseconds; } unsigned long _PyEval_GetSwitchInterval() { - struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil; + struct _gil_state *gil = &_PyRuntime.ceval.gil; return gil->interval; } @@ -484,7 +484,7 @@ _PyEval_InitGIL(PyThreadState *tstate) return _PyStatus_OK(); } - struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil; + struct _gil_state *gil = &tstate->interp->runtime->ceval.gil; assert(!gil_created(gil)); PyThread_init_thread(); @@ -506,7 +506,7 @@ _PyEval_FiniGIL(PyInterpreterState *interp) return; } - struct _gil_runtime_state *gil = &interp->runtime->ceval.gil; + struct _gil_state *gil = &interp->runtime->ceval.gil; if (!gil_created(gil)) { /* First Py_InitializeFromConfig() call: the GIL doesn't exist yet: do nothing. */ @@ -598,7 +598,7 @@ _PyEval_ReInitThreads(PyThreadState *tstate) { _PyRuntimeState *runtime = tstate->interp->runtime; - struct _gil_runtime_state *gil = &runtime->ceval.gil; + struct _gil_state *gil = &runtime->ceval.gil; if (!gil_created(gil)) { return _PyStatus_OK(); } From 711b19d43b7dfaa8facad06a8b50276f3232204d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 11:50:57 -0600 Subject: [PATCH 03/17] Pass PyInterpreterState to _PyEval_ThreadInitialized(). --- Include/internal/pycore_ceval.h | 2 +- Python/ceval_gil.c | 14 ++++++++++---- Python/pystate.c | 7 ++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 4914948c6ca744..bc8cdfb6a5a21a 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -103,7 +103,7 @@ _PyEval_Vector(PyThreadState *tstate, PyObject* const* args, size_t argcount, PyObject *kwnames); -extern int _PyEval_ThreadsInitialized(struct pyruntimestate *runtime); +extern int _PyEval_ThreadsInitialized(PyInterpreterState *interp); extern PyStatus _PyEval_InitGIL(PyThreadState *tstate); extern void _PyEval_FiniGIL(PyInterpreterState *interp); diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 5c4f1cb5811061..a3d1740dd9d262 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -462,16 +462,22 @@ unsigned long _PyEval_GetSwitchInterval() int -_PyEval_ThreadsInitialized(_PyRuntimeState *runtime) +_PyEval_ThreadsInitialized(PyInterpreterState *interp) { - return gil_created(&runtime->ceval.gil); + if (interp == NULL) { + interp = &_PyRuntime.main; + if (interp == NULL) { + return 0; + } + } + return gil_created(&interp->runtime->ceval.gil); } int PyEval_ThreadsInitialized(void) { - _PyRuntimeState *runtime = &_PyRuntime; - return _PyEval_ThreadsInitialized(runtime); + PyInterpreterState *interp = _PyInterpreterState_GET(); + return _PyEval_ThreadsInitialized(interp); } PyStatus diff --git a/Python/pystate.c b/Python/pystate.c index a0d61d7ebb3be9..75a4aa2e9420eb 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1677,9 +1677,10 @@ PyGILState_Ensure(void) spells out other issues. Embedders are expected to have called Py_Initialize(). */ - /* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been - called by Py_Initialize() */ - assert(_PyEval_ThreadsInitialized(runtime)); + /* Ensure that _PyEval_InitThreads() has been called by Py_Initialize() */ + // XXX Use the appropriate interpreter. + assert(runtime->main && _PyEval_ThreadsInitialized(runtime->main)); + /* Ensure that _PyGILState_Init() has been called by Py_Initialize() */ assert(gilstate->autoInterpreterState); PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey); From dba446005c301df7c5482f53de79a298c09acb71 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 12:38:22 -0600 Subject: [PATCH 04/17] runtime->main -> runtime->interpreters.main. --- Python/ceval_gil.c | 2 +- Python/pystate.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index a3d1740dd9d262..c0e16330c62c74 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -465,7 +465,7 @@ int _PyEval_ThreadsInitialized(PyInterpreterState *interp) { if (interp == NULL) { - interp = &_PyRuntime.main; + interp = _PyRuntime.interpreters.main; if (interp == NULL) { return 0; } diff --git a/Python/pystate.c b/Python/pystate.c index 75a4aa2e9420eb..196b0bdfb70534 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1679,7 +1679,8 @@ PyGILState_Ensure(void) /* Ensure that _PyEval_InitThreads() has been called by Py_Initialize() */ // XXX Use the appropriate interpreter. - assert(runtime->main && _PyEval_ThreadsInitialized(runtime->main)); + assert(runtime->interpreters.main && + _PyEval_ThreadsInitialized(runtime->interpreters.main)); /* Ensure that _PyGILState_Init() has been called by Py_Initialize() */ assert(gilstate->autoInterpreterState); From 5342672d57a40cd4b24b4b96fd8112cbf5cde9aa Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 12:39:01 -0600 Subject: [PATCH 05/17] Pass PyInterpreterState to _PyEval_InitState(). --- Include/internal/pycore_ceval.h | 2 +- Python/ceval_gil.c | 5 +++-- Python/pystate.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index bc8cdfb6a5a21a..5dabb9d35040db 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -29,7 +29,7 @@ struct _ceval_runtime_state; extern void _Py_FinishPendingCalls(PyThreadState *tstate); extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *); -extern void _PyEval_InitState(struct _ceval_state *, PyThread_type_lock); +extern void _PyEval_InitState(PyInterpreterState *, PyThread_type_lock); extern void _PyEval_FiniState(struct _ceval_state *ceval); PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp); PyAPI_FUNC(int) _PyEval_AddPendingCall( diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index c0e16330c62c74..6877988244dae7 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -908,11 +908,12 @@ _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval) } void -_PyEval_InitState(struct _ceval_state *ceval, PyThread_type_lock pending_lock) +_PyEval_InitState(PyInterpreterState *interp, PyThread_type_lock pending_lock) { + struct _ceval_state *ceval = &interp->ceval; + struct _pending_calls *pending = &ceval->pending; assert(pending->lock == NULL); - pending->lock = pending_lock; } diff --git a/Python/pystate.c b/Python/pystate.c index 196b0bdfb70534..fa2a8f9541d2ad 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -305,7 +305,7 @@ init_interpreter(PyInterpreterState *interp, assert(next != NULL || (interp == runtime->interpreters.main)); interp->next = next; - _PyEval_InitState(&interp->ceval, pending_lock); + _PyEval_InitState(interp, pending_lock); _PyGC_InitState(&interp->gc); PyConfig_InitPythonConfig(&interp->config); _PyType_InitCache(interp); From f2361d7b88464d6557967214175615503269af9f Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 14:01:47 -0600 Subject: [PATCH 06/17] Label some struct fields. --- Include/internal/pycore_interp.h | 1 + Include/internal/pycore_runtime.h | 1 + 2 files changed, 2 insertions(+) diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index fea6c8fbffe14b..d8da63f427f458 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -50,6 +50,7 @@ struct _ceval_state { _Py_atomic_int eval_breaker; /* Request for dropping the GIL */ _Py_atomic_int gil_drop_request; + /* Pending calls */ struct _pending_calls pending; }; diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index e77c78ec28c9e2..cf2b240c72e86b 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -26,6 +26,7 @@ struct _ceval_runtime_state { the main thread of the main interpreter can handle signals: see _Py_ThreadCanHandleSignals(). */ _Py_atomic_int signals_pending; + /* The GIL */ struct _gil_state gil; }; From adc09a05106baa925626463afd6a652776b10ca7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 15:19:47 -0600 Subject: [PATCH 07/17] Add _get_gil(). --- Python/ceval_gil.c | 161 ++++++++++++++++++++++++--------------------- 1 file changed, 85 insertions(+), 76 deletions(-) diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 6877988244dae7..52c2987aa77046 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -60,70 +60,70 @@ the GIL eventually anyway. */ static inline void COMPUTE_EVAL_BREAKER(PyInterpreterState *interp, - struct _ceval_runtime_state *ceval, - struct _ceval_state *ceval2) + struct _ceval_runtime_state *shared_ceval, + struct _ceval_state *ceval) { - _Py_atomic_store_relaxed(&ceval2->eval_breaker, - _Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request) - | (_Py_atomic_load_relaxed_int32(&ceval->signals_pending) + _Py_atomic_store_relaxed(&ceval->eval_breaker, + _Py_atomic_load_relaxed_int32(&ceval->gil_drop_request) + | (_Py_atomic_load_relaxed_int32(&shared_ceval->signals_pending) && _Py_ThreadCanHandleSignals(interp)) - | (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do) + | (_Py_atomic_load_relaxed_int32(&ceval->pending.calls_to_do) && _Py_ThreadCanHandlePendingCalls()) - | ceval2->pending.async_exc); + | ceval->pending.async_exc); } static inline void SET_GIL_DROP_REQUEST(PyInterpreterState *interp) { - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 1); - _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); + struct _ceval_state *ceval = &interp->ceval; + _Py_atomic_store_relaxed(&ceval->gil_drop_request, 1); + _Py_atomic_store_relaxed(&ceval->eval_breaker, 1); } static inline void RESET_GIL_DROP_REQUEST(PyInterpreterState *interp) { - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 0); - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + struct _ceval_runtime_state *shared_ceval = &interp->runtime->ceval; + struct _ceval_state *ceval = &interp->ceval; + _Py_atomic_store_relaxed(&ceval->gil_drop_request, 0); + COMPUTE_EVAL_BREAKER(interp, shared_ceval, ceval); } static inline void SIGNAL_PENDING_CALLS(PyInterpreterState *interp) { - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1); - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + struct _ceval_runtime_state *shared_ceval = &interp->runtime->ceval; + struct _ceval_state *ceval = &interp->ceval; + _Py_atomic_store_relaxed(&ceval->pending.calls_to_do, 1); + COMPUTE_EVAL_BREAKER(interp, shared_ceval, ceval); } static inline void UNSIGNAL_PENDING_CALLS(PyInterpreterState *interp) { - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0); - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + struct _ceval_runtime_state *shared_ceval = &interp->runtime->ceval; + struct _ceval_state *ceval = &interp->ceval; + _Py_atomic_store_relaxed(&ceval->pending.calls_to_do, 0); + COMPUTE_EVAL_BREAKER(interp, shared_ceval, ceval); } static inline void SIGNAL_PENDING_SIGNALS(PyInterpreterState *interp, int force) { - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval->signals_pending, 1); + struct _ceval_runtime_state *shared_ceval = &interp->runtime->ceval; + struct _ceval_state *ceval = &interp->ceval; + _Py_atomic_store_relaxed(&shared_ceval->signals_pending, 1); if (force) { - _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); + _Py_atomic_store_relaxed(&ceval->eval_breaker, 1); } else { /* eval_breaker is not set to 1 if thread_can_handle_signals() is false */ - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + COMPUTE_EVAL_BREAKER(interp, shared_ceval, ceval); } } @@ -131,29 +131,29 @@ SIGNAL_PENDING_SIGNALS(PyInterpreterState *interp, int force) static inline void UNSIGNAL_PENDING_SIGNALS(PyInterpreterState *interp) { - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval->signals_pending, 0); - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + struct _ceval_runtime_state *shared_ceval = &interp->runtime->ceval; + struct _ceval_state *ceval = &interp->ceval; + _Py_atomic_store_relaxed(&shared_ceval->signals_pending, 0); + COMPUTE_EVAL_BREAKER(interp, shared_ceval, ceval); } static inline void SIGNAL_ASYNC_EXC(PyInterpreterState *interp) { - struct _ceval_state *ceval2 = &interp->ceval; - ceval2->pending.async_exc = 1; - _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); + struct _ceval_state *ceval = &interp->ceval; + ceval->pending.async_exc = 1; + _Py_atomic_store_relaxed(&ceval->eval_breaker, 1); } static inline void UNSIGNAL_ASYNC_EXC(PyInterpreterState *interp) { - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - ceval2->pending.async_exc = 0; - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + struct _ceval_runtime_state *shared_ceval = &interp->runtime->ceval; + struct _ceval_state *ceval = &interp->ceval; + ceval->pending.async_exc = 0; + COMPUTE_EVAL_BREAKER(interp, shared_ceval, ceval); } #ifndef NDEBUG @@ -216,6 +216,14 @@ is_tstate_valid(PyThreadState *tstate) } \ +static inline struct _gil_state * +_get_gil(PyInterpreterState *interp) +{ + assert(interp->runtime == &_PyRuntime); + return &_PyRuntime.ceval.gil; +} + + #define DEFAULT_INTERVAL 5000 static void _gil_initialize(struct _gil_state *gil) @@ -271,10 +279,9 @@ static void recreate_gil(struct _gil_state *gil) #endif static void -drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2, +drop_gil(struct _gil_state *gil, struct _ceval_state *ceval, PyThreadState *tstate) { - struct _gil_state *gil = &ceval->gil; if (!_Py_atomic_load_relaxed(&gil->locked)) { Py_FatalError("drop_gil: GIL is not locked"); } @@ -294,7 +301,7 @@ drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2, MUTEX_UNLOCK(gil->mutex); #ifdef FORCE_SWITCHING - if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request) && tstate != NULL) { + if (_Py_atomic_load_relaxed(&ceval->gil_drop_request) && tstate != NULL) { MUTEX_LOCK(gil->switch_mutex); /* Not switched yet => wait */ if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate) @@ -356,9 +363,9 @@ take_gil(PyThreadState *tstate) assert(is_tstate_valid(tstate)); PyInterpreterState *interp = tstate->interp; - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - struct _gil_state *gil = &ceval->gil; + struct _ceval_runtime_state *shared_ceval = &interp->runtime->ceval; + struct _ceval_state *ceval = &interp->ceval; + struct _gil_state *gil = _get_gil(interp); /* Check that _PyEval_InitThreads() was called to create the lock */ assert(gil_created(gil)); @@ -421,12 +428,12 @@ take_gil(PyThreadState *tstate) in take_gil() while the main thread called wait_for_thread_shutdown() from Py_Finalize(). */ MUTEX_UNLOCK(gil->mutex); - drop_gil(ceval, ceval2, tstate); + drop_gil(gil, ceval, tstate); PyThread_exit_thread(); } assert(is_tstate_valid(tstate)); - if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request)) { + if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) { RESET_GIL_DROP_REQUEST(interp); } else { @@ -435,7 +442,7 @@ take_gil(PyThreadState *tstate) handle signals. Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */ - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + COMPUTE_EVAL_BREAKER(interp, shared_ceval, ceval); } /* Don't access tstate if the thread must exit */ @@ -450,13 +457,15 @@ take_gil(PyThreadState *tstate) void _PyEval_SetSwitchInterval(unsigned long microseconds) { - struct _gil_state *gil = &_PyRuntime.ceval.gil; + PyInterpreterState *interp = _PyInterpreterState_GET(); + struct _gil_state *gil = _get_gil(interp); gil->interval = microseconds; } unsigned long _PyEval_GetSwitchInterval() { - struct _gil_state *gil = &_PyRuntime.ceval.gil; + PyInterpreterState *interp = _PyInterpreterState_GET(); + struct _gil_state *gil = _get_gil(interp); return gil->interval; } @@ -470,7 +479,8 @@ _PyEval_ThreadsInitialized(PyInterpreterState *interp) return 0; } } - return gil_created(&interp->runtime->ceval.gil); + struct _gil_state *gil = _get_gil(interp); + return gil_created(gil); } int @@ -490,7 +500,7 @@ _PyEval_InitGIL(PyThreadState *tstate) return _PyStatus_OK(); } - struct _gil_state *gil = &tstate->interp->runtime->ceval.gil; + struct _gil_state *gil = _get_gil(tstate->interp); assert(!gil_created(gil)); PyThread_init_thread(); @@ -512,7 +522,7 @@ _PyEval_FiniGIL(PyInterpreterState *interp) return; } - struct _gil_state *gil = &interp->runtime->ceval.gil; + struct _gil_state *gil = _get_gil(interp); if (!gil_created(gil)) { /* First Py_InitializeFromConfig() call: the GIL doesn't exist yet: do nothing. */ @@ -554,17 +564,17 @@ PyEval_ReleaseLock(void) /* This function must succeed when the current thread state is NULL. We therefore avoid PyThreadState_Get() which dumps a fatal error in debug mode. */ - struct _ceval_runtime_state *ceval = &runtime->ceval; - struct _ceval_state *ceval2 = &tstate->interp->ceval; - drop_gil(ceval, ceval2, tstate); + struct _gil_state *gil = _get_gil(tstate->interp); + struct _ceval_state *ceval = &tstate->interp->ceval; + drop_gil(gil, ceval, tstate); } void _PyEval_ReleaseLock(PyThreadState *tstate) { - struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; - struct _ceval_state *ceval2 = &tstate->interp->ceval; - drop_gil(ceval, ceval2, tstate); + struct _gil_state *gil = _get_gil(tstate->interp); + struct _ceval_state *ceval = &tstate->interp->ceval; + drop_gil(gil, ceval, tstate); } void @@ -590,9 +600,9 @@ PyEval_ReleaseThread(PyThreadState *tstate) if (new_tstate != tstate) { Py_FatalError("wrong thread state"); } - struct _ceval_runtime_state *ceval = &runtime->ceval; - struct _ceval_state *ceval2 = &tstate->interp->ceval; - drop_gil(ceval, ceval2, tstate); + struct _gil_state *gil = _get_gil(tstate->interp); + struct _ceval_state *ceval = &tstate->interp->ceval; + drop_gil(gil, ceval, tstate); } #ifdef HAVE_FORK @@ -604,7 +614,7 @@ _PyEval_ReInitThreads(PyThreadState *tstate) { _PyRuntimeState *runtime = tstate->interp->runtime; - struct _gil_state *gil = &runtime->ceval.gil; + struct _gil_state *gil = _get_gil(tstate->interp); if (!gil_created(gil)) { return _PyStatus_OK(); } @@ -639,10 +649,10 @@ PyEval_SaveThread(void) PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); _Py_EnsureTstateNotNULL(tstate); - struct _ceval_runtime_state *ceval = &runtime->ceval; - struct _ceval_state *ceval2 = &tstate->interp->ceval; - assert(gil_created(&ceval->gil)); - drop_gil(ceval, ceval2, tstate); + struct _gil_state *gil = _get_gil(tstate->interp); + struct _ceval_state *ceval = &tstate->interp->ceval; + assert(gil_created(gil)); + drop_gil(gil, ceval, tstate); return tstate; } @@ -910,9 +920,7 @@ _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval) void _PyEval_InitState(PyInterpreterState *interp, PyThread_type_lock pending_lock) { - struct _ceval_state *ceval = &interp->ceval; - - struct _pending_calls *pending = &ceval->pending; + struct _pending_calls *pending = &interp->ceval.pending; assert(pending->lock == NULL); pending->lock = pending_lock; } @@ -933,30 +941,31 @@ int _Py_HandlePending(PyThreadState *tstate) { _PyRuntimeState * const runtime = &_PyRuntime; - struct _ceval_runtime_state *ceval = &runtime->ceval; + struct _ceval_runtime_state *shared_ceval = &runtime->ceval; /* Pending signals */ - if (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)) { + if (_Py_atomic_load_relaxed_int32(&shared_ceval->signals_pending)) { if (handle_signals(tstate) != 0) { return -1; } } /* Pending calls */ - struct _ceval_state *ceval2 = &tstate->interp->ceval; - if (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)) { + struct _ceval_state *ceval = &tstate->interp->ceval; + if (_Py_atomic_load_relaxed_int32(&ceval->pending.calls_to_do)) { if (make_pending_calls(tstate->interp) != 0) { return -1; } } /* GIL drop request */ - if (_Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request)) { + if (_Py_atomic_load_relaxed_int32(&ceval->gil_drop_request)) { /* Give another thread a chance */ if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) { Py_FatalError("tstate mix-up"); } - drop_gil(ceval, ceval2, tstate); + struct _gil_state *gil = _get_gil(tstate->interp); + drop_gil(gil, ceval, tstate); /* Other threads may run now */ @@ -985,7 +994,7 @@ _Py_HandlePending(PyThreadState *tstate) // value. It prevents to interrupt the eval loop at every instruction if // the current Python thread cannot handle signals (if // _Py_ThreadCanHandleSignals() is false). - COMPUTE_EVAL_BREAKER(tstate->interp, ceval, ceval2); + COMPUTE_EVAL_BREAKER(tstate->interp, shared_ceval, ceval); #endif return 0; From 7014bffdc9b2bcaaaaea3d92e7d6aef303c75899 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 15:27:07 -0600 Subject: [PATCH 08/17] Pass the runtime to _PyEval_InitRuntimeState(). --- Include/internal/pycore_ceval.h | 2 +- Python/ceval_gil.c | 4 ++-- Python/pystate.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 5dabb9d35040db..6d3c6b43021ad4 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -28,7 +28,7 @@ struct _ceval_runtime_state; extern void _Py_FinishPendingCalls(PyThreadState *tstate); -extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *); +extern void _PyEval_InitRuntimeState(_PyRuntimeState *); extern void _PyEval_InitState(PyInterpreterState *, PyThread_type_lock); extern void _PyEval_FiniState(struct _ceval_state *ceval); PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp); diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 52c2987aa77046..060280ee7fef5d 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -912,9 +912,9 @@ Py_MakePendingCalls(void) /* The interpreter's recursion limit */ void -_PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval) +_PyEval_InitRuntimeState(_PyRuntimeState *runtime) { - _gil_initialize(&ceval->gil); + _gil_initialize(&runtime->ceval.gil); } void diff --git a/Python/pystate.c b/Python/pystate.c index fa2a8f9541d2ad..a7df590f1dcd11 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -121,7 +121,7 @@ init_runtime(_PyRuntimeState *runtime, runtime->open_code_userdata = open_code_userdata; runtime->audit_hook_head = audit_hook_head; - _PyEval_InitRuntimeState(&runtime->ceval); + _PyEval_InitRuntimeState(runtime); PyPreConfig_InitPythonConfig(&runtime->preconfig); From 20260345eeadc2a45af54f6c9a65096ac277950b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 15:53:34 -0600 Subject: [PATCH 09/17] Add some comments. --- Python/ceval_gil.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 060280ee7fef5d..a8989be330ed7f 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -920,6 +920,8 @@ _PyEval_InitRuntimeState(_PyRuntimeState *runtime) void _PyEval_InitState(PyInterpreterState *interp, PyThread_type_lock pending_lock) { + /* Everthing GIL-related is initialized in _PyEval_InitGIL(). */ + struct _pending_calls *pending = &interp->ceval.pending; assert(pending->lock == NULL); pending->lock = pending_lock; @@ -933,6 +935,8 @@ _PyEval_FiniState(struct _ceval_state *ceval) PyThread_free_lock(pending->lock); pending->lock = NULL; } + + /* Everthing GIL-related is finalized in _PyEval_FiniGIL(). */ } /* Handle signals, pending calls, GIL drop request From 3ce9695374dd2dce25ab66121c4460016cd3db3e Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 15:54:50 -0600 Subject: [PATCH 10/17] Add _GET_OWN_GIL(). --- Python/ceval_gil.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index a8989be330ed7f..ed1de938b7497b 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -216,6 +216,12 @@ is_tstate_valid(PyThreadState *tstate) } \ +/* Currently, the GIL is shared by all interpreters, + and only the main interpreter is responsible to create + and destroy it. */ +#define _GET_OWN_GIL(interp) \ + (_Py_IsMainInterpreter(interp) ? (&_PyRuntime.ceval.gil) : NULL) + static inline struct _gil_state * _get_gil(PyInterpreterState *interp) { @@ -493,14 +499,12 @@ PyEval_ThreadsInitialized(void) PyStatus _PyEval_InitGIL(PyThreadState *tstate) { - if (!_Py_IsMainInterpreter(tstate->interp)) { - /* Currently, the GIL is shared by all interpreters, - and only the main interpreter is responsible to create - and destroy it. */ + struct _gil_state *gil = _get_gil(tstate->interp); + if (gil != _GET_OWN_GIL(tstate->interp)) { + /* It's a shared GIL. */ + assert(!_Py_IsMainInterpreter(tstate->interp)); return _PyStatus_OK(); } - - struct _gil_state *gil = _get_gil(tstate->interp); assert(!gil_created(gil)); PyThread_init_thread(); @@ -515,14 +519,12 @@ _PyEval_InitGIL(PyThreadState *tstate) void _PyEval_FiniGIL(PyInterpreterState *interp) { - if (!_Py_IsMainInterpreter(interp)) { - /* Currently, the GIL is shared by all interpreters, - and only the main interpreter is responsible to create - and destroy it. */ + struct _gil_state *gil = _get_gil(interp); + if (gil != _GET_OWN_GIL(interp)) { + /* It's a shared GIL. */ + assert(!_Py_IsMainInterpreter(interp)); return; } - - struct _gil_state *gil = _get_gil(interp); if (!gil_created(gil)) { /* First Py_InitializeFromConfig() call: the GIL doesn't exist yet: do nothing. */ From 57ca2fa9c974739920d9c65b1878d1089d1f6e97 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 16:06:40 -0600 Subject: [PATCH 11/17] Pass PyInterpreterState to _PyEval_FiniState(). --- Include/internal/pycore_ceval.h | 2 +- Python/ceval_gil.c | 4 ++-- Python/pystate.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 6d3c6b43021ad4..596d2f8abb623c 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -30,7 +30,7 @@ struct _ceval_runtime_state; extern void _Py_FinishPendingCalls(PyThreadState *tstate); extern void _PyEval_InitRuntimeState(_PyRuntimeState *); extern void _PyEval_InitState(PyInterpreterState *, PyThread_type_lock); -extern void _PyEval_FiniState(struct _ceval_state *ceval); +extern void _PyEval_FiniState(PyInterpreterState *); PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp); PyAPI_FUNC(int) _PyEval_AddPendingCall( PyInterpreterState *interp, diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index ed1de938b7497b..1799d54c099e14 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -930,9 +930,9 @@ _PyEval_InitState(PyInterpreterState *interp, PyThread_type_lock pending_lock) } void -_PyEval_FiniState(struct _ceval_state *ceval) +_PyEval_FiniState(PyInterpreterState *interp) { - struct _pending_calls *pending = &ceval->pending; + struct _pending_calls *pending = &interp->ceval.pending; if (pending->lock != NULL) { PyThread_free_lock(pending->lock); pending->lock = NULL; diff --git a/Python/pystate.c b/Python/pystate.c index a7df590f1dcd11..23de70acc2c4a2 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -495,7 +495,7 @@ PyInterpreterState_Delete(PyInterpreterState *interp) struct pyinterpreters *interpreters = &runtime->interpreters; zapthreads(interp, 0); - _PyEval_FiniState(&interp->ceval); + _PyEval_FiniState(interp); /* Delete current thread. After this, many C API calls become crashy. */ _PyThreadState_Swap(&runtime->gilstate, NULL); From 936c86dcdda4986456e347968448eba056378e67 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 16:14:57 -0600 Subject: [PATCH 12/17] Call _gil_initialize() in _PyEval_InitState(). --- Python/ceval_gil.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 1799d54c099e14..a97857095b4061 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -916,13 +916,19 @@ Py_MakePendingCalls(void) void _PyEval_InitRuntimeState(_PyRuntimeState *runtime) { - _gil_initialize(&runtime->ceval.gil); + //_gil_initialize(&runtime->ceval.gil); } void _PyEval_InitState(PyInterpreterState *interp, PyThread_type_lock pending_lock) { - /* Everthing GIL-related is initialized in _PyEval_InitGIL(). */ + /* Each interpreter is responsible to create and destroy + its own GIL. Interpreters that share a GIL skip this step. */ + struct _gil_state *gil = _get_gil(interp); + if (gil == _GET_OWN_GIL(interp)) { + _gil_initialize(gil); + /* Everthing else GIL-related is initialized in _PyEval_InitGIL(). */ + } struct _pending_calls *pending = &interp->ceval.pending; assert(pending->lock == NULL); From 66ca3e486baa228d4300a97438134b64401d6ae2 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 16:17:14 -0600 Subject: [PATCH 13/17] Drop _PyEval_InitRuntimeState(). --- Include/internal/pycore_ceval.h | 1 - Python/ceval_gil.c | 6 ------ Python/pystate.c | 2 -- 3 files changed, 9 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 596d2f8abb623c..ccd4e2e699c93a 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -28,7 +28,6 @@ struct _ceval_runtime_state; extern void _Py_FinishPendingCalls(PyThreadState *tstate); -extern void _PyEval_InitRuntimeState(_PyRuntimeState *); extern void _PyEval_InitState(PyInterpreterState *, PyThread_type_lock); extern void _PyEval_FiniState(PyInterpreterState *); PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp); diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index a97857095b4061..572b9c8ddcddb9 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -913,12 +913,6 @@ Py_MakePendingCalls(void) /* The interpreter's recursion limit */ -void -_PyEval_InitRuntimeState(_PyRuntimeState *runtime) -{ - //_gil_initialize(&runtime->ceval.gil); -} - void _PyEval_InitState(PyInterpreterState *interp, PyThread_type_lock pending_lock) { diff --git a/Python/pystate.c b/Python/pystate.c index 23de70acc2c4a2..a02eb20f03cb68 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -121,8 +121,6 @@ init_runtime(_PyRuntimeState *runtime, runtime->open_code_userdata = open_code_userdata; runtime->audit_hook_head = audit_hook_head; - _PyEval_InitRuntimeState(runtime); - PyPreConfig_InitPythonConfig(&runtime->preconfig); runtime->interpreters.mutex = interpreters_mutex; From 6d0932079c5da629542da8fd0ddbf8c37957e068 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 12:39:39 -0600 Subject: [PATCH 14/17] Move the GIL to PyInterpreterState (but still share). --- Include/internal/pycore_interp.h | 2 ++ Include/internal/pycore_runtime.h | 3 --- Python/ceval_gil.c | 9 +++++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index d8da63f427f458..6b123b8d96d5a4 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -50,6 +50,8 @@ struct _ceval_state { _Py_atomic_int eval_breaker; /* Request for dropping the GIL */ _Py_atomic_int gil_drop_request; + /* The GIL */ + struct _gil_state gil; /* Pending calls */ struct _pending_calls pending; }; diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index cf2b240c72e86b..d205f7afd0a46b 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -9,7 +9,6 @@ extern "C" { #endif #include "pycore_atomic.h" /* _Py_atomic_address */ -#include "pycore_gil.h" // struct _gil_state #include "pycore_global_objects.h" // struct _Py_global_objects #include "pycore_interp.h" // PyInterpreterState #include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids @@ -26,8 +25,6 @@ struct _ceval_runtime_state { the main thread of the main interpreter can handle signals: see _Py_ThreadCanHandleSignals(). */ _Py_atomic_int signals_pending; - /* The GIL */ - struct _gil_state gil; }; /* GIL state */ diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 572b9c8ddcddb9..78bc42bddd97f4 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -220,13 +220,18 @@ is_tstate_valid(PyThreadState *tstate) and only the main interpreter is responsible to create and destroy it. */ #define _GET_OWN_GIL(interp) \ - (_Py_IsMainInterpreter(interp) ? (&_PyRuntime.ceval.gil) : NULL) + (_Py_IsMainInterpreter(interp) \ + ? (&_PyRuntime.interpreters.main->ceval.gil) \ + : NULL) static inline struct _gil_state * _get_gil(PyInterpreterState *interp) { + //if (interp->config->_isolated_interpreter) { + // return &interp->ceval.gil; + //} assert(interp->runtime == &_PyRuntime); - return &_PyRuntime.ceval.gil; + return &_PyRuntime.interpreters.main->ceval.gil; } From 507599297eb2857dd9cdd6d99cc9f339d9552586 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 12:53:55 -0600 Subject: [PATCH 15/17] Keep sharing the GIL. --- Python/ceval_gil.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 78bc42bddd97f4..32a3896fecd9bc 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -227,9 +227,6 @@ is_tstate_valid(PyThreadState *tstate) static inline struct _gil_state * _get_gil(PyInterpreterState *interp) { - //if (interp->config->_isolated_interpreter) { - // return &interp->ceval.gil; - //} assert(interp->runtime == &_PyRuntime); return &_PyRuntime.interpreters.main->ceval.gil; } From f39c883a6e7443d4717896a6a8cdaacb163d8600 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 13:28:57 -0600 Subject: [PATCH 16/17] Check for GIL ownership. --- Python/ceval_gil.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 32a3896fecd9bc..83d66db38d5545 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -220,9 +220,7 @@ is_tstate_valid(PyThreadState *tstate) and only the main interpreter is responsible to create and destroy it. */ #define _GET_OWN_GIL(interp) \ - (_Py_IsMainInterpreter(interp) \ - ? (&_PyRuntime.interpreters.main->ceval.gil) \ - : NULL) + (&interp->ceval.gil) static inline struct _gil_state * _get_gil(PyInterpreterState *interp) From ae2eb3cfaf9146d955ebdc5255d8d20b7b6f7dc7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 12 Sep 2022 13:30:52 -0600 Subject: [PATCH 17/17] Stop sharing the GIL if configured as "isolated". --- Python/ceval_gil.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 83d66db38d5545..ab5b8f4cf50043 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -225,7 +225,9 @@ is_tstate_valid(PyThreadState *tstate) static inline struct _gil_state * _get_gil(PyInterpreterState *interp) { - assert(interp->runtime == &_PyRuntime); + if (interp->config._isolated_interpreter) { + return _GET_OWN_GIL(interp); + } return &_PyRuntime.interpreters.main->ceval.gil; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy