Skip to content

Commit 5e7283c

Browse files
PyThreadState_IsCurrent() -> holds_gil().
1 parent 4b952e0 commit 5e7283c

File tree

1 file changed

+30
-26
lines changed

1 file changed

+30
-26
lines changed

Python/pystate.c

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,26 @@ unbind_tstate(PyThreadState *tstate)
206206
tstate->native_thread_id = -1;
207207
}
208208

209+
/* This is not exported, as it is not reliable! It can only
210+
ever be compared to the state for the *current* thread.
211+
* If not equal, then it doesn't matter that the actual
212+
value may change immediately after comparison, as it can't
213+
possibly change to the current thread's state.
214+
* If equal, then the current thread holds the lock, so the value can't
215+
change until we yield the lock.
216+
*/
217+
static int
218+
holds_gil(PyThreadState *tstate)
219+
{
220+
// XXX Fall back to tstate->interp->runtime->ceval.gil.last_holder
221+
// (and tstate->interp->runtime->ceval.gil.locked).
222+
assert(tstate != NULL);
223+
_PyRuntimeState *runtime = tstate->interp->runtime;
224+
/* Must be the tstate for this thread */
225+
assert(tstate == current_tss_get(runtime));
226+
return tstate == current_fast_get(runtime);
227+
}
228+
209229

210230
/* the global runtime */
211231

@@ -1410,6 +1430,7 @@ _PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts)
14101430
to be used for a thread. Check this the best we can in debug
14111431
builds.
14121432
*/
1433+
// XXX The above isn't true when multiple interpreters are involved.
14131434
#if defined(Py_DEBUG)
14141435
if (newts && current_tss_initialized(runtime)) {
14151436
/* This can be called from PyEval_RestoreThread(). Similar
@@ -1692,24 +1713,6 @@ _PyThread_CurrentExceptions(void)
16921713

16931714
/* Python "auto thread state" API. */
16941715

1695-
/* Keep this as a static, as it is not reliable! It can only
1696-
ever be compared to the state for the *current* thread.
1697-
* If not equal, then it doesn't matter that the actual
1698-
value may change immediately after comparison, as it can't
1699-
possibly change to the current thread's state.
1700-
* If equal, then the current thread holds the lock, so the value can't
1701-
change until we yield the lock.
1702-
*/
1703-
static int
1704-
PyThreadState_IsCurrent(PyThreadState *tstate)
1705-
{
1706-
assert(tstate != NULL);
1707-
_PyRuntimeState *runtime = tstate->interp->runtime;
1708-
/* Must be the tstate for this thread */
1709-
assert(tstate == current_tss_get(runtime));
1710-
return tstate == current_fast_get(runtime);
1711-
}
1712-
17131716
/* Internal initialization/finalization functions called by
17141717
Py_Initialize/Py_FinalizeEx
17151718
*/
@@ -1817,7 +1820,7 @@ PyGILState_Ensure(void)
18171820
assert(runtime->gilstate.autoInterpreterState != NULL);
18181821

18191822
PyThreadState *tcur = current_tss_get(runtime);
1820-
int current;
1823+
int has_gil;
18211824
if (tcur == NULL) {
18221825
/* Create a new Python thread state for this thread */
18231826
tcur = PyThreadState_New(runtime->gilstate.autoInterpreterState);
@@ -1829,13 +1832,13 @@ PyGILState_Ensure(void)
18291832
matching call to PyGILState_Release(). */
18301833
assert(tcur->gilstate_counter == 1);
18311834
tcur->gilstate_counter = 0;
1832-
current = 0; /* new thread state is never current */
1835+
has_gil = 0; /* new thread state is never current */
18331836
}
18341837
else {
1835-
current = PyThreadState_IsCurrent(tcur);
1838+
has_gil = holds_gil(tcur);
18361839
}
18371840

1838-
if (current == 0) {
1841+
if (!has_gil) {
18391842
PyEval_RestoreThread(tcur);
18401843
}
18411844

@@ -1846,7 +1849,7 @@ PyGILState_Ensure(void)
18461849
*/
18471850
++tcur->gilstate_counter;
18481851

1849-
return current ? PyGILState_LOCKED : PyGILState_UNLOCKED;
1852+
return has_gil ? PyGILState_LOCKED : PyGILState_UNLOCKED;
18501853
}
18511854

18521855
void
@@ -1864,12 +1867,12 @@ PyGILState_Release(PyGILState_STATE oldstate)
18641867
but while this is very new (April 2003), the extra check
18651868
by release-only users can't hurt.
18661869
*/
1867-
if (!PyThreadState_IsCurrent(tstate)) {
1870+
if (!holds_gil(tstate)) {
18681871
_Py_FatalErrorFormat(__func__,
18691872
"thread state %p must be current when releasing",
18701873
tstate);
18711874
}
1872-
assert(PyThreadState_IsCurrent(tstate));
1875+
assert(holds_gil(tstate));
18731876
--tstate->gilstate_counter;
18741877
assert(tstate->gilstate_counter >= 0); /* illegal counter value */
18751878

@@ -1889,8 +1892,9 @@ PyGILState_Release(PyGILState_STATE oldstate)
18891892
_PyThreadState_DeleteCurrent(tstate);
18901893
}
18911894
/* Release the lock if necessary */
1892-
else if (oldstate == PyGILState_UNLOCKED)
1895+
else if (oldstate == PyGILState_UNLOCKED) {
18931896
PyEval_SaveThread();
1897+
}
18941898
}
18951899

18961900

0 commit comments

Comments
 (0)