8000 gh-59956: Clarify GILState-related Code by ericsnowcurrently · Pull Request #101161 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-59956: Clarify GILState-related Code #101161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jan 19, 2023
Merged
Prev Previous commit
Next Next commit
Factor out "current_fast" helpers.
  • Loading branch information
ericsnowcurrently committed Jan 19, 2023
commit a5eb3d86fc0e9153fe6693ff96ee84edf861c1e1
62 changes: 41 additions & 21 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,30 @@ static void _PyThreadState_Delete(PyThreadState *tstate, int check_current);

/* the current thread state */

#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))
static inline PyThreadState *
current_fast_get(_PyRuntimeState *runtime)
{
// The GIL must be held by the current thread.
return (PyThreadState*)_Py_atomic_load_relaxed(
&runtime->gilstate.tstate_current);
}

static inline void
current_fast_set(_PyRuntimeState *runtime, PyThreadState *tstate)
{
// The GIL must be held by the current thread.
assert(tstate != NULL);
_Py_atomic_store_relaxed(&runtime->gilstate.tstate_current,
(uintptr_t)tstate);
}

static inline void
current_fast_clear(_PyRuntimeState *runtime)
{
// The GIL must be held by the current thread.
_Py_atomic_store_relaxed(&runtime->gilstate.tstate_current,
(uintptr_t)NULL);
}


static int
Expand Down Expand Up @@ -1145,8 +1164,7 @@ PyThreadState_Clear(PyThreadState *tstate)

/* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */
static void
tstate_delete_common(PyThreadState *tstate,
struct _gilstate_runtime_state *gilstate)
tstate_delete_common(PyThreadState *tstate)
{
_Py_EnsureTstateNotNULL(tstate);
PyInterpreterState *interp = tstate->interp;
Expand Down Expand Up @@ -1187,13 +1205,12 @@ tstate_delete_common(PyThreadState *tstate,
static void
_PyThreadState_Delete(PyThreadState *tstate, int check_current)
{
struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate;
if (check_current) {
if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) {
if (tstate == current_fast_get(tstate->interp->runtime)) {
_Py_FatalErrorFormat(__func__, "tstate %p is still current", tstate);
}
}
tstate_delete_common(tstate, gilstate);
tstate_delete_common(tstate);
free_threadstate(tstate);
}

Expand All @@ -1209,18 +1226,16 @@ void
_PyThreadState_DeleteCurrent(PyThreadState *tstate)
{
_Py_EnsureTstateNotNULL(tstate);
struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate;
tstate_delete_common(tstate, gilstate);
_PyRuntimeGILState_SetThreadState(gilstate, NULL);
tstate_delete_common(tstate);
current_fast_clear(tstate->interp->runtime);
_PyEval_ReleaseLock(tstate);
free_threadstate(tstate);
}

void
PyThreadState_DeleteCurrent(void)
{
struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate);
PyThreadState *tstate = current_fast_get(&_PyRuntime);
_PyThreadState_DeleteCurrent(tstate);
}

Expand Down Expand Up @@ -1286,9 +1301,14 @@ PyThreadState_Get(void)
PyThreadState *
_PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts)
{
PyThreadState *oldts = _PyRuntimeGILState_GetThreadState(&runtime->gilstate);
PyThreadState *oldts = current_fast_get(runtime);

_PyRuntimeGILState_SetThreadState(&runtime->gilstate, newts);
if (newts == NULL) {
current_fast_clear(runtime);
}
else {
current_fast_set(runtime, newts);
}
/* 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
builds.
Expand Down Expand Up @@ -1590,7 +1610,7 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
_PyRuntimeState *runtime = tstate->interp->runtime;
/* Must be the tstate for this thread */
assert(tstate == current_tss_get(runtime));
return tstate == _PyRuntimeGILState_GetThreadState(&runtime->gilstate);
return tstate == current_fast_get(runtime);
}

/* Internal initialization/finalization functions called by
Expand Down Expand Up @@ -1738,7 +1758,7 @@ PyGILState_Check(void)
return 1;
}

PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(&runtime->gilstate);
PyThreadState *tstate = current_fast_get(runtime);
if (tstate == NULL) {
return 0;
}
Expand Down Expand Up @@ -1830,7 +1850,7 @@ PyGILState_Release(PyGILState_STATE oldstate)
* races; see bugs 225673 and 1061968 (that nasty bug has a
* habit of coming back).
*/
assert(_PyRuntimeGILState_GetThreadState(&runtime->gilstate) == tstate);
assert(current_fast_get(runtime) == tstate);
_PyThreadState_DeleteCurrent(tstate);
}
/* Release the lock if necessary */
Expand Down Expand Up @@ -2017,7 +2037,7 @@ _call_in_interpreter(PyInterpreterState *interp, releasefunc func, void *arg)
*/
_PyRuntimeState *runtime = interp->runtime;
PyThreadState *save_tstate = NULL;
if (interp != _PyRuntimeGILState_GetThreadState(&runtime->gilstate)->interp) {
if (interp != current_fast_get(runtime)->interp) {
// XXX Using the "head" thread isn't strictly correct.
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
// XXX Possible GILState issues?
Expand Down
0