summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-04-08 15:54:59 (GMT)
committerGitHub <noreply@github.com>2020-04-08 15:54:59 (GMT)
commitdda5d6e071c6a9d65993d45b90232565cfad2cde (patch)
treee5c629500c9557ecad3113054a019fc4af19f93a /Python/ceval.c
parentac2cfe6631b77a2005d8f16f034dbb6154f04ab2 (diff)
downloadcpython-dda5d6e071c6a9d65993d45b90232565cfad2cde.zip
cpython-dda5d6e071c6a9d65993d45b90232565cfad2cde.tar.gz
cpython-dda5d6e071c6a9d65993d45b90232565cfad2cde.tar.bz2
bpo-40226: PyInterpreterState_Delete() deletes pending calls (GH-19436)
PyInterpreterState_New() is now responsible to create pending calls, PyInterpreterState_Delete() now deletes pending calls. * Rename _PyEval_InitThreads() to _PyEval_InitGIL() and rename _PyEval_InitGIL() to _PyEval_FiniGIL(). * _PyEval_InitState() and PyEval_FiniState() now create and delete pending calls. _PyEval_InitState() now returns -1 on memory allocation failure. * Add init_interp_create_gil() helper function: code shared by Py_NewInterpreter() and Py_InitializeFromConfig(). * init_interp_create_gil() now also calls _PyEval_FiniGIL(), _PyEval_InitGIL() and _PyGILState_Init() in subinterpreters, but these functions now do nothing when called from a subinterpreter.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c81
1 files changed, 50 insertions, 31 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 7747b08..2e94f32 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -275,54 +275,52 @@ PyEval_ThreadsInitialized(void)
}
PyStatus
-_PyEval_InitThreads(PyThreadState *tstate)
+_PyEval_InitGIL(PyThreadState *tstate)
{
- assert(is_tstate_valid(tstate));
+ if (!_Py_IsMainInterpreter(tstate)) {
+ /* Currently, the GIL is shared by all interpreters,
+ and only the main interpreter is responsible to create
+ and destroy it. */
+ return _PyStatus_OK();
+ }
- if (_Py_IsMainInterpreter(tstate)) {
- struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
- if (gil_created(gil)) {
- return _PyStatus_OK();
- }
+ struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
+ assert(!gil_created(gil));
- PyThread_init_thread();
- create_gil(gil);
+ PyThread_init_thread();
+ create_gil(gil);
- take_gil(tstate);
- }
-
- struct _pending_calls *pending = &tstate->interp->ceval.pending;
- assert(pending->lock == NULL);
- pending->lock = PyThread_allocate_lock();
- if (pending->lock == NULL) {
- return _PyStatus_NO_MEMORY();
- }
+ take_gil(tstate);
+ assert(gil_created(gil));
return _PyStatus_OK();
}
void
-PyEval_InitThreads(void)
+_PyEval_FiniGIL(PyThreadState *tstate)
{
- /* Do nothing: kept for backward compatibility */
-}
+ if (!_Py_IsMainInterpreter(tstate)) {
+ /* Currently, the GIL is shared by all interpreters,
+ and only the main interpreter is responsible to create
+ and destroy it. */
+ return;
+ }
-void
-_PyEval_FiniThreads(PyThreadState *tstate)
-{
struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
if (!gil_created(gil)) {
+ /* First Py_InitializeFromConfig() call: the GIL doesn't exist
+ yet: do nothing. */
return;
}
destroy_gil(gil);
assert(!gil_created(gil));
+}
- struct _pending_calls *pending = &tstate->interp->ceval.pending;
- if (pending->lock != NULL) {
- PyThread_free_lock(pending->lock);
- pending->lock = NULL;
- }
+void
+PyEval_InitThreads(void)
+{
+ /* Do nothing: kept for backward compatibility */
}
void
@@ -544,6 +542,10 @@ _PyEval_AddPendingCall(PyThreadState *tstate,
{
struct _pending_calls *pending = &tstate->interp->ceval.pending;
+ /* Ensure that _PyEval_InitPendingCalls() was called
+ and that _PyEval_FiniPendingCalls() is not called yet. */
+ assert(pending->lock != NULL);
+
PyThread_acquire_lock(pending->lock, WAIT_LOCK);
if (pending->finishing) {
PyThread_release_lock(pending->lock);
@@ -721,10 +723,27 @@ _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
_gil_initialize(&ceval->gil);
}
-void
+int
_PyEval_InitState(struct _ceval_state *ceval)
{
- /* PyInterpreterState_New() initializes ceval to zero */
+ struct _pending_calls *pending = &ceval->pending;
+ assert(pending->lock == NULL);
+
+ pending->lock = PyThread_allocate_lock();
+ if (pending->lock == NULL) {
+ return -1;
+ }
+ return 0;
+}
+
+void
+_PyEval_FiniState(struct _ceval_state *ceval)
+{
+ struct _pending_calls *pending = &ceval->pending;
+ if (pending->lock != NULL) {
+ PyThread_free_lock(pending->lock);
+ pending->lock = NULL;
+ }
}
int