@@ -54,7 +54,6 @@ class object "PyObject *" "&PyBaseObject_Type"
5454 PyUnicode_CheckExact(name) && \
5555 (PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE)
5656
57- #define NEXT_GLOBAL_VERSION_TAG _PyRuntime.types.next_version_tag
5857#define NEXT_VERSION_TAG (interp ) \
5958 (interp)->types.next_version_tag
6059
@@ -266,8 +265,8 @@ static_ext_type_lookup(PyInterpreterState *interp, size_t index,
266265 assert (index < _Py_MAX_MANAGED_STATIC_EXT_TYPES );
267266
268267 size_t full_index = index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES ;
269- int64_t interp_count =
270- _PyRuntime .types .managed_static .types [full_index ].interp_count ;
268+ int64_t interp_count = _Py_atomic_load_int64 (
269+ & _PyRuntime .types .managed_static .types [full_index ].interp_count ) ;
271270 assert ((interp_count == 0 ) ==
272271 (_PyRuntime .types .managed_static .types [full_index ].type == NULL ));
273272 * p_interp_count = interp_count ;
@@ -344,7 +343,7 @@ managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self,
344343 : index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES ;
345344
346345 assert ((initial == 1 ) ==
347- (_PyRuntime .types .managed_static .types [full_index ].interp_count == 0 ));
346+ (_Py_atomic_load_int64 ( & _PyRuntime .types .managed_static .types [full_index ].interp_count ) == 0 ));
348347 (void )_Py_atomic_add_int64 (
349348 & _PyRuntime .types .managed_static .types [full_index ].interp_count , 1 );
350349
@@ -393,7 +392,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
393392 : & (interp -> types .for_extensions .initialized [index ]);
394393 assert (state != NULL );
395394
396- assert (_PyRuntime .types .managed_static .types [full_index ].interp_count > 0 );
395+ assert (_Py_atomic_load_int64 ( & _PyRuntime .types .managed_static .types [full_index ].interp_count ) > 0 );
397396 assert (_PyRuntime .types .managed_static .types [full_index ].type == state -> type );
398397
399398 assert (state -> type != NULL );
@@ -403,7 +402,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
403402 (void )_Py_atomic_add_int64 (
404403 & _PyRuntime .types .managed_static .types [full_index ].interp_count , -1 );
405404 if (final ) {
406- assert (!_PyRuntime .types .managed_static .types [full_index ].interp_count );
405+ assert (!_Py_atomic_load_int64 ( & _PyRuntime .types .managed_static .types [full_index ].interp_count ) );
407406 _PyRuntime .types .managed_static .types [full_index ].type = NULL ;
408407
409408 managed_static_type_index_clear (self );
@@ -1359,6 +1358,19 @@ _PyType_LookupByVersion(unsigned int version)
13591358#error "_Py_ATTR_CACHE_UNUSED must be bigger than max"
13601359#endif
13611360
1361+ static inline unsigned int
1362+ next_global_version_tag (void )
1363+ {
1364+ unsigned int old ;
1365+ do {
1366+ old = _Py_atomic_load_uint_relaxed (& _PyRuntime .types .next_version_tag );
1367+ if (old >= _Py_MAX_GLOBAL_TYPE_VERSION_TAG ) {
1368+ return 0 ;
1369+ }
1370+ } while (!_Py_atomic_compare_exchange_uint (& _PyRuntime .types .next_version_tag , & old , old + 1 ));
1371+ return old + 1 ;
1372+ }
1373+
13621374static int
13631375assign_version_tag (PyInterpreterState * interp , PyTypeObject * type )
13641376{
@@ -1389,11 +1401,12 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
13891401 }
13901402 if (type -> tp_flags & Py_TPFLAGS_IMMUTABLETYPE ) {
13911403 /* static types */
1392- if (NEXT_GLOBAL_VERSION_TAG > _Py_MAX_GLOBAL_TYPE_VERSION_TAG ) {
1404+ unsigned int next_version_tag = next_global_version_tag ();
1405+ if (next_version_tag == 0 ) {
13931406 /* We have run out of version numbers */
13941407 return 0 ;
13951408 }
1396- set_version_unlocked (type , NEXT_GLOBAL_VERSION_TAG ++ );
1409+ set_version_unlocked (type , next_version_tag );
13971410 assert (type -> tp_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
13981411 }
13991412 else {
@@ -9007,7 +9020,11 @@ type_ready_set_new(PyTypeObject *type, int initial)
90079020 && base == & PyBaseObject_Type
90089021 && !(type -> tp_flags & Py_TPFLAGS_HEAPTYPE ))
90099022 {
9010- type_add_flags (type , Py_TPFLAGS_DISALLOW_INSTANTIATION );
9023+ if (initial ) {
9024+ type_add_flags (type , Py_TPFLAGS_DISALLOW_INSTANTIATION );
9025+ } else {
9026+ assert (type -> tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION );
9027+ }
90119028 }
90129029
90139030 if (!(type -> tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION )) {
@@ -9021,13 +9038,17 @@ type_ready_set_new(PyTypeObject *type, int initial)
90219038 }
90229039 }
90239040 else {
9024- // tp_new is NULL: inherit tp_new from base
9025- type -> tp_new = base -> tp_new ;
9041+ if (initial ) {
9042+ // tp_new is NULL: inherit tp_new from base
9043+ type -> tp_new = base -> tp_new ;
9044+ }
90269045 }
90279046 }
90289047 else {
90299048 // Py_TPFLAGS_DISALLOW_INSTANTIATION sets tp_new to NULL
9030- type -> tp_new = NULL ;
9049+ if (initial ) {
9050+ type -> tp_new = NULL ;
9051+ }
90319052 }
90329053 return 0 ;
90339054}
@@ -9160,7 +9181,12 @@ type_ready(PyTypeObject *type, int initial)
91609181 }
91619182
91629183 /* All done -- set the ready flag */
9163- type_add_flags (type , Py_TPFLAGS_READY );
9184+ if (initial ) {
9185+ type_add_flags (type , Py_TPFLAGS_READY );
9186+ } else {
9187+ assert (type -> tp_flags & Py_TPFLAGS_READY );
9188+ }
9189+
91649190 stop_readying (type );
91659191
91669192 assert (_PyType_CheckConsistency (type ));
@@ -9209,15 +9235,16 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self,
92099235 assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_DICT ));
92109236 assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_WEAKREF ));
92119237
9212- if (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 ) {
9213- assert (initial );
9238+ if (initial ) {
9239+ assert (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 );
92149240
92159241 type_add_flags (self , _Py_TPFLAGS_STATIC_BUILTIN );
92169242 type_add_flags (self , Py_TPFLAGS_IMMUTABLETYPE );
92179243
9218- assert (NEXT_GLOBAL_VERSION_TAG <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
92199244 if (self -> tp_version_tag == 0 ) {
9220- _PyType_SetVersion (self , NEXT_GLOBAL_VERSION_TAG ++ );
9245+ unsigned int next_version_tag = next_global_version_tag ();
9246+ assert (next_version_tag != 0 );
9247+ _PyType_SetVersion (self , next_version_tag );
92219248 }
92229249 }
92239250 else {
0 commit comments