aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Include
diff options
context:
space:
mode:
authorNeil Schemenauer <nas-github@arctrix.com>2025-04-28 13:28:44 -0700
committerGitHub <noreply@github.com>2025-04-28 20:28:44 +0000
commite414a2d81c3e15553516979e146d9f258fb47b2e (patch)
treea3235722193c596e4188373416afb4412cdd6045 /Include
parent22f0730d40c9534672f745f35cf876ad63d450bb (diff)
downloadcpython-e414a2d81c3e15553516979e146d9f258fb47b2e.tar.gz
cpython-e414a2d81c3e15553516979e146d9f258fb47b2e.zip
gh-127266: avoid data races when updating type slots (gh-131174)
In the free-threaded build, avoid data races caused by updating type slots or type flags after the type was initially created. For those (typically rare) cases, use the stop-the-world mechanism. Remove the use of atomics when reading or writing type flags. The use of atomics is not sufficient to avoid races (since flags are sometimes read without a lock and without atomics) and are no longer required.
Diffstat (limited to 'Include')
-rw-r--r--Include/internal/pycore_interp_structs.h3
-rw-r--r--Include/internal/pycore_object.h2
-rw-r--r--Include/internal/pycore_typeobject.h1
-rw-r--r--Include/object.h12
-rw-r--r--Include/refcount.h3
5 files changed, 11 insertions, 10 deletions
diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h
index af6ee3ab489..f193fed1153 100644
--- a/Include/internal/pycore_interp_structs.h
+++ b/Include/internal/pycore_interp_structs.h
@@ -667,8 +667,11 @@ struct _Py_interp_cached_objects {
/* object.__reduce__ */
PyObject *objreduce;
+#ifndef Py_GIL_DISABLED
+ /* resolve_slotdups() */
PyObject *type_slots_pname;
pytype_slotdef *type_slots_ptrs[MAX_EQUIV];
+#endif
/* TypeVar and related types */
PyTypeObject *generic_type;
diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index b7e162c8abc..986bcc9fd08 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -313,7 +313,7 @@ extern int _PyDict_CheckConsistency(PyObject *mp, int check_content);
// Fast inlined version of PyType_HasFeature()
static inline int
_PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
- return ((FT_ATOMIC_LOAD_ULONG_RELAXED(type->tp_flags) & feature) != 0);
+ return ((type->tp_flags) & feature) != 0;
}
extern void _PyType_InitCache(PyInterpreterState *interp);
diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h
index 1a4f89fd244..0ee7d555c56 100644
--- a/Include/internal/pycore_typeobject.h
+++ b/Include/internal/pycore_typeobject.h
@@ -134,7 +134,6 @@ extern int _PyType_AddMethod(PyTypeObject *, PyMethodDef *);
extern void _PyType_SetFlagsRecursive(PyTypeObject *self, unsigned long mask,
unsigned long flags);
-extern unsigned int _PyType_GetVersionForCurrentState(PyTypeObject *tp);
PyAPI_FUNC(void) _PyType_SetVersion(PyTypeObject *tp, unsigned int version);
PyTypeObject *_PyType_LookupByVersion(unsigned int version);
diff --git a/Include/object.h b/Include/object.h
index 8cc83abb857..994cac1ad17 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -620,6 +620,12 @@ given type object has a specified feature.
#define Py_TPFLAGS_HAVE_FINALIZE (1UL << 0)
#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18)
+// Flag values for ob_flags (16 bits available, if SIZEOF_VOID_P > 4).
+#define _Py_IMMORTAL_FLAGS (1 << 0)
+#define _Py_STATICALLY_ALLOCATED_FLAG (1 << 2)
+#if defined(Py_GIL_DISABLED) && defined(Py_DEBUG)
+#define _Py_TYPE_REVEALED_FLAG (1 << 3)
+#endif
#define Py_CONSTANT_NONE 0
#define Py_CONSTANT_FALSE 1
@@ -776,11 +782,7 @@ PyType_HasFeature(PyTypeObject *type, unsigned long feature)
// PyTypeObject is opaque in the limited C API
flags = PyType_GetFlags(type);
#else
-# ifdef Py_GIL_DISABLED
- flags = _Py_atomic_load_ulong_relaxed(&type->tp_flags);
-# else
- flags = type->tp_flags;
-# endif
+ flags = type->tp_flags;
#endif
return ((flags & feature) != 0);
}
diff --git a/Include/refcount.h b/Include/refcount.h
index 177bbdaf0c5..ebd1dba6d15 100644
--- a/Include/refcount.h
+++ b/Include/refcount.h
@@ -19,9 +19,6 @@ immortal. The latter should be the only instances that require
cleanup during runtime finalization.
*/
-#define _Py_STATICALLY_ALLOCATED_FLAG 4
-#define _Py_IMMORTAL_FLAGS 1
-
#if SIZEOF_VOID_P > 4
/*
In 64+ bit systems, any object whose 32 bit reference count is >= 2**31