|
10 | 10 | #include "pycore_gc.h" // _PyGC_CLEAR_FINALIZED() |
11 | 11 | #include "pycore_genobject.h" // _PyGen_SetStopIterationValue() |
12 | 12 | #include "pycore_interpframe.h" // _PyFrame_GetCode() |
| 13 | +#include "pycore_lock.h" // _Py_yield() |
13 | 14 | #include "pycore_modsupport.h" // _PyArg_CheckPositional() |
14 | 15 | #include "pycore_object.h" // _PyObject_GC_UNTRACK() |
15 | 16 | #include "pycore_opcode_utils.h" // RESUME_AFTER_YIELD_FROM |
@@ -37,8 +38,20 @@ static PyObject* async_gen_athrow_new(PyAsyncGenObject *, PyObject *); |
37 | 38 | _Py_CAST(PyAsyncGenObject*, (op)) |
38 | 39 |
|
39 | 40 | #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 | + |
40 | 53 | # define _Py_GEN_TRY_SET_FRAME_STATE(gen, expected, state) \ |
41 | | - _Py_atomic_compare_exchange_int8(&(gen)->gi_frame_state, &expected, (state)) |
| 54 | + gen_try_set_frame_state((gen), &(expected), (state)) |
42 | 55 | #else |
43 | 56 | # define _Py_GEN_TRY_SET_FRAME_STATE(gen, expected, state) \ |
44 | 57 | ((gen)->gi_frame_state = (state), true) |
@@ -470,9 +483,7 @@ gen_close(PyObject *self, PyObject *args) |
470 | 483 | return NULL; |
471 | 484 | } |
472 | 485 |
|
473 | | - assert(frame_state == FRAME_SUSPENDED_YIELD_FROM || |
474 | | - frame_state == FRAME_SUSPENDED); |
475 | | - |
| 486 | + assert(FRAME_STATE_SUSPENDED(frame_state)); |
476 | 487 | } while (!_Py_GEN_TRY_SET_FRAME_STATE(gen, frame_state, FRAME_EXECUTING)); |
477 | 488 |
|
478 | 489 | int err = 0; |
@@ -876,12 +887,26 @@ static PyObject * |
876 | 887 | gen_getyieldfrom(PyObject *self, void *Py_UNUSED(ignored)) |
877 | 888 | { |
878 | 889 | PyGenObject *gen = _PyGen_CAST(self); |
879 | | - int8_t frame_state = FT_ATOMIC_LOAD_INT8_RELAXED(gen->gi_frame_state); |
| 890 | +#ifdef Py_GIL_DISABLED |
| 891 | + int8_t frame_state = _Py_atomic_load_int8_relaxed(&gen->gi_frame_state); |
| 892 | + do { |
| 893 | + if (frame_state != FRAME_SUSPENDED_YIELD_FROM && |
| 894 | + frame_state != FRAME_SUSPENDED_YIELD_FROM_LOCKED) |
| 895 | + { |
| 896 | + Py_RETURN_NONE; |
| 897 | + } |
| 898 | + } while (!_Py_GEN_TRY_SET_FRAME_STATE(gen, frame_state, FRAME_SUSPENDED_YIELD_FROM_LOCKED)); |
| 899 | + |
| 900 | + PyObject *result = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe)); |
| 901 | + _Py_atomic_store_int8_release(&gen->gi_frame_state, FRAME_SUSPENDED_YIELD_FROM); |
| 902 | + return result; |
| 903 | +#else |
| 904 | + int8_t frame_state = gen->gi_frame_state; |
880 | 905 | if (frame_state != FRAME_SUSPENDED_YIELD_FROM) { |
881 | 906 | Py_RETURN_NONE; |
882 | 907 | } |
883 | | - // TODO: still not thread-safe with free threading |
884 | 908 | return PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe)); |
| 909 | +#endif |
885 | 910 | } |
886 | 911 |
|
887 | 912 |
|
|
0 commit comments