@@ -68,6 +68,8 @@ to avoid the expense of doing their own locking).
6868 For each of these functions, the GIL must be held by the current thread.
6969 */
7070
71+ static inline void
72+ ensure_tstate_is_valid (PyThreadState * tstate );
7173
7274/* The attached thread state for the current thread. */
7375_Py_thread_local PyThreadState * _Py_tss_tstate = NULL ;
@@ -89,7 +91,7 @@ current_fast_get(void)
8991static inline void
9092current_fast_set (_PyRuntimeState * Py_UNUSED (runtime ), PyThreadState * tstate )
9193{
92- assert (tstate != NULL );
94+ ensure_tstate_is_valid (tstate );
9395 _Py_tss_tstate = tstate ;
9496 assert (tstate -> interp != NULL );
9597 _Py_tss_interp = tstate -> interp ;
@@ -133,7 +135,7 @@ gilstate_get(void)
133135static inline void
134136gilstate_set (PyThreadState * tstate )
135137{
136- assert (tstate != NULL );
138+ ensure_tstate_is_valid (tstate );
137139 _Py_tss_gilstate = tstate ;
138140}
139141
@@ -162,7 +164,7 @@ static void tstate_mimalloc_bind(PyThreadState *);
162164static void
163165bind_tstate (PyThreadState * tstate )
164166{
165- assert (tstate != NULL );
167+ ensure_tstate_is_valid (tstate );
166168 assert (tstate_is_alive (tstate ) && !tstate -> _status .bound );
167169 assert (!tstate -> _status .unbound ); // just in case
168170 assert (!tstate -> _status .bound_gilstate );
@@ -194,7 +196,7 @@ bind_tstate(PyThreadState *tstate)
194196static void
195197unbind_tstate (PyThreadState * tstate )
196198{
197- assert (tstate != NULL );
199+ ensure_tstate_is_valid (tstate );
198200 assert (tstate_is_bound (tstate ));
199201#ifndef HAVE_PTHREAD_STUBS
200202 assert (tstate -> thread_id > 0 );
@@ -235,7 +237,7 @@ unbind_tstate(PyThreadState *tstate)
235237static void
236238bind_gilstate_tstate (PyThreadState * tstate )
237239{
238- assert (tstate != NULL );
240+ ensure_tstate_is_valid (tstate );
239241 assert (tstate_is_alive (tstate ));
240242 assert (tstate_is_bound (tstate ));
241243 // XXX assert(!tstate->_status.active);
@@ -254,7 +256,7 @@ bind_gilstate_tstate(PyThreadState *tstate)
254256static void
255257unbind_gilstate_tstate (PyThreadState * tstate )
256258{
257- assert (tstate != NULL );
259+ ensure_tstate_is_valid (tstate );
258260 // XXX assert(tstate_is_alive(tstate));
259261 assert (tstate_is_bound (tstate ));
260262 // XXX assert(!tstate->_status.active);
@@ -282,7 +284,7 @@ holds_gil(PyThreadState *tstate)
282284{
283285 // XXX Fall back to tstate->interp->runtime->ceval.gil.last_holder
284286 // (and tstate->interp->runtime->ceval.gil.locked).
285- assert (tstate != NULL );
287+ ensure_tstate_is_valid (tstate );
286288 /* Must be the tstate for this thread */
287289 assert (tstate == gilstate_get ());
288290 return tstate == current_fast_get ();
@@ -781,7 +783,7 @@ static void
781783interpreter_clear (PyInterpreterState * interp , PyThreadState * tstate )
782784{
783785 assert (interp != NULL );
784- assert (tstate != NULL );
786+ ensure_tstate_is_valid (tstate );
785787 _PyRuntimeState * runtime = interp -> runtime ;
786788
787789 /* XXX Conditions we need to enforce:
@@ -2009,7 +2011,7 @@ PyThreadState_DeleteCurrent(void)
20092011PyThreadState *
20102012_PyThreadState_RemoveExcept (PyThreadState * tstate )
20112013{
2012- assert (tstate != NULL );
2014+ ensure_tstate_is_valid (tstate );
20132015 PyInterpreterState * interp = tstate -> interp ;
20142016 _PyRuntimeState * runtime = interp -> runtime ;
20152017
@@ -2078,7 +2080,7 @@ _PyThreadState_DeleteList(PyThreadState *list, int is_after_fork)
20782080PyObject *
20792081_PyThreadState_GetDict (PyThreadState * tstate )
20802082{
2081- assert (tstate != NULL );
2083+ ensure_tstate_is_valid (tstate );
20822084 if (tstate -> dict == NULL ) {
20832085 tstate -> dict = PyDict_New ();
20842086 if (tstate -> dict == NULL ) {
@@ -2103,15 +2105,15 @@ PyThreadState_GetDict(void)
21032105PyInterpreterState *
21042106PyThreadState_GetInterpreter (PyThreadState * tstate )
21052107{
2106- assert (tstate != NULL );
2108+ ensure_tstate_is_valid (tstate );
21072109 return tstate -> interp ;
21082110}
21092111
21102112
21112113PyFrameObject *
21122114PyThreadState_GetFrame (PyThreadState * tstate )
21132115{
2114- assert (tstate != NULL );
2116+ ensure_tstate_is_valid (tstate );
21152117 _PyInterpreterFrame * f = _PyThreadState_GetFrame (tstate );
21162118 if (f == NULL ) {
21172119 return NULL ;
@@ -2127,15 +2129,15 @@ PyThreadState_GetFrame(PyThreadState *tstate)
21272129uint64_t
21282130PyThreadState_GetID (PyThreadState * tstate )
21292131{
2130- assert (tstate != NULL );
2132+ ensure_tstate_is_valid (tstate );
21312133 return tstate -> id ;
21322134}
21332135
21342136
21352137static inline void
21362138tstate_activate (PyThreadState * tstate )
21372139{
2138- assert (tstate != NULL );
2140+ ensure_tstate_is_valid (tstate );
21392141 // XXX assert(tstate_is_alive(tstate));
21402142 assert (tstate_is_bound (tstate ));
21412143 assert (!tstate -> _status .active );
@@ -2152,7 +2154,7 @@ tstate_activate(PyThreadState *tstate)
21522154static inline void
21532155tstate_deactivate (PyThreadState * tstate )
21542156{
2155- assert (tstate != NULL );
2157+ ensure_tstate_is_valid (tstate );
21562158 // XXX assert(tstate_is_alive(tstate));
21572159 assert (tstate_is_bound (tstate ));
21582160 assert (tstate -> _status .active );
@@ -2170,6 +2172,7 @@ tstate_deactivate(PyThreadState *tstate)
21702172static int
21712173tstate_try_attach (PyThreadState * tstate )
21722174{
2175+ ensure_tstate_is_valid (tstate );
21732176#ifdef Py_GIL_DISABLED
21742177 int expected = _Py_THREAD_DETACHED ;
21752178 return _Py_atomic_compare_exchange_int (& tstate -> state ,
@@ -2185,6 +2188,7 @@ tstate_try_attach(PyThreadState *tstate)
21852188static void
21862189tstate_set_detached (PyThreadState * tstate , int detached_state )
21872190{
2191+ ensure_tstate_is_valid (tstate );
21882192 assert (_Py_atomic_load_int_relaxed (& tstate -> state ) == _Py_THREAD_ATTACHED );
21892193#ifdef Py_GIL_DISABLED
21902194 _Py_atomic_store_int (& tstate -> state , detached_state );
@@ -2196,6 +2200,7 @@ tstate_set_detached(PyThreadState *tstate, int detached_state)
21962200static void
21972201tstate_wait_attach (PyThreadState * tstate )
21982202{
2203+ ensure_tstate_is_valid (tstate );
21992204 do {
22002205 int state = _Py_atomic_load_int_relaxed (& tstate -> state );
22012206 if (state == _Py_THREAD_SUSPENDED ) {
@@ -2217,6 +2222,7 @@ tstate_wait_attach(PyThreadState *tstate)
22172222void
22182223_PyThreadState_Attach (PyThreadState * tstate )
22192224{
2225+ ensure_tstate_is_valid (tstate );
22202226#if defined(Py_DEBUG )
22212227 // This is called from PyEval_RestoreThread(). Similar
22222228 // to it, we need to ensure errno doesn't change.
@@ -2276,6 +2282,7 @@ _PyThreadState_Attach(PyThreadState *tstate)
22762282static void
22772283detach_thread (PyThreadState * tstate , int detached_state )
22782284{
2285+ ensure_tstate_is_valid (tstate );
22792286 // XXX assert(tstate_is_alive(tstate) && tstate_is_bound(tstate));
22802287 assert (_Py_atomic_load_int_relaxed (& tstate -> state ) == _Py_THREAD_ATTACHED );
22812288 assert (tstate == current_fast_get ());
@@ -2300,6 +2307,7 @@ _PyThreadState_Detach(PyThreadState *tstate)
23002307void
23012308_PyThreadState_Suspend (PyThreadState * tstate )
23022309{
2310+ ensure_tstate_is_valid (tstate );
23032311 _PyRuntimeState * runtime = & _PyRuntime ;
23042312
23052313 assert (_Py_atomic_load_int_relaxed (& tstate -> state ) == _Py_THREAD_ATTACHED );
@@ -2587,6 +2595,7 @@ PyThreadState_Get(void)
25872595{
25882596 PyThreadState * tstate = current_fast_get ();
25892597 _Py_EnsureTstateNotNULL (tstate );
2598+ ensure_tstate_is_valid (tstate );
25902599 return tstate ;
25912600}
25922601
@@ -2666,7 +2675,9 @@ PyInterpreterState_ThreadHead(PyInterpreterState *interp) {
26662675}
26672676
26682677PyThreadState *
2669- PyThreadState_Next (PyThreadState * tstate ) {
2678+ PyThreadState_Next (PyThreadState * tstate )
2679+ {
2680+ ensure_tstate_is_valid (tstate );
26702681 return tstate -> next ;
26712682}
26722683
@@ -2841,7 +2852,7 @@ void
28412852_PyGILState_SetTstate (PyThreadState * tstate )
28422853{
28432854 /* must init with valid states */
2844- assert (tstate != NULL );
2855+ ensure_tstate_is_valid (tstate );
28452856 assert (tstate -> interp != NULL );
28462857
28472858 if (!_Py_IsMainInterpreter (tstate -> interp )) {
@@ -3087,6 +3098,7 @@ _PyInterpreterState_HasFeature(PyInterpreterState *interp, unsigned long feature
30873098static PyObject * *
30883099push_chunk (PyThreadState * tstate , int size )
30893100{
3101+ ensure_tstate_is_valid (tstate );
30903102 int allocate_size = _PY_DATA_STACK_CHUNK_SIZE ;
30913103 while (allocate_size < (int )sizeof (PyObject * )* (size + MINIMUM_OVERHEAD )) {
30923104 allocate_size *= 2 ;
@@ -3123,6 +3135,7 @@ push_chunk(PyThreadState *tstate, int size)
31233135_PyInterpreterFrame *
31243136_PyThreadState_PushFrame (PyThreadState * tstate , size_t size )
31253137{
3138+ ensure_tstate_is_valid (tstate );
31263139 assert (size < INT_MAX /sizeof (PyObject * ));
31273140 if (_PyThreadState_HasStackSpace (tstate , (int )size )) {
31283141 _PyInterpreterFrame * res = (_PyInterpreterFrame * )tstate -> datastack_top ;
@@ -3135,6 +3148,7 @@ _PyThreadState_PushFrame(PyThreadState *tstate, size_t size)
31353148void
31363149_PyThreadState_PopFrame (PyThreadState * tstate , _PyInterpreterFrame * frame )
31373150{
3151+ ensure_tstate_is_valid (tstate );
31383152 assert (tstate -> datastack_chunk );
31393153 PyObject * * base = (PyObject * * )frame ;
31403154 if (base == & tstate -> datastack_chunk -> data [0 ]) {
@@ -3171,6 +3185,7 @@ _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame)
31713185int
31723186_PyThreadState_CheckConsistency (PyThreadState * tstate )
31733187{
3188+ ensure_tstate_is_valid (tstate );
31743189 assert (!_PyMem_IsPtrFreed (tstate ));
31753190 assert (!_PyMem_IsPtrFreed (tstate -> interp ));
31763191 return 1 ;
@@ -3189,13 +3204,15 @@ _PyThreadState_CheckConsistency(PyThreadState *tstate)
31893204int
31903205_PyThreadState_MustExit (PyThreadState * tstate )
31913206{
3207+ ensure_tstate_is_valid (tstate );
31923208 int state = _Py_atomic_load_int_relaxed (& tstate -> state );
31933209 return state == _Py_THREAD_SHUTTING_DOWN ;
31943210}
31953211
31963212void
31973213_PyThreadState_HangThread (PyThreadState * tstate )
31983214{
3215+ ensure_tstate_is_valid (tstate );
31993216 _PyThreadStateImpl * tstate_impl = (_PyThreadStateImpl * )tstate ;
32003217 decref_threadstate (tstate_impl );
32013218 PyThread_hang_thread ();
@@ -3209,6 +3226,7 @@ static void
32093226tstate_mimalloc_bind (PyThreadState * tstate )
32103227{
32113228#ifdef Py_GIL_DISABLED
3229+ ensure_tstate_is_valid (tstate );
32123230 struct _mimalloc_thread_state * mts = & ((_PyThreadStateImpl * )tstate )-> mimalloc ;
32133231
32143232 // Initialize the mimalloc thread state. This must be called from the
@@ -3262,6 +3280,7 @@ void
32623280_PyThreadState_ClearMimallocHeaps (PyThreadState * tstate )
32633281{
32643282#ifdef Py_GIL_DISABLED
3283+ ensure_tstate_is_valid (tstate );
32653284 if (!tstate -> _status .bound ) {
32663285 // The mimalloc heaps are only initialized when the thread is bound.
32673286 return ;
@@ -3490,7 +3509,15 @@ PyInterpreterView_FromMain(void)
34903509// thread state was attached.
34913510// To do this, we just use the memory address of a global variable and
34923511// cast it to a PyThreadState *.
3493- static const int NO_TSTATE_SENTINEL = 0 ;
3512+ static const PyThreadState _no_tstate_sentinel = {0 };
3513+ #define NO_TSTATE_SENTINEL ((PyThreadState *)&_no_tstate_sentinel)
3514+
3515+ static inline void
3516+ ensure_tstate_is_valid (PyThreadState * tstate )
3517+ {
3518+ assert (tstate != NULL );
3519+ assert (tstate != NO_TSTATE_SENTINEL );
3520+ }
34943521
34953522PyThreadState *
34963523PyThreadState_Ensure (PyInterpreterGuard * guard )
@@ -3502,7 +3529,7 @@ PyThreadState_Ensure(PyInterpreterGuard *guard)
35023529 if (attached_tstate != NULL && attached_tstate -> interp == interp ) {
35033530 /* Yay! We already have an attached thread state that matches. */
35043531 ++ attached_tstate -> ensure .counter ;
3505- return ( PyThreadState * ) & NO_TSTATE_SENTINEL ;
3532+ return NO_TSTATE_SENTINEL ;
35063533 }
35073534
35083535 PyThreadState * detached_gilstate = gilstate_get ();
@@ -3511,7 +3538,7 @@ PyThreadState_Ensure(PyInterpreterGuard *guard)
35113538 assert (attached_tstate == NULL );
35123539 ++ detached_gilstate -> ensure .counter ;
35133540 _PyThreadState_Attach (detached_gilstate );
3514- return ( PyThreadState * ) & NO_TSTATE_SENTINEL ;
3541+ return NO_TSTATE_SENTINEL ;
35153542 }
35163543
35173544 PyThreadState * fresh_tstate = _PyThreadState_NewBound (interp ,
@@ -3528,7 +3555,7 @@ PyThreadState_Ensure(PyInterpreterGuard *guard)
35283555 _PyThreadState_Attach (fresh_tstate );
35293556 }
35303557
3531- return ( PyThreadState * ) & NO_TSTATE_SENTINEL ;
3558+ return NO_TSTATE_SENTINEL ;
35323559}
35333560
35343561PyThreadState *
@@ -3547,7 +3574,7 @@ PyThreadState_EnsureFromView(PyInterpreterView *view)
35473574 }
35483575
35493576 PyThreadState * tstate = current_fast_get ();
3550- assert (tstate != NULL );
3577+ ensure_tstate_is_valid (tstate );
35513578
35523579 if (tstate -> ensure .owned_guard != NULL ) {
35533580 assert (tstate -> ensure .owned_guard -> interp == guard -> interp );
@@ -3575,7 +3602,7 @@ PyThreadState_Release(PyThreadState *old_tstate)
35753602 }
35763603
35773604 PyThreadState * to_restore ;
3578- if (old_tstate == ( PyThreadState * ) & NO_TSTATE_SENTINEL ) {
3605+ if (old_tstate == NO_TSTATE_SENTINEL ) {
35793606 to_restore = NULL ;
35803607 }
35813608 else {
0 commit comments