gh-128759: Fix accesses to tp_version_tag. (GH-129750)

We should use a relaxed atomic load in the free threading build in
`PyType_Modified()` because that's called without the type lock held.
It's not necessary to use atomics in `type_modified_unlocked()`.

We should also use `FT_ATOMIC_STORE_UINT_RELAXED()` instead of the
`UINT32` variant because `tp_version_tag` is declared as `unsigned int`.
This commit is contained in:
Sam Gross 2025-02-12 09:34:40 -05:00 committed by GitHub
parent 3cf68cdd3e
commit 57f45ee2d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1010,7 +1010,7 @@ set_version_unlocked(PyTypeObject *tp, unsigned int version)
_Py_atomic_add_uint16(&tp->tp_versions_used, 1);
}
#endif
FT_ATOMIC_STORE_UINT32_RELAXED(tp->tp_version_tag, version);
FT_ATOMIC_STORE_UINT_RELAXED(tp->tp_version_tag, version);
#ifndef Py_GIL_DISABLED
if (version != 0) {
PyTypeObject **slot =
@ -1039,7 +1039,8 @@ type_modified_unlocked(PyTypeObject *type)
We don't assign new version tags eagerly, but only as
needed.
*/
if (FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag) == 0) {
ASSERT_TYPE_LOCK_HELD();
if (type->tp_version_tag == 0) {
return;
}
// Cannot modify static builtin types.
@ -1094,7 +1095,7 @@ void
PyType_Modified(PyTypeObject *type)
{
// Quick check without the lock held
if (type->tp_version_tag == 0) {
if (FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag) == 0) {
return;
}