gh-120321: Make gi_frame_state transitions atomic in FT build (gh-142599)

This makes generator frame state transitions atomic in the free
threading build, which avoids segfaults when trying to execute
a generator from multiple threads concurrently.

There are still a few operations that aren't thread-safe and may crash
if performed concurrently on the same generator/coroutine:

 * Accessing gi_yieldfrom/cr_await/ag_await
 * Accessing gi_frame/cr_frame/ag_frame
 * Async generator operations
This commit is contained in:
Sam Gross 2025-12-19 14:10:37 -05:00 committed by GitHub
parent e2a7db7175
commit 08bc03ff2a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 1124 additions and 883 deletions

View file

@ -523,6 +523,9 @@ _Py_atomic_store_uintptr_release(uintptr_t *obj, uintptr_t value);
static inline void
_Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value);
static inline void
_Py_atomic_store_int8_release(int8_t *obj, int8_t value);
static inline void
_Py_atomic_store_int_release(int *obj, int value);

View file

@ -572,6 +572,10 @@ static inline void
_Py_atomic_store_int_release(int *obj, int value)
{ __atomic_store_n(obj, value, __ATOMIC_RELEASE); }
static inline void
_Py_atomic_store_int8_release(int8_t *obj, int8_t value)
{ __atomic_store_n(obj, value, __ATOMIC_RELEASE); }
static inline void
_Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value)
{ __atomic_store_n(obj, value, __ATOMIC_RELEASE); }

View file

@ -1066,6 +1066,19 @@ _Py_atomic_store_int_release(int *obj, int value)
#endif
}
static inline void
_Py_atomic_store_int8_release(int8_t *obj, int8_t value)
{
#if defined(_M_X64) || defined(_M_IX86)
*(int8_t volatile *)obj = value;
#elif defined(_M_ARM64)
_Py_atomic_ASSERT_ARG_TYPE(unsigned __int8);
__stlr8((unsigned __int8 volatile *)obj, (unsigned __int8)value);
#else
# error "no implementation of _Py_atomic_store_int8_release"
#endif
}
static inline void
_Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value)
{

View file

@ -1023,6 +1023,14 @@ _Py_atomic_store_int_release(int *obj, int value)
memory_order_release);
}
static inline void
_Py_atomic_store_int8_release(int8_t *obj, int8_t value)
{
_Py_USING_STD;
atomic_store_explicit((_Atomic(int8_t)*)obj, value,
memory_order_release);
}
static inline void
_Py_atomic_store_uint_release(unsigned int *obj, unsigned int value)
{