Description
Feature or enhancement
Proposal:
Nearly all of the C-API expects that the current thread holds the GIL when called. Mostly, users of the C-API had to know before calling the C-API. Beck in the day it wasn't obvious how. This was the motivation behind adding PyGILState_Check()
.
The key point in this issue is that the name PyGILState_Check()
unnecessarily associates the capability with the PyGILState_*
API. Users would benefit from a different function name. I'd think something like Py_HoldsGIL()
would be better.
Why was the function added as PyGILState_Check()
? Perhaps @kristjanvalur remembers. It was added in 2013, 10 years after the PEP 311 implementation, so it's not because it was part of the PEP. I'd guess it's mostly because it was implemented using PyGILState_GetThisThreadState()
.
It's also notable that a lot of things have changed in the runtime since 2013. At the time PyGILState_Check()
was added:
- you could use
PyThreadState_Get()
(orPyThreadState_GET()
) to get the tstate active in the current thread, but only if it held the GIL - you could get the last active tstate in the current thread using
PyGILState_GetThisThreadState()
- internally there was a static
PyThreadState_IsCurrent()
that sort of merged the two
Here some of the developments since then:
- every tstate now knows whether or not it holds the GIL
- the runtime now keeps track of the last tstate to hold the GIL
- the current tstate has moved from a global variable to a thread-local variable
- each interpreter now has its own GIL
Here's the history in some detail:
(expand)
- 1997 - thread state (& interp state) introduced (commit a027efa)
- current tstate stored in static global variable
PyThreadState_Get()
exposes itPyThreadState_Swap()
modifies it- GIL must be held to call it, so that global effectively indicates which tstate (i.e. thread) holds the GIL
- 1998 - added
PyThreadState_GET()
macro (commit 275ea67)- current tstate global variable moved to "internal" C-API (commit 18bc7c2)
- 2003 - PEP 311 adds the
PyGILState_*
API (commit 8d98d2c),- last tstate used in current OS thread stored in thread-specific storage (
autoTLSkey
) PyGILState_GetThisThreadState()
exposes it- it is set to NULL when a tstate is destroyed and it was the last one used in the current thread
- adds static
PyThreadState_IsCurrent()
that indicates if that thread-local tstate holds the GIL PyGILState_Check()
does not exist yet
- last tstate used in current OS thread stored in thread-specific storage (
- 2009 - new GIL impl (commit 074e5ed)
- adds new "last_holder" and "held" state
- 2013 -
PyGILState_Check()
added (Add api PyGILState_Check #61724, commit 684cd0e)- effectively exposes
PyThreadState_IsCurrent(PyGILState_GetThisThreadState())
- effectively exposes
- 2017 -
_PyRuntimeState
added (commit 2ebc5ce)- moved "current" tstate from global var in pystate.c (
_PyThreadState_Current
) to_PyRuntime.gilstate.tstate_current
- moved GILState-related global vars to
_PyRuntime.gilstate
- moved GIL from global vars to
_PyRuntime.ceval.gil
- moved "current" tstate from global var in pystate.c (
- 2018 - added
_PyThreadState_GET()
, without NULL check (commit 50b4857) - 2023 - moved "current" tstate from
_PyRuntime.gilstate.tstate_current
to_PyRuntime.tstate_current
(commit 6036c3e) - 2023 - moved "current" tstate to a thread-local variable in pystate.c (commit f8abfa3)
- 2023 - added internal
current_thread_holds_gil
(commit 92d8bff) - 2023 - moved GIL to the interpreter state (commit 5c9ee49)
- 2024 - added
PyThreadState._status.holds_gil
(commit be1dfcc)
Has this already been discussed elsewhere?
No response given
Links to previous discussion of this feature:
No response