Skip to content

Commit 455b26b

Browse files
committed
Move FRAME_SUSPENDED_YIELD_FROM_LOCKED logic into _Py_GEN_TRY_SET_FRAME_STATE
1 parent f2e445e commit 455b26b

File tree

1 file changed

+17
-24
lines changed

1 file changed

+17
-24
lines changed

Objects/genobject.c

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,25 @@ static PyObject* async_gen_athrow_new(PyAsyncGenObject *, PyObject *);
3838
_Py_CAST(PyAsyncGenObject*, (op))
3939

4040
#ifdef Py_GIL_DISABLED
41+
static bool
42+
gen_try_set_frame_state(PyGenObject *gen, int8_t *expected, int8_t state)
43+
{
44+
if (*expected == FRAME_SUSPENDED_YIELD_FROM_LOCKED) {
45+
// Wait for the in-progress gi_yieldfrom read to complete
46+
_Py_yield();
47+
*expected = _Py_atomic_load_int8_relaxed(&gen->gi_frame_state);
48+
return false;
49+
}
50+
return _Py_atomic_compare_exchange_int8(&gen->gi_frame_state, expected, state);
51+
}
52+
4153
# define _Py_GEN_TRY_SET_FRAME_STATE(gen, expected, state) \
42-
_Py_atomic_compare_exchange_int8(&(gen)->gi_frame_state, &expected, (state))
54+
gen_try_set_frame_state((gen), &(expected), (state))
4355
#else
4456
# define _Py_GEN_TRY_SET_FRAME_STATE(gen, expected, state) \
4557
((gen)->gi_frame_state = (state), true)
4658
#endif
4759

48-
// Wait for any in-progress gi_yieldfrom read to complete.
49-
static inline void
50-
gen_yield_from_lock_wait(PyGenObject *gen, int8_t *frame_state)
51-
{
52-
#ifdef Py_GIL_DISABLED
53-
while (*frame_state == FRAME_SUSPENDED_YIELD_FROM_LOCKED) {
54-
_Py_yield();
55-
*frame_state = _Py_atomic_load_int8_relaxed(&gen->gi_frame_state);
56-
}
57-
#endif
58-
}
59-
6060

6161
static const char *NON_INIT_CORO_MSG = "can't send non-None value to a "
6262
"just-started coroutine";
@@ -331,8 +331,6 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, PyObject **presult)
331331
*presult = NULL;
332332
int8_t frame_state = FT_ATOMIC_LOAD_INT8_RELAXED(gen->gi_frame_state);
333333
do {
334-
gen_yield_from_lock_wait(gen, &frame_state);
335-
336334
if (frame_state == FRAME_CREATED && arg && arg != Py_None) {
337335
const char *msg = "can't send non-None value to a "
338336
"just-started generator";
@@ -467,8 +465,6 @@ gen_close(PyObject *self, PyObject *args)
467465

468466
int8_t frame_state = FT_ATOMIC_LOAD_INT8_RELAXED(gen->gi_frame_state);
469467
do {
470-
gen_yield_from_lock_wait(gen, &frame_state);
471-
472468
if (frame_state == FRAME_CREATED) {
473469
// && (1) to avoid -Wunreachable-code warning on Clang
474470
if (!_Py_GEN_TRY_SET_FRAME_STATE(gen, frame_state, FRAME_CLEARED) && (1)) {
@@ -487,9 +483,7 @@ gen_close(PyObject *self, PyObject *args)
487483
return NULL;
488484
}
489485

490-
assert(frame_state == FRAME_SUSPENDED_YIELD_FROM ||
491-
frame_state == FRAME_SUSPENDED);
492-
486+
assert(FRAME_STATE_SUSPENDED(frame_state));
493487
} while (!_Py_GEN_TRY_SET_FRAME_STATE(gen, frame_state, FRAME_EXECUTING));
494488

495489
int err = 0;
@@ -631,8 +625,6 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
631625
{
632626
int8_t frame_state = FT_ATOMIC_LOAD_INT8_RELAXED(gen->gi_frame_state);
633627
do {
634-
gen_yield_from_lock_wait(gen, &frame_state);
635-
636628
if (frame_state == FRAME_EXECUTING) {
637629
gen_raise_already_executing_error(gen);
638630
return NULL;
@@ -898,8 +890,9 @@ gen_getyieldfrom(PyObject *self, void *Py_UNUSED(ignored))
898890
#ifdef Py_GIL_DISABLED
899891
int8_t frame_state = _Py_atomic_load_int8_relaxed(&gen->gi_frame_state);
900892
do {
901-
gen_yield_from_lock_wait(gen, &frame_state);
902-
if (frame_state != FRAME_SUSPENDED_YIELD_FROM) {
893+
if (frame_state != FRAME_SUSPENDED_YIELD_FROM &&
894+
frame_state != FRAME_SUSPENDED_YIELD_FROM_LOCKED)
895+
{
903896
Py_RETURN_NONE;
904897
}
905898
} while (!_Py_GEN_TRY_SET_FRAME_STATE(gen, frame_state, FRAME_SUSPENDED_YIELD_FROM_LOCKED));

0 commit comments

Comments
 (0)