bpo-36710: Add runtime variable in pystate.c (GH-12956)

Add 'gilstate', 'runtime' or 'xidregistry' parameter to many
functions on pystate.c to avoid lying on _PyRuntime global.
This commit is contained in:
Victor Stinner 2019-04-26 01:53:18 +02:00 committed by GitHub
parent 5422e3cfb7
commit 10c8e6af91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 233 additions and 156 deletions

View File

@ -6,11 +6,6 @@
#include "pycore_pymem.h" #include "pycore_pymem.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#define _PyThreadState_SET(value) \
_Py_atomic_store_relaxed(&_PyRuntime.gilstate.tstate_current, \
(uintptr_t)(value))
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
CAUTION CAUTION
@ -34,6 +29,18 @@ to avoid the expense of doing their own locking).
extern "C" { extern "C" {
#endif #endif
#define _PyRuntimeGILState_GetThreadState(gilstate) \
((PyThreadState*)_Py_atomic_load_relaxed(&(gilstate)->tstate_current))
#define _PyRuntimeGILState_SetThreadState(gilstate, value) \
_Py_atomic_store_relaxed(&(gilstate)->tstate_current, \
(uintptr_t)(value))
/* Forward declarations */
static PyThreadState *_PyGILState_GetThisThreadState(struct _gilstate_runtime_state *gilstate);
static void _PyThreadState_Delete(_PyRuntimeState *runtime, PyThreadState *tstate);
static PyThreadState *_PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts);
static _PyInitError static _PyInitError
_PyRuntimeState_Init_impl(_PyRuntimeState *runtime) _PyRuntimeState_Init_impl(_PyRuntimeState *runtime)
{ {
@ -137,9 +144,10 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
} }
} }
#define HEAD_LOCK() PyThread_acquire_lock(_PyRuntime.interpreters.mutex, \ #define HEAD_LOCK(runtime) \
WAIT_LOCK) PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)
#define HEAD_UNLOCK() PyThread_release_lock(_PyRuntime.interpreters.mutex) #define HEAD_UNLOCK(runtime) \
PyThread_release_lock((runtime)->interpreters.mutex)
/* Forward declaration */ /* Forward declaration */
static void _PyGILState_NoteThreadState( static void _PyGILState_NoteThreadState(
@ -148,21 +156,22 @@ static void _PyGILState_NoteThreadState(
_PyInitError _PyInitError
_PyInterpreterState_Enable(_PyRuntimeState *runtime) _PyInterpreterState_Enable(_PyRuntimeState *runtime)
{ {
runtime->interpreters.next_id = 0; struct pyinterpreters *interpreters = &runtime->interpreters;
interpreters->next_id = 0;
/* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex. /* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex.
Create a new mutex if needed. */ Create a new mutex if needed. */
if (runtime->interpreters.mutex == NULL) { if (interpreters->mutex == NULL) {
/* Force default allocator, since _PyRuntimeState_Fini() must /* Force default allocator, since _PyRuntimeState_Fini() must
use the same allocator than this function. */ use the same allocator than this function. */
PyMemAllocatorEx old_alloc; PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
runtime->interpreters.mutex = PyThread_allocate_lock(); interpreters->mutex = PyThread_allocate_lock();
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (runtime->interpreters.mutex == NULL) { if (interpreters->mutex == NULL) {
return _Py_INIT_ERR("Can't initialize threads for interpreter"); return _Py_INIT_ERR("Can't initialize threads for interpreter");
} }
} }
@ -173,9 +182,7 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime)
PyInterpreterState * PyInterpreterState *
PyInterpreterState_New(void) PyInterpreterState_New(void)
{ {
PyInterpreterState *interp = (PyInterpreterState *) PyInterpreterState *interp = PyMem_RawMalloc(sizeof(PyInterpreterState));
PyMem_RawMalloc(sizeof(PyInterpreterState));
if (interp == NULL) { if (interp == NULL) {
return NULL; return NULL;
} }
@ -193,23 +200,27 @@ PyInterpreterState_New(void)
#endif #endif
#endif #endif
HEAD_LOCK(); _PyRuntimeState *runtime = &_PyRuntime;
if (_PyRuntime.interpreters.next_id < 0) { struct pyinterpreters *interpreters = &runtime->interpreters;
HEAD_LOCK(runtime);
if (interpreters->next_id < 0) {
/* overflow or Py_Initialize() not called! */ /* overflow or Py_Initialize() not called! */
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"failed to get an interpreter ID"); "failed to get an interpreter ID");
PyMem_RawFree(interp); PyMem_RawFree(interp);
interp = NULL; interp = NULL;
} else {
interp->id = _PyRuntime.interpreters.next_id;
_PyRuntime.interpreters.next_id += 1;
interp->next = _PyRuntime.interpreters.head;
if (_PyRuntime.interpreters.main == NULL) {
_PyRuntime.interpreters.main = interp;
}
_PyRuntime.interpreters.head = interp;
} }
HEAD_UNLOCK(); else {
interp->id = interpreters->next_id;
interpreters->next_id += 1;
interp->next = interpreters->head;
if (interpreters->main == NULL) {
interpreters->main = interp;
}
interpreters->head = interp;
}
HEAD_UNLOCK(runtime);
if (interp == NULL) { if (interp == NULL) {
return NULL; return NULL;
@ -221,14 +232,14 @@ PyInterpreterState_New(void)
} }
void static void
PyInterpreterState_Clear(PyInterpreterState *interp) _PyInterpreterState_Clear(_PyRuntimeState *runtime, PyInterpreterState *interp)
{ {
PyThreadState *p; HEAD_LOCK(runtime);
HEAD_LOCK(); for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) {
for (p = interp->tstate_head; p != NULL; p = p->next)
PyThreadState_Clear(p); PyThreadState_Clear(p);
HEAD_UNLOCK(); }
HEAD_UNLOCK(runtime);
_PyCoreConfig_Clear(&interp->core_config); _PyCoreConfig_Clear(&interp->core_config);
Py_CLEAR(interp->codec_search_path); Py_CLEAR(interp->codec_search_path);
Py_CLEAR(interp->codec_search_cache); Py_CLEAR(interp->codec_search_cache);
@ -251,45 +262,63 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
// objects have been cleaned up at the point. // objects have been cleaned up at the point.
} }
void
PyInterpreterState_Clear(PyInterpreterState *interp)
{
_PyInterpreterState_Clear(&_PyRuntime, interp);
}
static void static void
zapthreads(PyInterpreterState *interp) zapthreads(_PyRuntimeState *runtime, PyInterpreterState *interp)
{ {
PyThreadState *p; PyThreadState *p;
/* No need to lock the mutex here because this should only happen /* No need to lock the mutex here because this should only happen
when the threads are all really dead (XXX famous last words). */ when the threads are all really dead (XXX famous last words). */
while ((p = interp->tstate_head) != NULL) { while ((p = interp->tstate_head) != NULL) {
PyThreadState_Delete(p); _PyThreadState_Delete(runtime, p);
} }
} }
static void
_PyInterpreterState_Delete(_PyRuntimeState *runtime,
PyInterpreterState *interp)
{
struct pyinterpreters *interpreters = &runtime->interpreters;
zapthreads(runtime, interp);
HEAD_LOCK(runtime);
PyInterpreterState **p;
for (p = &interpreters->head; ; p = &(*p)->next) {
if (*p == NULL) {
Py_FatalError("PyInterpreterState_Delete: invalid interp");
}
if (*p == interp) {
break;
}
}
if (interp->tstate_head != NULL) {
Py_FatalError("PyInterpreterState_Delete: remaining threads");
}
*p = interp->next;
if (interpreters->main == interp) {
interpreters->main = NULL;
if (interpreters->head != NULL) {
Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters");
}
}
HEAD_UNLOCK(runtime);
if (interp->id_mutex != NULL) {
PyThread_free_lock(interp->id_mutex);
}
PyMem_RawFree(interp);
}
void void
PyInterpreterState_Delete(PyInterpreterState *interp) PyInterpreterState_Delete(PyInterpreterState *interp)
{ {
PyInterpreterState **p; _PyInterpreterState_Delete(&_PyRuntime, interp);
zapthreads(interp);
HEAD_LOCK();
for (p = &_PyRuntime.interpreters.head; ; p = &(*p)->next) {
if (*p == NULL)
Py_FatalError(
"PyInterpreterState_Delete: invalid interp");
if (*p == interp)
break;
}
if (interp->tstate_head != NULL)
Py_FatalError("PyInterpreterState_Delete: remaining threads");
*p = interp->next;
if (_PyRuntime.interpreters.main == interp) {
_PyRuntime.interpreters.main = NULL;
if (_PyRuntime.interpreters.head != NULL)
Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters");
}
HEAD_UNLOCK();
if (interp->id_mutex != NULL) {
PyThread_free_lock(interp->id_mutex);
}
PyMem_RawFree(interp);
} }
@ -300,14 +329,15 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
void void
_PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
{ {
struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
struct pyinterpreters *interpreters = &runtime->interpreters; struct pyinterpreters *interpreters = &runtime->interpreters;
PyThreadState *tstate = PyThreadState_Swap(NULL); PyThreadState *tstate = _PyThreadState_Swap(gilstate, NULL);
if (tstate != NULL && tstate->interp != interpreters->main) { if (tstate != NULL && tstate->interp != interpreters->main) {
Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter"); Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter");
} }
HEAD_LOCK(); HEAD_LOCK(runtime);
PyInterpreterState *interp = interpreters->head; PyInterpreterState *interp = interpreters->head;
interpreters->head = NULL; interpreters->head = NULL;
while (interp != NULL) { while (interp != NULL) {
@ -318,8 +348,8 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
continue; continue;
} }
PyInterpreterState_Clear(interp); // XXX must activate? _PyInterpreterState_Clear(runtime, interp); // XXX must activate?
zapthreads(interp); zapthreads(runtime, interp);
if (interp->id_mutex != NULL) { if (interp->id_mutex != NULL) {
PyThread_free_lock(interp->id_mutex); PyThread_free_lock(interp->id_mutex);
} }
@ -327,12 +357,12 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
interp = interp->next; interp = interp->next;
PyMem_RawFree(prev_interp); PyMem_RawFree(prev_interp);
} }
HEAD_UNLOCK(); HEAD_UNLOCK(runtime);
if (interpreters->head == NULL) { if (interpreters->head == NULL) {
Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main"); Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main");
} }
PyThreadState_Swap(tstate); _PyThreadState_Swap(gilstate, tstate);
} }
@ -363,9 +393,9 @@ PyInterpreterState_GetID(PyInterpreterState *interp)
static PyInterpreterState * static PyInterpreterState *
interp_look_up_id(PY_INT64_T requested_id) interp_look_up_id(_PyRuntimeState *runtime, PY_INT64_T requested_id)
{ {
PyInterpreterState *interp = PyInterpreterState_Head(); PyInterpreterState *interp = runtime->interpreters.head;
while (interp != NULL) { while (interp != NULL) {
PY_INT64_T id = PyInterpreterState_GetID(interp); PY_INT64_T id = PyInterpreterState_GetID(interp);
if (id < 0) { if (id < 0) {
@ -384,9 +414,10 @@ _PyInterpreterState_LookUpID(PY_INT64_T requested_id)
{ {
PyInterpreterState *interp = NULL; PyInterpreterState *interp = NULL;
if (requested_id >= 0) { if (requested_id >= 0) {
HEAD_LOCK(); _PyRuntimeState *runtime = &_PyRuntime;
interp = interp_look_up_id(requested_id); HEAD_LOCK(runtime);
HEAD_UNLOCK(); interp = interp_look_up_id(runtime, requested_id);
HEAD_UNLOCK(runtime);
} }
if (interp == NULL && !PyErr_Occurred()) { if (interp == NULL && !PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError, PyErr_Format(PyExc_RuntimeError,
@ -431,6 +462,7 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp)
if (interp->id_mutex == NULL) { if (interp->id_mutex == NULL) {
return; return;
} }
struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK);
assert(interp->id_refcount != 0); assert(interp->id_refcount != 0);
interp->id_refcount -= 1; interp->id_refcount -= 1;
@ -441,9 +473,9 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp)
// XXX Using the "head" thread isn't strictly correct. // XXX Using the "head" thread isn't strictly correct.
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
// XXX Possible GILState issues? // XXX Possible GILState issues?
PyThreadState *save_tstate = PyThreadState_Swap(tstate); PyThreadState *save_tstate = _PyThreadState_Swap(gilstate, tstate);
Py_EndInterpreter(tstate); Py_EndInterpreter(tstate);
PyThreadState_Swap(save_tstate); _PyThreadState_Swap(gilstate, save_tstate);
} }
} }
@ -498,6 +530,7 @@ threadstate_getframe(PyThreadState *self)
static PyThreadState * static PyThreadState *
new_threadstate(PyInterpreterState *interp, int init) new_threadstate(PyInterpreterState *interp, int init)
{ {
_PyRuntimeState *runtime = &_PyRuntime;
PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState)); PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState));
if (tstate == NULL) { if (tstate == NULL) {
return NULL; return NULL;
@ -556,16 +589,16 @@ new_threadstate(PyInterpreterState *interp, int init)
tstate->id = ++interp->tstate_next_unique_id; tstate->id = ++interp->tstate_next_unique_id;
if (init) { if (init) {
_PyThreadState_Init(&_PyRuntime, tstate); _PyThreadState_Init(runtime, tstate);
} }
HEAD_LOCK(); HEAD_LOCK(runtime);
tstate->prev = NULL; tstate->prev = NULL;
tstate->next = interp->tstate_head; tstate->next = interp->tstate_head;
if (tstate->next) if (tstate->next)
tstate->next->prev = tstate; tstate->next->prev = tstate;
interp->tstate_head = tstate; interp->tstate_head = tstate;
HEAD_UNLOCK(); HEAD_UNLOCK(runtime);
return tstate; return tstate;
} }
@ -750,22 +783,23 @@ PyThreadState_Clear(PyThreadState *tstate)
/* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */ /* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */
static void static void
tstate_delete_common(PyThreadState *tstate) tstate_delete_common(_PyRuntimeState *runtime, PyThreadState *tstate)
{ {
PyInterpreterState *interp; if (tstate == NULL) {
if (tstate == NULL)
Py_FatalError("PyThreadState_Delete: NULL tstate"); Py_FatalError("PyThreadState_Delete: NULL tstate");
interp = tstate->interp; }
if (interp == NULL) PyInterpreterState *interp = tstate->interp;
if (interp == NULL) {
Py_FatalError("PyThreadState_Delete: NULL interp"); Py_FatalError("PyThreadState_Delete: NULL interp");
HEAD_LOCK(); }
HEAD_LOCK(runtime);
if (tstate->prev) if (tstate->prev)
tstate->prev->next = tstate->next; tstate->prev->next = tstate->next;
else else
interp->tstate_head = tstate->next; interp->tstate_head = tstate->next;
if (tstate->next) if (tstate->next)
tstate->next->prev = tstate->prev; tstate->next->prev = tstate->prev;
HEAD_UNLOCK(); HEAD_UNLOCK(runtime);
if (tstate->on_delete != NULL) { if (tstate->on_delete != NULL) {
tstate->on_delete(tstate->on_delete_data); tstate->on_delete(tstate->on_delete_data);
} }
@ -773,37 +807,53 @@ tstate_delete_common(PyThreadState *tstate)
} }
void static void
PyThreadState_Delete(PyThreadState *tstate) _PyThreadState_Delete(_PyRuntimeState *runtime, PyThreadState *tstate)
{ {
if (tstate == _PyThreadState_GET()) struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) {
Py_FatalError("PyThreadState_Delete: tstate is still current"); Py_FatalError("PyThreadState_Delete: tstate is still current");
if (_PyRuntime.gilstate.autoInterpreterState &&
PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate)
{
PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL);
} }
tstate_delete_common(tstate); if (gilstate->autoInterpreterState &&
PyThread_tss_get(&gilstate->autoTSSkey) == tstate)
{
PyThread_tss_set(&gilstate->autoTSSkey, NULL);
}
tstate_delete_common(runtime, tstate);
} }
void void
PyThreadState_DeleteCurrent() PyThreadState_Delete(PyThreadState *tstate)
{ {
PyThreadState *tstate = _PyThreadState_GET(); return _PyThreadState_Delete(&_PyRuntime, tstate);
}
static void
_PyThreadState_DeleteCurrent(_PyRuntimeState *runtime)
{
struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate);
if (tstate == NULL) if (tstate == NULL)
Py_FatalError( Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate"); "PyThreadState_DeleteCurrent: no current tstate");
tstate_delete_common(tstate); tstate_delete_common(runtime, tstate);
if (_PyRuntime.gilstate.autoInterpreterState && if (gilstate->autoInterpreterState &&
PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate) PyThread_tss_get(&gilstate->autoTSSkey) == tstate)
{ {
PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL); PyThread_tss_set(&gilstate->autoTSSkey, NULL);
} }
_PyThreadState_SET(NULL); _PyRuntimeGILState_SetThreadState(gilstate, NULL);
PyEval_ReleaseLock(); PyEval_ReleaseLock();
} }
void
PyThreadState_DeleteCurrent()
{
_PyThreadState_DeleteCurrent(&_PyRuntime);
}
/* /*
* Delete all thread states except the one passed as argument. * Delete all thread states except the one passed as argument.
@ -815,9 +865,10 @@ PyThreadState_DeleteCurrent()
void void
_PyThreadState_DeleteExcept(PyThreadState *tstate) _PyThreadState_DeleteExcept(PyThreadState *tstate)
{ {
_PyRuntimeState *runtime = &_PyRuntime;
PyInterpreterState *interp = tstate->interp; PyInterpreterState *interp = tstate->interp;
PyThreadState *p, *next, *garbage; PyThreadState *p, *next, *garbage;
HEAD_LOCK(); HEAD_LOCK(runtime);
/* Remove all thread states, except tstate, from the linked list of /* Remove all thread states, except tstate, from the linked list of
thread states. This will allow calling PyThreadState_Clear() thread states. This will allow calling PyThreadState_Clear()
without holding the lock. */ without holding the lock. */
@ -830,7 +881,7 @@ _PyThreadState_DeleteExcept(PyThreadState *tstate)
tstate->next->prev = tstate->prev; tstate->next->prev = tstate->prev;
tstate->prev = tstate->next = NULL; tstate->prev = tstate->next = NULL;
interp->tstate_head = tstate; interp->tstate_head = tstate;
HEAD_UNLOCK(); HEAD_UNLOCK(runtime);
/* Clear and deallocate all stale thread states. Even if this /* Clear and deallocate all stale thread states. Even if this
executes Python code, we should be safe since it executes executes Python code, we should be safe since it executes
in the current thread, not one of the stale threads. */ in the current thread, not one of the stale threads. */
@ -860,12 +911,12 @@ PyThreadState_Get(void)
} }
PyThreadState * static PyThreadState *
PyThreadState_Swap(PyThreadState *newts) _PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts)
{ {
PyThreadState *oldts = _PyThreadState_GET(); PyThreadState *oldts = _PyRuntimeGILState_GetThreadState(gilstate);
_PyThreadState_SET(newts); _PyRuntimeGILState_SetThreadState(gilstate, newts);
/* It should not be possible for more than one thread state /* It should not be possible for more than one thread state
to be used for a thread. Check this the best we can in debug to be used for a thread. Check this the best we can in debug
builds. builds.
@ -876,7 +927,7 @@ PyThreadState_Swap(PyThreadState *newts)
to it, we need to ensure errno doesn't change. to it, we need to ensure errno doesn't change.
*/ */
int err = errno; int err = errno;
PyThreadState *check = PyGILState_GetThisThreadState(); PyThreadState *check = _PyGILState_GetThisThreadState(gilstate);
if (check && check->interp == newts->interp && check != newts) if (check && check->interp == newts->interp && check != newts)
Py_FatalError("Invalid thread state for this thread"); Py_FatalError("Invalid thread state for this thread");
errno = err; errno = err;
@ -885,6 +936,12 @@ PyThreadState_Swap(PyThreadState *newts)
return oldts; return oldts;
} }
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
return _PyThreadState_Swap(&_PyRuntime.gilstate, newts);
}
/* An extension mechanism to store arbitrary additional per-thread state. /* An extension mechanism to store arbitrary additional per-thread state.
PyThreadState_GetDict() returns a dictionary that can be used to hold such PyThreadState_GetDict() returns a dictionary that can be used to hold such
state; the caller should pick a unique key and store its state there. If state; the caller should pick a unique key and store its state there. If
@ -928,7 +985,8 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
* list of thread states we're traversing, so to prevent that we lock * list of thread states we're traversing, so to prevent that we lock
* head_mutex for the duration. * head_mutex for the duration.
*/ */
HEAD_LOCK(); _PyRuntimeState *runtime = &_PyRuntime;
HEAD_LOCK(runtime);
for (p = interp->tstate_head; p != NULL; p = p->next) { for (p = interp->tstate_head; p != NULL; p = p->next) {
if (p->thread_id == id) { if (p->thread_id == id) {
/* Tricky: we need to decref the current value /* Tricky: we need to decref the current value
@ -941,13 +999,13 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
PyObject *old_exc = p->async_exc; PyObject *old_exc = p->async_exc;
Py_XINCREF(exc); Py_XINCREF(exc);
p->async_exc = exc; p->async_exc = exc;
HEAD_UNLOCK(); HEAD_UNLOCK(runtime);
Py_XDECREF(old_exc); Py_XDECREF(old_exc);
_PyEval_SignalAsyncExc(); _PyEval_SignalAsyncExc();
return 1; return 1;
} }
} }
HEAD_UNLOCK(); HEAD_UNLOCK(runtime);
return 0; return 0;
} }
@ -1003,8 +1061,9 @@ _PyThread_CurrentFrames(void)
* Because these lists can mutate even when the GIL is held, we * Because these lists can mutate even when the GIL is held, we
* need to grab head_mutex for the duration. * need to grab head_mutex for the duration.
*/ */
HEAD_LOCK(); _PyRuntimeState *runtime = &_PyRuntime;
for (i = _PyRuntime.interpreters.head; i != NULL; i = i->next) { HEAD_LOCK(runtime);
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
PyThreadState *t; PyThreadState *t;
for (t = i->tstate_head; t != NULL; t = t->next) { for (t = i->tstate_head; t != NULL; t = t->next) {
PyObject *id; PyObject *id;
@ -1021,11 +1080,11 @@ _PyThread_CurrentFrames(void)
goto Fail; goto Fail;
} }
} }
HEAD_UNLOCK(); HEAD_UNLOCK(runtime);
return result; return result;
Fail: Fail:
HEAD_UNLOCK(); HEAD_UNLOCK(runtime);
Py_DECREF(result); Py_DECREF(result);
return NULL; return NULL;
} }
@ -1044,8 +1103,9 @@ static int
PyThreadState_IsCurrent(PyThreadState *tstate) PyThreadState_IsCurrent(PyThreadState *tstate)
{ {
/* Must be the tstate for this thread */ /* Must be the tstate for this thread */
assert(PyGILState_GetThisThreadState()==tstate); struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
return tstate == _PyThreadState_GET(); assert(_PyGILState_GetThisThreadState(gilstate) == tstate);
return tstate == _PyRuntimeGILState_GetThreadState(gilstate);
} }
/* Internal initialization/finalization functions called by /* Internal initialization/finalization functions called by
@ -1093,7 +1153,7 @@ void
_PyGILState_Reinit(_PyRuntimeState *runtime) _PyGILState_Reinit(_PyRuntimeState *runtime)
{ {
struct _gilstate_runtime_state *gilstate = &runtime->gilstate; struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
PyThreadState *tstate = PyGILState_GetThisThreadState(); PyThreadState *tstate = _PyGILState_GetThisThreadState(gilstate);
PyThread_tss_delete(&gilstate->autoTSSkey); PyThread_tss_delete(&gilstate->autoTSSkey);
if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) {
@ -1147,36 +1207,45 @@ _PyGILState_NoteThreadState(struct _gilstate_runtime_state *gilstate, PyThreadSt
} }
/* The public functions */ /* The public functions */
static PyThreadState *
_PyGILState_GetThisThreadState(struct _gilstate_runtime_state *gilstate)
{
if (gilstate->autoInterpreterState == NULL)
return NULL;
return (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey);
}
PyThreadState * PyThreadState *
PyGILState_GetThisThreadState(void) PyGILState_GetThisThreadState(void)
{ {
if (_PyRuntime.gilstate.autoInterpreterState == NULL) return _PyGILState_GetThisThreadState(&_PyRuntime.gilstate);
return NULL;
return (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey);
} }
int int
PyGILState_Check(void) PyGILState_Check(void)
{ {
PyThreadState *tstate;
if (!_PyGILState_check_enabled) if (!_PyGILState_check_enabled) {
return 1;
if (!PyThread_tss_is_created(&_PyRuntime.gilstate.autoTSSkey)) {
return 1; return 1;
} }
tstate = _PyThreadState_GET(); struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
if (tstate == NULL) if (!PyThread_tss_is_created(&gilstate->autoTSSkey)) {
return 0; return 1;
}
return (tstate == PyGILState_GetThisThreadState()); PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate);
if (tstate == NULL) {
return 0;
}
return (tstate == _PyGILState_GetThisThreadState(gilstate));
} }
PyGILState_STATE PyGILState_STATE
PyGILState_Ensure(void) PyGILState_Ensure(void)
{ {
struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
int current; int current;
PyThreadState *tcur; PyThreadState *tcur;
int need_init_threads = 0; int need_init_threads = 0;
@ -1187,14 +1256,14 @@ PyGILState_Ensure(void)
called Py_Initialize() and usually PyEval_InitThreads(). called Py_Initialize() and usually PyEval_InitThreads().
*/ */
/* Py_Initialize() hasn't been called! */ /* Py_Initialize() hasn't been called! */
assert(_PyRuntime.gilstate.autoInterpreterState); assert(gilstate->autoInterpreterState);
tcur = (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey); tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey);
if (tcur == NULL) { if (tcur == NULL) {
need_init_threads = 1; need_init_threads = 1;
/* Create a new thread state for this thread */ /* Create a new thread state for this thread */
tcur = PyThreadState_New(_PyRuntime.gilstate.autoInterpreterState); tcur = PyThreadState_New(gilstate->autoInterpreterState);
if (tcur == NULL) if (tcur == NULL)
Py_FatalError("Couldn't create thread-state for new thread"); Py_FatalError("Couldn't create thread-state for new thread");
/* This is our thread state! We'll need to delete it in the /* This is our thread state! We'll need to delete it in the
@ -1230,18 +1299,21 @@ PyGILState_Ensure(void)
void void
PyGILState_Release(PyGILState_STATE oldstate) PyGILState_Release(PyGILState_STATE oldstate)
{ {
PyThreadState *tcur = (PyThreadState *)PyThread_tss_get( _PyRuntimeState *runtime = &_PyRuntime;
&_PyRuntime.gilstate.autoTSSkey); PyThreadState *tcur = PyThread_tss_get(&runtime->gilstate.autoTSSkey);
if (tcur == NULL) if (tcur == NULL) {
Py_FatalError("auto-releasing thread-state, " Py_FatalError("auto-releasing thread-state, "
"but no thread-state for this thread"); "but no thread-state for this thread");
}
/* We must hold the GIL and have our thread state current */ /* We must hold the GIL and have our thread state current */
/* XXX - remove the check - the assert should be fine, /* XXX - remove the check - the assert should be fine,
but while this is very new (April 2003), the extra check but while this is very new (April 2003), the extra check
by release-only users can't hurt. by release-only users can't hurt.
*/ */
if (! PyThreadState_IsCurrent(tcur)) if (!PyThreadState_IsCurrent(tcur)) {
Py_FatalError("This thread state must be current when releasing"); Py_FatalError("This thread state must be current when releasing");
}
assert(PyThreadState_IsCurrent(tcur)); assert(PyThreadState_IsCurrent(tcur));
--tcur->gilstate_counter; --tcur->gilstate_counter;
assert(tcur->gilstate_counter >= 0); /* illegal counter value */ assert(tcur->gilstate_counter >= 0); /* illegal counter value */
@ -1258,7 +1330,7 @@ PyGILState_Release(PyGILState_STATE oldstate)
* races; see bugs 225673 and 1061968 (that nasty bug has a * races; see bugs 225673 and 1061968 (that nasty bug has a
* habit of coming back). * habit of coming back).
*/ */
PyThreadState_DeleteCurrent(); _PyThreadState_DeleteCurrent(runtime);
} }
/* Release the lock if necessary */ /* Release the lock if necessary */
else if (oldstate == PyGILState_UNLOCKED) else if (oldstate == PyGILState_UNLOCKED)
@ -1363,7 +1435,8 @@ _release_xidata(void *arg)
} }
static void static void
_call_in_interpreter(PyInterpreterState *interp, _call_in_interpreter(struct _gilstate_runtime_state *gilstate,
PyInterpreterState *interp,
void (*func)(void *), void *arg) void (*func)(void *), void *arg)
{ {
/* We would use Py_AddPendingCall() if it weren't specific to the /* We would use Py_AddPendingCall() if it weren't specific to the
@ -1371,18 +1444,18 @@ _call_in_interpreter(PyInterpreterState *interp,
* naive approach. * naive approach.
*/ */
PyThreadState *save_tstate = NULL; PyThreadState *save_tstate = NULL;
if (interp != _PyInterpreterState_Get()) { if (interp != _PyRuntimeGILState_GetThreadState(gilstate)->interp) {
// XXX Using the "head" thread isn't strictly correct. // XXX Using the "head" thread isn't strictly correct.
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
// XXX Possible GILState issues? // XXX Possible GILState issues?
save_tstate = PyThreadState_Swap(tstate); save_tstate = _PyThreadState_Swap(gilstate, tstate);
} }
func(arg); func(arg);
// Switch back. // Switch back.
if (save_tstate != NULL) { if (save_tstate != NULL) {
PyThreadState_Swap(save_tstate); _PyThreadState_Swap(gilstate, save_tstate);
} }
} }
@ -1405,7 +1478,8 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
} }
// "Release" the data and/or the object. // "Release" the data and/or the object.
_call_in_interpreter(interp, _release_xidata, data); struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
_call_in_interpreter(gilstate, interp, _release_xidata, data);
} }
PyObject * PyObject *
@ -1421,7 +1495,8 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
crossinterpdatafunc. It would be simpler and more efficient. */ crossinterpdatafunc. It would be simpler and more efficient. */
static int static int
_register_xidata(PyTypeObject *cls, crossinterpdatafunc getdata) _register_xidata(struct _xidregistry *xidregistry, PyTypeObject *cls,
crossinterpdatafunc getdata)
{ {
// Note that we effectively replace already registered classes // Note that we effectively replace already registered classes
// rather than failing. // rather than failing.
@ -1430,12 +1505,12 @@ _register_xidata(PyTypeObject *cls, crossinterpdatafunc getdata)
return -1; return -1;
newhead->cls = cls; newhead->cls = cls;
newhead->getdata = getdata; newhead->getdata = getdata;
newhead->next = _PyRuntime.xidregistry.head; newhead->next = xidregistry->head;
_PyRuntime.xidregistry.head = newhead; xidregistry->head = newhead;
return 0; return 0;
} }
static void _register_builtins_for_crossinterpreter_data(void); static void _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry);
int int
_PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls,
@ -1453,12 +1528,13 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls,
// Make sure the class isn't ever deallocated. // Make sure the class isn't ever deallocated.
Py_INCREF((PyObject *)cls); Py_INCREF((PyObject *)cls);
PyThread_acquire_lock(_PyRuntime.xidregistry.mutex, WAIT_LOCK); struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ;
if (_PyRuntime.xidregistry.head == NULL) { PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK);
_register_builtins_for_crossinterpreter_data(); if (xidregistry->head == NULL) {
_register_builtins_for_crossinterpreter_data(xidregistry);
} }
int res = _register_xidata(cls, getdata); int res = _register_xidata(xidregistry, cls, getdata);
PyThread_release_lock(_PyRuntime.xidregistry.mutex); PyThread_release_lock(xidregistry->mutex);
return res; return res;
} }
@ -1469,13 +1545,14 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls,
crossinterpdatafunc crossinterpdatafunc
_PyCrossInterpreterData_Lookup(PyObject *obj) _PyCrossInterpreterData_Lookup(PyObject *obj)
{ {
struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ;
PyObject *cls = PyObject_Type(obj); PyObject *cls = PyObject_Type(obj);
crossinterpdatafunc getdata = NULL; crossinterpdatafunc getdata = NULL;
PyThread_acquire_lock(_PyRuntime.xidregistry.mutex, WAIT_LOCK); PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK);
struct _xidregitem *cur = _PyRuntime.xidregistry.head; struct _xidregitem *cur = xidregistry->head;
if (cur == NULL) { if (cur == NULL) {
_register_builtins_for_crossinterpreter_data(); _register_builtins_for_crossinterpreter_data(xidregistry);
cur = _PyRuntime.xidregistry.head; cur = xidregistry->head;
} }
for(; cur != NULL; cur = cur->next) { for(; cur != NULL; cur = cur->next) {
if (cur->cls == (PyTypeObject *)cls) { if (cur->cls == (PyTypeObject *)cls) {
@ -1484,7 +1561,7 @@ _PyCrossInterpreterData_Lookup(PyObject *obj)
} }
} }
Py_DECREF(cls); Py_DECREF(cls);
PyThread_release_lock(_PyRuntime.xidregistry.mutex); PyThread_release_lock(xidregistry->mutex);
return getdata; return getdata;
} }
@ -1591,25 +1668,25 @@ _none_shared(PyObject *obj, _PyCrossInterpreterData *data)
} }
static void static void
_register_builtins_for_crossinterpreter_data(void) _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry)
{ {
// None // None
if (_register_xidata((PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) { if (_register_xidata(xidregistry, (PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) {
Py_FatalError("could not register None for cross-interpreter sharing"); Py_FatalError("could not register None for cross-interpreter sharing");
} }
// int // int
if (_register_xidata(&PyLong_Type, _long_shared) != 0) { if (_register_xidata(xidregistry, &PyLong_Type, _long_shared) != 0) {
Py_FatalError("could not register int for cross-interpreter sharing"); Py_FatalError("could not register int for cross-interpreter sharing");
} }
// bytes // bytes
if (_register_xidata(&PyBytes_Type, _bytes_shared) != 0) { if (_register_xidata(xidregistry, &PyBytes_Type, _bytes_shared) != 0) {
Py_FatalError("could not register bytes for cross-interpreter sharing"); Py_FatalError("could not register bytes for cross-interpreter sharing");
} }
// str // str
if (_register_xidata(&PyUnicode_Type, _str_shared) != 0) { if (_register_xidata(xidregistry, &PyUnicode_Type, _str_shared) != 0) {
Py_FatalError("could not register str for cross-interpreter sharing"); Py_FatalError("could not register str for cross-interpreter sharing");
} }
} }