@@ -790,18 +790,15 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
790790 }
791791
792792 // Clear the current/main thread state last.
793- HEAD_LOCK (runtime );
794- PyThreadState * p = interp -> threads .head ;
795- HEAD_UNLOCK (runtime );
796- while (p != NULL ) {
793+ _Py_FOR_EACH_TSTATE_BEGIN (interp , p ) {
797794 // See https://github.com/python/cpython/issues/102126
798795 // Must be called without HEAD_LOCK held as it can deadlock
799796 // if any finalizer tries to acquire that lock.
797+ HEAD_UNLOCK (runtime );
800798 PyThreadState_Clear (p );
801799 HEAD_LOCK (runtime );
802- p = p -> next ;
803- HEAD_UNLOCK (runtime );
804800 }
801+ _Py_FOR_EACH_TSTATE_END (interp );
805802 if (tstate -> interp == interp ) {
806803 /* We fix tstate->_status below when we for sure aren't using it
807804 (e.g. no longer need the GIL). */
@@ -1801,10 +1798,9 @@ tstate_delete_common(PyThreadState *tstate, int release_gil)
18011798static void
18021799zapthreads (PyInterpreterState * interp )
18031800{
1804- PyThreadState * tstate ;
18051801 /* No need to lock the mutex here because this should only happen
18061802 when the threads are all really dead (XXX famous last words). */
1807- while (( tstate = interp -> threads . head ) != NULL ) {
1803+ _Py_FOR_EACH_TSTATE_UNLOCKED ( interp , tstate ) {
18081804 tstate_verify_not_active (tstate );
18091805 tstate_delete_common (tstate , 0 );
18101806 free_threadstate ((_PyThreadStateImpl * )tstate );
@@ -2161,7 +2157,7 @@ decrement_stoptheworld_countdown(struct _stoptheworld_state *stw)
21612157}
21622158
21632159#ifdef Py_GIL_DISABLED
2164- // Interpreter for _Py_FOR_EACH_THREAD (). For global stop-the-world events,
2160+ // Interpreter for _Py_FOR_EACH_STW_INTERP (). For global stop-the-world events,
21652161// we start with the first interpreter and then iterate over all interpreters.
21662162// For per-interpreter stop-the-world events, we only operate on the one
21672163// interpreter.
@@ -2176,10 +2172,9 @@ interp_for_stop_the_world(struct _stoptheworld_state *stw)
21762172// Loops over threads for a stop-the-world event.
21772173// For global: all threads in all interpreters
21782174// For per-interpreter: all threads in the interpreter
2179- #define _Py_FOR_EACH_THREAD (stw , i , t ) \
2180- for (i = interp_for_stop_the_world((stw)); \
2181- i != NULL; i = ((stw->is_global) ? i->next : NULL)) \
2182- for (t = i->threads.head; t; t = t->next)
2175+ #define _Py_FOR_EACH_STW_INTERP (stw , i ) \
2176+ for (PyInterpreterState *i = interp_for_stop_the_world((stw)); \
2177+ i != NULL; i = ((stw->is_global) ? i->next : NULL))
21832178
21842179
21852180// Try to transition threads atomically from the "detached" state to the
@@ -2188,19 +2183,19 @@ static bool
21882183park_detached_threads (struct _stoptheworld_state * stw )
21892184{
21902185 int num_parked = 0 ;
2191- PyInterpreterState * i ;
2192- PyThreadState * t ;
2193- _Py_FOR_EACH_THREAD (stw , i , t ) {
2194- int state = _Py_atomic_load_int_relaxed (& t -> state );
2195- if (state == _Py_THREAD_DETACHED ) {
2196- // Atomically transition to "suspended" if in "detached" state.
2197- if (_Py_atomic_compare_exchange_int (& t -> state ,
2198- & state , _Py_THREAD_SUSPENDED )) {
2199- num_parked ++ ;
2186+ _Py_FOR_EACH_STW_INTERP (stw , i ) {
2187+ _Py_FOR_EACH_TSTATE_UNLOCKED (i , t ) {
2188+ int state = _Py_atomic_load_int_relaxed (& t -> state );
2189+ if (state == _Py_THREAD_DETACHED ) {
2190+ // Atomically transition to "suspended" if in "detached" state.
2191+ if (_Py_atomic_compare_exchange_int (
2192+ & t -> state , & state , _Py_THREAD_SUSPENDED )) {
2193+ num_parked ++ ;
2194+ }
2195+ }
2196+ else if (state == _Py_THREAD_ATTACHED && t != stw -> requester ) {
2197+ _Py_set_eval_breaker_bit (t , _PY_EVAL_PLEASE_STOP_BIT );
22002198 }
2201- }
2202- else if (state == _Py_THREAD_ATTACHED && t != stw -> requester ) {
2203- _Py_set_eval_breaker_bit (t , _PY_EVAL_PLEASE_STOP_BIT );
22042199 }
22052200 }
22062201 stw -> thread_countdown -= num_parked ;
@@ -2227,12 +2222,12 @@ stop_the_world(struct _stoptheworld_state *stw)
22272222 stw -> stop_event = (PyEvent ){0 }; // zero-initialize (unset)
22282223 stw -> requester = _PyThreadState_GET (); // may be NULL
22292224
2230- PyInterpreterState * i ;
2231- PyThreadState * t ;
2232- _Py_FOR_EACH_THREAD ( stw , i , t ) {
2233- if ( t != stw -> requester ) {
2234- // Count all the other threads (we don't wait on ourself).
2235- stw -> thread_countdown ++ ;
2225+ _Py_FOR_EACH_STW_INTERP ( stw , i ) {
2226+ _Py_FOR_EACH_TSTATE_UNLOCKED ( i , t ) {
2227+ if ( t != stw -> requester ) {
2228+ // Count all the other threads (we don't wait on ourself).
2229+ stw -> thread_countdown ++ ;
2230+ }
22362231 }
22372232 }
22382233
@@ -2273,14 +2268,14 @@ start_the_world(struct _stoptheworld_state *stw)
22732268 stw -> requested = 0 ;
22742269 stw -> world_stopped = 0 ;
22752270 // Switch threads back to the detached state.
2276- PyInterpreterState * i ;
2277- PyThreadState * t ;
2278- _Py_FOR_EACH_THREAD ( stw , i , t ) {
2279- if ( t != stw -> requester ) {
2280- assert ( _Py_atomic_load_int_relaxed ( & t -> state ) ==
2281- _Py_THREAD_SUSPENDED );
2282- _Py_atomic_store_int (& t -> state , _Py_THREAD_DETACHED );
2283- _PyParkingLot_UnparkAll ( & t -> state );
2271+ _Py_FOR_EACH_STW_INTERP ( stw , i ) {
2272+ _Py_FOR_EACH_TSTATE_UNLOCKED ( i , t ) {
2273+ if ( t != stw -> requester ) {
2274+ assert ( _Py_atomic_load_int_relaxed ( & t -> state ) ==
2275+ _Py_THREAD_SUSPENDED );
2276+ _Py_atomic_store_int ( & t -> state , _Py_THREAD_DETACHED );
2277+ _PyParkingLot_UnparkAll (& t -> state );
2278+ }
22842279 }
22852280 }
22862281 stw -> requester = NULL ;
@@ -2344,7 +2339,6 @@ _PyEval_StartTheWorld(PyInterpreterState *interp)
23442339int
23452340PyThreadState_SetAsyncExc (unsigned long id , PyObject * exc )
23462341{
2347- _PyRuntimeState * runtime = & _PyRuntime ;
23482342 PyInterpreterState * interp = _PyInterpreterState_GET ();
23492343
23502344 /* Although the GIL is held, a few C API functions can be called
@@ -2353,12 +2347,16 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
23532347 * list of thread states we're traversing, so to prevent that we lock
23542348 * head_mutex for the duration.
23552349 */
2356- HEAD_LOCK (runtime );
2357- for (PyThreadState * tstate = interp -> threads .head ; tstate != NULL ; tstate = tstate -> next ) {
2358- if (tstate -> thread_id != id ) {
2359- continue ;
2350+ PyThreadState * tstate = NULL ;
2351+ _Py_FOR_EACH_TSTATE_BEGIN (interp , t ) {
2352+ if (t -> thread_id == id ) {
2353+ tstate = t ;
2354+ break ;
23602355 }
2356+ }
2357+ _Py_FOR_EACH_TSTATE_END (interp );
23612358
2359+ if (tstate != NULL ) {
23622360 /* Tricky: we need to decref the current value
23632361 * (if any) in tstate->async_exc, but that can in turn
23642362 * allow arbitrary Python code to run, including
@@ -2368,14 +2366,12 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
23682366 */
23692367 Py_XINCREF (exc );
23702368 PyObject * old_exc = _Py_atomic_exchange_ptr (& tstate -> async_exc , exc );
2371- HEAD_UNLOCK (runtime );
23722369
23732370 Py_XDECREF (old_exc );
23742371 _Py_set_eval_breaker_bit (tstate , _PY_ASYNC_EXCEPTION_BIT );
2375- return 1 ;
23762372 }
2377- HEAD_UNLOCK ( runtime );
2378- return 0 ;
2373+
2374+ return tstate != NULL ;
23792375}
23802376
23812377//---------------------------------
@@ -2515,8 +2511,7 @@ _PyThread_CurrentFrames(void)
25152511 HEAD_LOCK (runtime );
25162512 PyInterpreterState * i ;
25172513 for (i = runtime -> interpreters .head ; i != NULL ; i = i -> next ) {
2518- PyThreadState * t ;
2519- for (t = i -> threads .head ; t != NULL ; t = t -> next ) {
2514+ _Py_FOR_EACH_TSTATE_UNLOCKED (i , t ) {
25202515 _PyInterpreterFrame * frame = t -> current_frame ;
25212516 frame = _PyFrame_GetFirstComplete (frame );
25222517 if (frame == NULL ) {
@@ -2581,8 +2576,7 @@ _PyThread_CurrentExceptions(void)
25812576 HEAD_LOCK (runtime );
25822577 PyInterpreterState * i ;
25832578 for (i = runtime -> interpreters .head ; i != NULL ; i = i -> next ) {
2584- PyThreadState * t ;
2585- for (t = i -> threads .head ; t != NULL ; t = t -> next ) {
2579+ _Py_FOR_EACH_TSTATE_UNLOCKED (i , t ) {
25862580 _PyErr_StackItem * err_info = _PyErr_GetTopmostException (t );
25872581 if (err_info == NULL ) {
25882582 continue ;
0 commit comments