@@ -176,13 +176,20 @@ current_tss_reinit(_PyRuntimeState *runtime)
176
176
}
177
177
#endif
178
178
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
+ }
179
186
180
187
static void
181
188
bind_tstate (PyThreadState * tstate )
182
189
{
183
190
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
186
193
assert (tstate -> thread_id == 0 );
187
194
assert (tstate -> native_thread_id == 0 );
188
195
_PyRuntimeState * runtime = tstate -> interp -> runtime ;
@@ -222,8 +229,8 @@ static void
222
229
unbind_tstate (PyThreadState * tstate )
223
230
{
224
231
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));
227
234
assert (tstate -> thread_id > 0 );
228
235
#ifdef PY_HAVE_THREAD_NATIVE_ID
229
236
assert (tstate -> native_thread_id > 0 );
@@ -1078,6 +1085,16 @@ _PyInterpreterState_LookUpID(int64_t requested_id)
1078
1085
/* the per-thread runtime state */
1079
1086
/********************************/
1080
1087
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
+
1081
1098
//----------
1082
1099
// lifecycle
1083
1100
//----------
@@ -1246,6 +1263,10 @@ _PyThreadState_Init(PyThreadState *tstate)
1246
1263
void
1247
1264
PyThreadState_Clear (PyThreadState * tstate )
1248
1265
{
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
+
1249
1270
/* XXX Conditions we need to enforce:
1250
1271
1251
1272
* the GIL must be held by the current thread
@@ -1313,6 +1334,8 @@ PyThreadState_Clear(PyThreadState *tstate)
1313
1334
tstate -> on_delete (tstate -> on_delete_data );
1314
1335
}
1315
1336
1337
+ tstate -> _status .cleared = 1 ;
1338
+
1316
1339
// XXX Call _PyThreadStateSwap(runtime, NULL) here if "current".
1317
1340
// XXX Do it as early in the function as possible.
1318
1341
}
@@ -1322,6 +1345,8 @@ PyThreadState_Clear(PyThreadState *tstate)
1322
1345
static void
1323
1346
tstate_delete_common (PyThreadState * tstate )
1324
1347
{
1348
+ assert (tstate -> _status .cleared && !tstate -> _status .finalized );
1349
+
1325
1350
PyInterpreterState * interp = tstate -> interp ;
1326
1351
if (interp == NULL ) {
1327
1352
Py_FatalError ("NULL interpreter" );
@@ -1351,6 +1376,8 @@ tstate_delete_common(PyThreadState *tstate)
1351
1376
_PyObject_VirtualFree (chunk , chunk -> size );
1352
1377
chunk = prev ;
1353
1378
}
1379
+
1380
+ tstate -> _status .finalized = 1 ;
1354
1381
}
1355
1382
1356
1383
@@ -1583,13 +1610,17 @@ PyThreadState *
1583
1610
_PyThreadState_Swap (_PyRuntimeState * runtime , PyThreadState * newts )
1584
1611
{
1585
1612
PyThreadState * oldts = current_fast_get (runtime );
1613
+ // XXX assert(oldts == NULL || tstate_is_alive(oldts));
1614
+ // XXX tstate_is_bound(oldts)
1586
1615
1587
1616
if (newts == NULL ) {
1588
1617
current_fast_clear (runtime );
1589
1618
}
1590
1619
else {
1620
+ assert (tstate_is_alive (newts ) && tstate_is_bound (newts ));
1591
1621
current_fast_set (runtime , newts );
1592
1622
}
1623
+
1593
1624
/* It should not be possible for more than one thread state
1594
1625
to be used for a thread. Check this the best we can in debug
1595
1626
builds.
0 commit comments