@@ -1564,7 +1564,7 @@ tstate_delete_common(PyThreadState *tstate)
15641564 if (tstate -> next ) {
15651565 tstate -> next -> prev = tstate -> prev ;
15661566 }
1567- if (tstate -> state != _Py_THREAD_GC ) {
1567+ if (tstate -> state != _Py_THREAD_SUSPENDED ) {
15681568 // Any ongoing stop-the-world request should not wait for us because
15691569 // our thread is getting deleted.
15701570 if (interp -> stoptheworld .requested ) {
@@ -1804,9 +1804,9 @@ static void
18041804tstate_wait_attach (PyThreadState * tstate )
18051805{
18061806 do {
1807- int expected = _Py_THREAD_GC ;
1807+ int expected = _Py_THREAD_SUSPENDED ;
18081808
1809- // Wait until we're switched out of GC to DETACHED.
1809+ // Wait until we're switched out of SUSPENDED to DETACHED.
18101810 _PyParkingLot_Park (& tstate -> state , & expected , sizeof (tstate -> state ),
18111811 /*timeout=*/ -1 , NULL , /*detach=*/ 0 );
18121812
@@ -1870,19 +1870,8 @@ _PyThreadState_Detach(PyThreadState *tstate)
18701870 detach_thread (tstate , _Py_THREAD_DETACHED );
18711871}
18721872
1873- // Decrease stop-the-world counter of remaining number of threads that need to
1874- // pause. If we are the final thread to pause, notify the requesting thread.
1875- static void
1876- decrement_stoptheworld_countdown (struct _stoptheworld_state * stw )
1877- {
1878- assert (stw -> thread_countdown > 0 );
1879- if (-- stw -> thread_countdown == 0 ) {
1880- _PyEvent_Notify (& stw -> stop_event );
1881- }
1882- }
1883-
1884- void
1885- _PyThreadState_Park (PyThreadState * tstate )
1873+ int
1874+ _PyThreadState_Suspend (PyThreadState * tstate )
18861875{
18871876 _PyRuntimeState * runtime = & _PyRuntime ;
18881877
@@ -1899,25 +1888,30 @@ _PyThreadState_Park(PyThreadState *tstate)
18991888 HEAD_UNLOCK (runtime );
19001889
19011890 if (stw == NULL ) {
1902- // We might be processing a stale EVAL_PLEASE_STOP, in which
1903- // case there is nothing to do. This can happen if a thread
1904- // asks us to stop for a previous GC at the same time we detach.
1905- return ;
1891+ // Don't suspend if we are not in a stop-the-world event.
1892+ return 0 ;
19061893 }
19071894
1908- // Switch to GC state.
1909- detach_thread (tstate , _Py_THREAD_GC );
1895+ // Switch to "suspended" state.
1896+ detach_thread (tstate , _Py_THREAD_SUSPENDED );
19101897
19111898 // Decrease the count of remaining threads needing to park.
19121899 HEAD_LOCK (runtime );
19131900 decrement_stoptheworld_countdown (stw );
19141901 HEAD_UNLOCK (runtime );
1915-
1916- // Wait until we are switched back to DETACHED and then re-attach. After
1917- // this we will be in the ATTACHED state, the same as before.
1918- tstate_wait_attach (tstate );
1902+ return 1 ;
19191903}
19201904
1905+ // Decrease stop-the-world counter of remaining number of threads that need to
1906+ // pause. If we are the final thread to pause, notify the requesting thread.
1907+ static void
1908+ decrement_stoptheworld_countdown (struct _stoptheworld_state * stw )
1909+ {
1910+ assert (stw -> thread_countdown > 0 );
1911+ if (-- stw -> thread_countdown == 0 ) {
1912+ _PyEvent_Notify (& stw -> stop_event );
1913+ }
1914+ }
19211915
19221916#ifdef Py_GIL_DISABLED
19231917// Interpreter for _Py_FOR_EACH_THREAD(). For global stop-the-world events,
@@ -1935,10 +1929,10 @@ interp_for_stop_the_world(struct _stoptheworld_state *stw)
19351929// Loops over threads for a stop-the-world event.
19361930// For global: all threads in all interpreters
19371931// For per-interpreter: all threads in the interpreter
1938- #define _Py_FOR_EACH_THREAD (stw ) \
1939- for (PyInterpreterState * i = interp_for_stop_the_world((stw)); \
1932+ #define _Py_FOR_EACH_THREAD (stw , i , t ) \
1933+ for (i = interp_for_stop_the_world((stw)); \
19401934 i != NULL; i = ((stw->is_global) ? i->next : NULL)) \
1941- for (PyThreadState * t = i->threads.head; t; t = t->next)
1935+ for (t = i->threads.head; t; t = t->next)
19421936
19431937
19441938// Try to transition threads atomically from the "detached" state to the
@@ -1947,12 +1941,14 @@ static bool
19471941park_detached_threads (struct _stoptheworld_state * stw )
19481942{
19491943 int num_parked = 0 ;
1950- _Py_FOR_EACH_THREAD (stw ) {
1944+ PyInterpreterState * i ;
1945+ PyThreadState * t ;
1946+ _Py_FOR_EACH_THREAD (stw , i , t ) {
19511947 int state = _Py_atomic_load_int_relaxed (& t -> state );
19521948 if (state == _Py_THREAD_DETACHED ) {
1953- // Atomically transition to _Py_THREAD_GC if in detached state.
1949+ // Atomically transition to "suspended" if in " detached" state.
19541950 if (_Py_atomic_compare_exchange_int (& t -> state ,
1955- & state , _Py_THREAD_GC )) {
1951+ & state , _Py_THREAD_SUSPENDED )) {
19561952 num_parked ++ ;
19571953 }
19581954 }
@@ -1982,9 +1978,12 @@ stop_the_world(struct _stoptheworld_state *stw)
19821978 HEAD_LOCK (runtime );
19831979 stw -> requested = 1 ;
19841980 stw -> thread_countdown = 0 ;
1981+ stw -> stop_event = (PyEvent ){0 }; // zero-initialize (unset)
19851982 stw -> requester = _PyThreadState_GET (); // may be NULL
19861983
1987- _Py_FOR_EACH_THREAD (stw ) {
1984+ PyInterpreterState * i ;
1985+ PyThreadState * t ;
1986+ _Py_FOR_EACH_THREAD (stw , i , t ) {
19881987 if (t != stw -> requester ) {
19891988 // Count all the other threads (we don't wait on ourself).
19901989 stw -> thread_countdown ++ ;
@@ -2006,10 +2005,9 @@ stop_the_world(struct _stoptheworld_state *stw)
20062005 break ;
20072006 }
20082007
2009- int64_t wait_ns = 1000 * 1000 ; // 1ms
2008+ _PyTime_t wait_ns = 1000 * 1000 ; // 1ms (arbitrary, may need tuning)
20102009 if (PyEvent_WaitTimed (& stw -> stop_event , wait_ns )) {
20112010 assert (stw -> thread_countdown == 0 );
2012- stw -> stop_event = (PyEvent ){0 };
20132011 break ;
20142012 }
20152013
@@ -2029,12 +2027,12 @@ start_the_world(struct _stoptheworld_state *stw)
20292027 stw -> world_stopped = 0 ;
20302028 stw -> requester = NULL ;
20312029 // Switch threads back to the detached state.
2032- _Py_FOR_EACH_THREAD ( stw ) {
2033- int state = _Py_atomic_load_int_relaxed ( & t -> state ) ;
2034- if ( state == _Py_THREAD_GC &&
2035- _Py_atomic_compare_exchange_int ( & t -> state ,
2036- & state ,
2037- _Py_THREAD_DETACHED )) {
2030+ PyInterpreterState * i ;
2031+ PyThreadState * t ;
2032+ _Py_FOR_EACH_THREAD ( stw , i , t ) {
2033+ if ( t != stw -> requester ) {
2034+ assert ( t -> state == _Py_THREAD_SUSPENDED );
2035+ _Py_atomic_store_int ( & t -> state , _Py_THREAD_DETACHED );
20382036 _PyParkingLot_UnparkAll (& t -> state );
20392037 }
20402038 }
0 commit comments