mirror of
https://github.com/python/cpython.git
synced 2026-02-06 18:01:17 +00:00
gh-120321: Make gi_yieldfrom thread-safe in free-threading build (#144292)
Add a FRAME_SUSPENDED_YIELD_FROM_LOCKED state that acts as a brief lock, preventing other threads from transitioning the frame state while gen_getyieldfrom reads the yield-from object off the stack.
This commit is contained in:
parent
a7048327ed
commit
a01694dacd
9 changed files with 103 additions and 19 deletions
|
|
@ -3391,7 +3391,9 @@ _PyEval_GetAwaitable(PyObject *iterable, int oparg)
|
|||
else if (PyCoro_CheckExact(iter)) {
|
||||
PyCoroObject *coro = (PyCoroObject *)iter;
|
||||
int8_t frame_state = FT_ATOMIC_LOAD_INT8_RELAXED(coro->cr_frame_state);
|
||||
if (frame_state == FRAME_SUSPENDED_YIELD_FROM) {
|
||||
if (frame_state == FRAME_SUSPENDED_YIELD_FROM ||
|
||||
frame_state == FRAME_SUSPENDED_YIELD_FROM_LOCKED)
|
||||
{
|
||||
/* `iter` is a coroutine object that is being awaited. */
|
||||
Py_CLEAR(iter);
|
||||
_PyErr_SetString(PyThreadState_GET(), PyExc_RuntimeError,
|
||||
|
|
|
|||
|
|
@ -522,19 +522,22 @@ gen_try_set_executing(PyGenObject *gen)
|
|||
#ifdef Py_GIL_DISABLED
|
||||
if (!_PyObject_IsUniquelyReferenced((PyObject *)gen)) {
|
||||
int8_t frame_state = _Py_atomic_load_int8_relaxed(&gen->gi_frame_state);
|
||||
while (frame_state < FRAME_EXECUTING) {
|
||||
while (frame_state < FRAME_SUSPENDED_YIELD_FROM_LOCKED) {
|
||||
if (_Py_atomic_compare_exchange_int8(&gen->gi_frame_state,
|
||||
&frame_state,
|
||||
FRAME_EXECUTING)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// NB: We return false for FRAME_SUSPENDED_YIELD_FROM_LOCKED as well.
|
||||
// That case is rare enough that we can just handle it in the deopt.
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
// Use faster non-atomic modifications in the GIL-enabled build and when
|
||||
// the object is uniquely referenced in the free-threaded build.
|
||||
if (gen->gi_frame_state < FRAME_EXECUTING) {
|
||||
assert(gen->gi_frame_state != FRAME_SUSPENDED_YIELD_FROM_LOCKED);
|
||||
gen->gi_frame_state = FRAME_EXECUTING;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ struct mutex_entry {
|
|||
int handed_off;
|
||||
};
|
||||
|
||||
static void
|
||||
void
|
||||
_Py_yield(void)
|
||||
{
|
||||
#ifdef MS_WINDOWS
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue