Skip to content

Commit 3418d43

Browse files
Add more status fields.
1 parent a9cde7f commit 3418d43

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

Include/cpython/pystate.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,19 @@ struct _ts {
125125
In order to be effective, this must be set to 0 during or right
126126
after allocation. */
127127
unsigned int initialized:1;
128+
128129
/* Has been bound to an OS thread. */
129130
unsigned int bound:1;
130131
/* Has been unbound from its OS thread. */
131132
unsigned int unbound:1;
132-
// XXX finalizing
133-
// XXX cleared
134-
// XXX finalized
133+
134+
/* various stages of finalization */
135+
unsigned int finalizing:1;
136+
unsigned int cleared:1;
137+
unsigned int finalized:1;
138+
135139
/* padding to align to 4 bytes */
136-
unsigned int :29;
140+
unsigned int :26;
137141
} _status;
138142

139143
int py_recursion_remaining;

Python/pystate.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,20 @@ current_tss_reinit(_PyRuntimeState *runtime)
176176
}
177177
#endif
178178

179+
static inline int tstate_is_alive(PyThreadState *tstate);
180+
181+
static inline int
182+
tstate_is_bound(PyThreadState *tstate)
183+
{
184+
return tstate->_status.bound && !tstate->_status.unbound;
185+
}
179186

180187
static void
181188
bind_tstate(PyThreadState *tstate)
182189
{
183190
assert(tstate != NULL);
184-
assert(tstate->_status.initialized && !tstate->_status.bound);
185-
// XXX tstate_alive()
191+
assert(tstate_is_alive(tstate) && !tstate->_status.bound);
192+
assert(!tstate->_status.unbound); // just in case
186193
assert(tstate->thread_id == 0);
187194
assert(tstate->native_thread_id == 0);
188195
_PyRuntimeState *runtime = tstate->interp->runtime;
@@ -222,8 +229,8 @@ static void
222229
unbind_tstate(PyThreadState *tstate)
223230
{
224231
assert(tstate != NULL);
225-
assert(tstate->_status.bound && !tstate->_status.unbound);
226-
// XXX tstate_alive()
232+
assert(tstate_is_bound(tstate));
233+
// XXX assert(tstate_is_alive(tstate) && tstate_is_bound(tstate));
227234
assert(tstate->thread_id > 0);
228235
#ifdef PY_HAVE_THREAD_NATIVE_ID
229236
assert(tstate->native_thread_id > 0);
@@ -1078,6 +1085,16 @@ _PyInterpreterState_LookUpID(int64_t requested_id)
10781085
/* the per-thread runtime state */
10791086
/********************************/
10801087

1088+
static inline int
1089+
tstate_is_alive(PyThreadState *tstate)
1090+
{
1091+
return (tstate->_status.initialized &&
1092+
!tstate->_status.finalized &&
1093+
!tstate->_status.cleared &&
1094+
!tstate->_status.finalizing);
1095+
}
1096+
1097+
10811098
//----------
10821099
// lifecycle
10831100
//----------
@@ -1246,6 +1263,10 @@ _PyThreadState_Init(PyThreadState *tstate)
12461263
void
12471264
PyThreadState_Clear(PyThreadState *tstate)
12481265
{
1266+
assert(tstate->_status.initialized && !tstate->_status.cleared);
1267+
// XXX !tstate->_status.bound || tstate->_status.unbound
1268+
tstate->_status.finalizing = 1; // just in case
1269+
12491270
/* XXX Conditions we need to enforce:
12501271
12511272
* the GIL must be held by the current thread
@@ -1313,6 +1334,8 @@ PyThreadState_Clear(PyThreadState *tstate)
13131334
tstate->on_delete(tstate->on_delete_data);
13141335
}
13151336

1337+
tstate->_status.cleared = 1;
1338+
13161339
// XXX Call _PyThreadStateSwap(runtime, NULL) here if "current".
13171340
// XXX Do it as early in the function as possible.
13181341
}
@@ -1322,6 +1345,8 @@ PyThreadState_Clear(PyThreadState *tstate)
13221345
static void
13231346
tstate_delete_common(PyThreadState *tstate)
13241347
{
1348+
assert(tstate->_status.cleared && !tstate->_status.finalized);
1349+
13251350
PyInterpreterState *interp = tstate->interp;
13261351
if (interp == NULL) {
13271352
Py_FatalError("NULL interpreter");
@@ -1351,6 +1376,8 @@ tstate_delete_common(PyThreadState *tstate)
13511376
_PyObject_VirtualFree(chunk, chunk->size);
13521377
chunk = prev;
13531378
}
1379+
1380+
tstate->_status.finalized = 1;
13541381
}
13551382

13561383

@@ -1583,13 +1610,17 @@ PyThreadState *
15831610
_PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts)
15841611
{
15851612
PyThreadState *oldts = current_fast_get(runtime);
1613+
// XXX assert(oldts == NULL || tstate_is_alive(oldts));
1614+
// XXX tstate_is_bound(oldts)
15861615

15871616
if (newts == NULL) {
15881617
current_fast_clear(runtime);
15891618
}
15901619
else {
1620+
assert(tstate_is_alive(newts) && tstate_is_bound(newts));
15911621
current_fast_set(runtime, newts);
15921622
}
1623+
15931624
/* It should not be possible for more than one thread state
15941625
to be used for a thread. Check this the best we can in debug
15951626
builds.

0 commit comments

Comments
 (0)