Skip to content

Commit 470298f

Browse files
committed
Update comments and _PyThreadState_Suspend.
_PyThreadState_Suspend now switches to "detached" if there is no active stop-the-world request.
1 parent 4ca1e31 commit 470298f

File tree

3 files changed

+22
-23
lines changed

3 files changed

+22
-23
lines changed

Include/internal/pycore_pystate.h

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@ extern "C" {
2020
// transitions between "attached" and "detached" on its own PyThreadState.
2121
//
2222
// The "suspended" state is used to implement stop-the-world pauses, such as
23-
// for cyclic garbage collection. It is only used in `--disable-gil` builds. It
24-
// is similar to the "detached" state, but only the thread performing a
25-
// stop-the-world pause may transition a thread from the "suspended" state back
26-
// to the "detached" state. A thread trying to "attach" from the "suspended"
27-
// state will block until it is transitioned back to "detached" when the
28-
// stop-the-world pause is complete.
23+
// for cyclic garbage collection. It is only used in `--disable-gil` builds.
24+
// The "suspended" state is similar to the "detached" state in that in both
25+
// states the thread is not allowed to call most Python APIs. However, unlike
26+
// the "detached" state, a thread may not transition itself out from the
27+
// "suspended" state. Only the thread performing a stop-the-world pause may
28+
// transition a thread from the "suspended" state back to the "detached" state.
2929
//
3030
// State transition diagram:
3131
//
3232
// (bound thread) (stop-the-world thread)
3333
// [attached] <-> [detached] <-> [suspended]
34-
// + ^
35-
// +--------------------------------------------------------+
34+
// | ^
35+
// +---------------------------->---------------------------+
3636
// (bound thread)
3737
//
38-
// See `_PyThreadState_Attach()`, `_PyThreadState_Detach()`, and
39-
// `_PyThreadState_Suspend()`.
38+
// The (bound thread) and (stop-the-world thread) labels indicate which thread
39+
// is allowed to perform the transition.
4040
#define _Py_THREAD_DETACHED 0
4141
#define _Py_THREAD_ATTACHED 1
4242
#define _Py_THREAD_SUSPENDED 2
@@ -153,10 +153,9 @@ extern void _PyThreadState_Detach(PyThreadState *tstate);
153153
// Detaches the current thread to the "suspended" state if a stop-the-world
154154
// pause is in progress.
155155
//
156-
// If there is no stop-the-world pause in progress, then this function is
157-
// a no-op. Returns one if the thread was switched to the "suspended" state and
158-
// zero otherwise.
159-
extern int _PyThreadState_Suspend(PyThreadState *tstate);
156+
// If there is no stop-the-world pause in progress, then the thread switches
157+
// to the "detached" state.
158+
extern void _PyThreadState_Suspend(PyThreadState *tstate);
160159

161160
// Perform a stop-the-world pause for all threads in the all interpreters.
162161
//

Python/ceval_gil.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -952,11 +952,10 @@ _Py_HandlePending(PyThreadState *tstate)
952952
/* Stop-the-world */
953953
if (_Py_eval_breaker_bit_is_set(interp, _PY_EVAL_PLEASE_STOP_BIT)) {
954954
_Py_set_eval_breaker_bit(interp, _PY_EVAL_PLEASE_STOP_BIT, 0);
955-
if (_PyThreadState_Suspend(tstate)) {
956-
/* The attach blocks until the stop-the-world event is complete. */
957-
_PyThreadState_Attach(tstate);
958-
}
959-
// else: stale stop-the-world event, ignore it!
955+
_PyThreadState_Suspend(tstate);
956+
957+
/* The attach blocks until the stop-the-world event is complete. */
958+
_PyThreadState_Attach(tstate);
960959
}
961960

962961
/* Pending signals */

Python/pystate.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,7 +1876,7 @@ _PyThreadState_Detach(PyThreadState *tstate)
18761876
detach_thread(tstate, _Py_THREAD_DETACHED);
18771877
}
18781878

1879-
int
1879+
void
18801880
_PyThreadState_Suspend(PyThreadState *tstate)
18811881
{
18821882
_PyRuntimeState *runtime = &_PyRuntime;
@@ -1894,8 +1894,10 @@ _PyThreadState_Suspend(PyThreadState *tstate)
18941894
HEAD_UNLOCK(runtime);
18951895

18961896
if (stw == NULL) {
1897-
// Don't suspend if we are not in a stop-the-world event.
1898-
return 0;
1897+
// Switch directly to "detached" if there is no active stop-the-world
1898+
// request.
1899+
detach_thread(tstate, _Py_THREAD_DETACHED);
1900+
return;
18991901
}
19001902

19011903
// Switch to "suspended" state.
@@ -1905,7 +1907,6 @@ _PyThreadState_Suspend(PyThreadState *tstate)
19051907
HEAD_LOCK(runtime);
19061908
decrement_stoptheworld_countdown(stw);
19071909
HEAD_UNLOCK(runtime);
1908-
return 1;
19091910
}
19101911

19111912
// Decrease stop-the-world counter of remaining number of threads that need to

0 commit comments

Comments
 (0)