@@ -37,7 +37,15 @@ static inline PyObject* _Py_FROM_GC(PyGC_Head *gc) {
3737}
3838
3939
40- /* Bit flags for ob_gc_bits (in Py_GIL_DISABLED builds) */
40+ /* Bit flags for ob_gc_bits (in Py_GIL_DISABLED builds)
41+ *
42+ * Setting the bits requires a relaxed store. The per-object lock must also be
43+ * held, except when the object is only visible to a single thread (e.g. during
44+ * object initialization or destruction).
45+ *
46+ * Reading the bits requires using a relaxed load, but does not require holding
47+ * the per-object lock.
48+ */
4149#ifdef Py_GIL_DISABLED
4250# define _PyGC_BITS_TRACKED (1) // Tracked by the GC
4351# define _PyGC_BITS_FINALIZED (2) // tp_finalize was called
@@ -48,10 +56,34 @@ static inline PyObject* _Py_FROM_GC(PyGC_Head *gc) {
4856# define _PyGC_BITS_DEFERRED (64) // Use deferred reference counting
4957#endif
5058
59+ #ifdef Py_GIL_DISABLED
60+
61+ static inline void
62+ _PyObject_SET_GC_BITS (PyObject * op , uint8_t new_bits )
63+ {
64+ uint8_t bits = _Py_atomic_load_uint8_relaxed (& op -> ob_gc_bits );
65+ _Py_atomic_store_uint8_relaxed (& op -> ob_gc_bits , bits | new_bits );
66+ }
67+
68+ static inline int
69+ _PyObject_HAS_GC_BITS (PyObject * op , uint8_t bits )
70+ {
71+ return (_Py_atomic_load_uint8_relaxed (& op -> ob_gc_bits ) & bits ) != 0 ;
72+ }
73+
74+ static inline void
75+ _PyObject_CLEAR_GC_BITS (PyObject * op , uint8_t bits_to_clear )
76+ {
77+ uint8_t bits = _Py_atomic_load_uint8_relaxed (& op -> ob_gc_bits );
78+ _Py_atomic_store_uint8_relaxed (& op -> ob_gc_bits , bits & ~bits_to_clear );
79+ }
80+
81+ #endif
82+
5183/* True if the object is currently tracked by the GC. */
5284static inline int _PyObject_GC_IS_TRACKED (PyObject * op ) {
5385#ifdef Py_GIL_DISABLED
54- return (op -> ob_gc_bits & _PyGC_BITS_TRACKED ) != 0 ;
86+ return _PyObject_HAS_GC_BITS (op , _PyGC_BITS_TRACKED );
5587#else
5688 PyGC_Head * gc = _Py_AS_GC (op );
5789 return (gc -> _gc_next != 0 );
@@ -80,12 +112,12 @@ static inline int _PyObject_GC_MAY_BE_TRACKED(PyObject *obj) {
80112 * for calling _PyMem_FreeDelayed on the referenced
81113 * memory. */
82114static inline int _PyObject_GC_IS_SHARED (PyObject * op ) {
83- return (op -> ob_gc_bits & _PyGC_BITS_SHARED ) != 0 ;
115+ return _PyObject_HAS_GC_BITS (op , _PyGC_BITS_SHARED );
84116}
85117#define _PyObject_GC_IS_SHARED (op ) _PyObject_GC_IS_SHARED(_Py_CAST(PyObject*, op))
86118
87119static inline void _PyObject_GC_SET_SHARED (PyObject * op ) {
88- op -> ob_gc_bits |= _PyGC_BITS_SHARED ;
120+ _PyObject_SET_GC_BITS ( op , _PyGC_BITS_SHARED ) ;
89121}
90122#define _PyObject_GC_SET_SHARED (op ) _PyObject_GC_SET_SHARED(_Py_CAST(PyObject*, op))
91123
@@ -95,13 +127,13 @@ static inline void _PyObject_GC_SET_SHARED(PyObject *op) {
95127 * Objects with this bit that are GC objects will automatically
96128 * delay-freed by PyObject_GC_Del. */
97129static inline int _PyObject_GC_IS_SHARED_INLINE (PyObject * op ) {
98- return (op -> ob_gc_bits & _PyGC_BITS_SHARED_INLINE ) != 0 ;
130+ return _PyObject_HAS_GC_BITS (op , _PyGC_BITS_SHARED_INLINE );
99131}
100132#define _PyObject_GC_IS_SHARED_INLINE (op ) \
101133 _PyObject_GC_IS_SHARED_INLINE(_Py_CAST(PyObject*, op))
102134
103135static inline void _PyObject_GC_SET_SHARED_INLINE (PyObject * op ) {
104- op -> ob_gc_bits |= _PyGC_BITS_SHARED_INLINE ;
136+ _PyObject_SET_GC_BITS ( op , _PyGC_BITS_SHARED_INLINE ) ;
105137}
106138#define _PyObject_GC_SET_SHARED_INLINE (op ) \
107139 _PyObject_GC_SET_SHARED_INLINE(_Py_CAST(PyObject*, op))
@@ -178,23 +210,23 @@ static inline void _PyGCHead_SET_PREV(PyGC_Head *gc, PyGC_Head *prev) {
178210
179211static inline int _PyGC_FINALIZED (PyObject * op ) {
180212#ifdef Py_GIL_DISABLED
181- return (op -> ob_gc_bits & _PyGC_BITS_FINALIZED ) != 0 ;
213+ return _PyObject_HAS_GC_BITS (op , _PyGC_BITS_FINALIZED );
182214#else
183215 PyGC_Head * gc = _Py_AS_GC (op );
184216 return ((gc -> _gc_prev & _PyGC_PREV_MASK_FINALIZED ) != 0 );
185217#endif
186218}
187219static inline void _PyGC_SET_FINALIZED (PyObject * op ) {
188220#ifdef Py_GIL_DISABLED
189- op -> ob_gc_bits |= _PyGC_BITS_FINALIZED ;
221+ _PyObject_SET_GC_BITS ( op , _PyGC_BITS_FINALIZED ) ;
190222#else
191223 PyGC_Head * gc = _Py_AS_GC (op );
192224 gc -> _gc_prev |= _PyGC_PREV_MASK_FINALIZED ;
193225#endif
194226}
195227static inline void _PyGC_CLEAR_FINALIZED (PyObject * op ) {
196228#ifdef Py_GIL_DISABLED
197- op -> ob_gc_bits &= ~ _PyGC_BITS_FINALIZED ;
229+ _PyObject_CLEAR_GC_BITS ( op , _PyGC_BITS_FINALIZED ) ;
198230#else
199231 PyGC_Head * gc = _Py_AS_GC (op );
200232 gc -> _gc_prev &= ~_PyGC_PREV_MASK_FINALIZED ;
0 commit comments