@@ -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
6161static 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