@@ -790,18 +790,15 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
790
790
}
791
791
792
792
// 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 ) {
797
794
// See https://github.com/python/cpython/issues/102126
798
795
// Must be called without HEAD_LOCK held as it can deadlock
799
796
// if any finalizer tries to acquire that lock.
797
+ HEAD_UNLOCK (runtime );
800
798
PyThreadState_Clear (p );
801
799
HEAD_LOCK (runtime );
802
- p = p -> next ;
803
- HEAD_UNLOCK (runtime );
804
800
}
801
+ _Py_FOR_EACH_TSTATE_END (interp );
805
802
if (tstate -> interp == interp ) {
806
803
/* We fix tstate->_status below when we for sure aren't using it
807
804
(e.g. no longer need the GIL). */
@@ -1801,10 +1798,9 @@ tstate_delete_common(PyThreadState *tstate, int release_gil)
1801
1798
static void
1802
1799
zapthreads (PyInterpreterState * interp )
1803
1800
{
1804
- PyThreadState * tstate ;
1805
1801
/* No need to lock the mutex here because this should only happen
1806
1802
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 ) {
1808
1804
tstate_verify_not_active (tstate );
1809
1805
tstate_delete_common (tstate , 0 );
1810
1806
free_threadstate ((_PyThreadStateImpl * )tstate );
@@ -2161,7 +2157,7 @@ decrement_stoptheworld_countdown(struct _stoptheworld_state *stw)
2161
2157
}
2162
2158
2163
2159
#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,
2165
2161
// we start with the first interpreter and then iterate over all interpreters.
2166
2162
// For per-interpreter stop-the-world events, we only operate on the one
2167
2163
// interpreter.
@@ -2176,10 +2172,9 @@ interp_for_stop_the_world(struct _stoptheworld_state *stw)
2176
2172
// Loops over threads for a stop-the-world event.
2177
2173
// For global: all threads in all interpreters
2178
2174
// 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))
2183
2178
2184
2179
2185
2180
// Try to transition threads atomically from the "detached" state to the
@@ -2188,19 +2183,19 @@ static bool
2188
2183
park_detached_threads (struct _stoptheworld_state * stw )
2189
2184
{
2190
2185
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 );
2200
2198
}
2201
- }
2202
- else if (state == _Py_THREAD_ATTACHED && t != stw -> requester ) {
2203
- _Py_set_eval_breaker_bit (t , _PY_EVAL_PLEASE_STOP_BIT );
2204
2199
}
2205
2200
}
2206
2201
stw -> thread_countdown -= num_parked ;
@@ -2227,12 +2222,12 @@ stop_the_world(struct _stoptheworld_state *stw)
2227
2222
stw -> stop_event = (PyEvent ){0 }; // zero-initialize (unset)
2228
2223
stw -> requester = _PyThreadState_GET (); // may be NULL
2229
2224
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
+ }
2236
2231
}
2237
2232
}
2238
2233
@@ -2273,14 +2268,14 @@ start_the_world(struct _stoptheworld_state *stw)
2273
2268
stw -> requested = 0 ;
2274
2269
stw -> world_stopped = 0 ;
2275
2270
// 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
+ }
2284
2279
}
2285
2280
}
2286
2281
stw -> requester = NULL ;
@@ -2344,7 +2339,6 @@ _PyEval_StartTheWorld(PyInterpreterState *interp)
2344
2339
int
2345
2340
PyThreadState_SetAsyncExc (unsigned long id , PyObject * exc )
2346
2341
{
2347
- _PyRuntimeState * runtime = & _PyRuntime ;
2348
2342
PyInterpreterState * interp = _PyInterpreterState_GET ();
2349
2343
2350
2344
/* Although the GIL is held, a few C API functions can be called
@@ -2353,12 +2347,16 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
2353
2347
* list of thread states we're traversing, so to prevent that we lock
2354
2348
* head_mutex for the duration.
2355
2349
*/
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 ;
2360
2355
}
2356
+ }
2357
+ _Py_FOR_EACH_TSTATE_END (interp );
2361
2358
2359
+ if (tstate != NULL ) {
2362
2360
/* Tricky: we need to decref the current value
2363
2361
* (if any) in tstate->async_exc, but that can in turn
2364
2362
* allow arbitrary Python code to run, including
@@ -2368,14 +2366,12 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
2368
2366
*/
2369
2367
Py_XINCREF (exc );
2370
2368
PyObject * old_exc = _Py_atomic_exchange_ptr (& tstate -> async_exc , exc );
2371
- HEAD_UNLOCK (runtime );
2372
2369
2373
2370
Py_XDECREF (old_exc );
2374
2371
_Py_set_eval_breaker_bit (tstate , _PY_ASYNC_EXCEPTION_BIT );
2375
- return 1 ;
2376
2372
}
2377
- HEAD_UNLOCK ( runtime );
2378
- return 0 ;
2373
+
2374
+ return tstate != NULL ;
2379
2375
}
2380
2376
2381
2377
//---------------------------------
@@ -2515,8 +2511,7 @@ _PyThread_CurrentFrames(void)
2515
2511
HEAD_LOCK (runtime );
2516
2512
PyInterpreterState * i ;
2517
2513
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 ) {
2520
2515
_PyInterpreterFrame * frame = t -> current_frame ;
2521
2516
frame = _PyFrame_GetFirstComplete (frame );
2522
2517
if (frame == NULL ) {
@@ -2581,8 +2576,7 @@ _PyThread_CurrentExceptions(void)
2581
2576
HEAD_LOCK (runtime );
2582
2577
PyInterpreterState * i ;
2583
2578
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 ) {
2586
2580
_PyErr_StackItem * err_info = _PyErr_GetTopmostException (t );
2587
2581
if (err_info == NULL ) {
2588
2582
continue ;
0 commit comments