@@ -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
@@ -157,8 +156,8 @@ static_ext_type_lookup(PyInterpreterState *interp, size_t index,
157156 assert (index < _Py_MAX_MANAGED_STATIC_EXT_TYPES );
158157
159158 size_t full_index = index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES ;
160- int64_t interp_count =
161- _PyRuntime .types .managed_static .types [full_index ].interp_count ;
159+ int64_t interp_count = _Py_atomic_load_int64 (
160+ & _PyRuntime .types .managed_static .types [full_index ].interp_count ) ;
162161 assert ((interp_count == 0 ) ==
163162 (_PyRuntime .types .managed_static .types [full_index ].type == NULL ));
164163 * p_interp_count = interp_count ;
@@ -235,7 +234,7 @@ managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self,
235234 : index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES ;
236235
237236 assert ((initial == 1 ) ==
238- (_PyRuntime .types .managed_static .types [full_index ].interp_count == 0 ));
237+ (_Py_atomic_load_int64 ( & _PyRuntime .types .managed_static .types [full_index ].interp_count ) == 0 ));
239238 (void )_Py_atomic_add_int64 (
240239 & _PyRuntime .types .managed_static .types [full_index ].interp_count , 1 );
241240
@@ -284,7 +283,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
284283 : & (interp -> types .for_extensions .initialized [index ]);
285284 assert (state != NULL );
286285
287- assert (_PyRuntime .types .managed_static .types [full_index ].interp_count > 0 );
286+ assert (_Py_atomic_load_int64 ( & _PyRuntime .types .managed_static .types [full_index ].interp_count ) > 0 );
288287 assert (_PyRuntime .types .managed_static .types [full_index ].type == state -> type );
289288
290289 assert (state -> type != NULL );
@@ -294,7 +293,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
294293 (void )_Py_atomic_add_int64 (
295294 & _PyRuntime .types .managed_static .types [full_index ].interp_count , -1 );
296295 if (final ) {
297- assert (!_PyRuntime .types .managed_static .types [full_index ].interp_count );
296+ assert (!_Py_atomic_load_int64 ( & _PyRuntime .types .managed_static .types [full_index ].interp_count ) );
298297 _PyRuntime .types .managed_static .types [full_index ].type = NULL ;
299298
300299 managed_static_type_index_clear (self );
@@ -1258,6 +1257,19 @@ _PyType_GetVersionForCurrentState(PyTypeObject *tp)
12581257#error "_Py_ATTR_CACHE_UNUSED must be bigger than max"
12591258#endif
12601259
1260+ static inline unsigned int
1261+ next_global_version_tag (void )
1262+ {
1263+ unsigned int old ;
1264+ do {
1265+ old = _Py_atomic_load_uint_relaxed (& _PyRuntime .types .next_version_tag );
1266+ if (old >= _Py_MAX_GLOBAL_TYPE_VERSION_TAG ) {
1267+ return 0 ;
1268+ }
1269+ } while (!_Py_atomic_compare_exchange_uint (& _PyRuntime .types .next_version_tag , & old , old + 1 ));
1270+ return old + 1 ;
1271+ }
1272+
12611273static int
12621274assign_version_tag (PyInterpreterState * interp , PyTypeObject * type )
12631275{
@@ -1288,11 +1300,12 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
12881300 }
12891301 if (type -> tp_flags & Py_TPFLAGS_IMMUTABLETYPE ) {
12901302 /* static types */
1291- if (NEXT_GLOBAL_VERSION_TAG > _Py_MAX_GLOBAL_TYPE_VERSION_TAG ) {
1303+ unsigned int next_version_tag = next_global_version_tag ();
1304+ if (next_version_tag == 0 ) {
12921305 /* We have run out of version numbers */
12931306 return 0 ;
12941307 }
1295- set_version_unlocked (type , NEXT_GLOBAL_VERSION_TAG ++ );
1308+ set_version_unlocked (type , next_version_tag );
12961309 assert (type -> tp_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
12971310 }
12981311 else {
@@ -8704,7 +8717,11 @@ type_ready_set_new(PyTypeObject *type, int initial)
87048717 && base == & PyBaseObject_Type
87058718 && !(type -> tp_flags & Py_TPFLAGS_HEAPTYPE ))
87068719 {
8707- type_add_flags (type , Py_TPFLAGS_DISALLOW_INSTANTIATION );
8720+ if (initial ) {
8721+ type_add_flags (type , Py_TPFLAGS_DISALLOW_INSTANTIATION );
8722+ } else {
8723+ assert (type -> tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION );
8724+ }
87088725 }
87098726
87108727 if (!(type -> tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION )) {
@@ -8718,13 +8735,17 @@ type_ready_set_new(PyTypeObject *type, int initial)
87188735 }
87198736 }
87208737 else {
8721- // tp_new is NULL: inherit tp_new from base
8722- type -> tp_new = base -> tp_new ;
8738+ if (initial ) {
8739+ // tp_new is NULL: inherit tp_new from base
8740+ type -> tp_new = base -> tp_new ;
8741+ }
87238742 }
87248743 }
87258744 else {
87268745 // Py_TPFLAGS_DISALLOW_INSTANTIATION sets tp_new to NULL
8727- type -> tp_new = NULL ;
8746+ if (initial ) {
8747+ type -> tp_new = NULL ;
8748+ }
87288749 }
87298750 return 0 ;
87308751}
@@ -8857,7 +8878,12 @@ type_ready(PyTypeObject *type, int initial)
88578878 }
88588879
88598880 /* All done -- set the ready flag */
8860- type_add_flags (type , Py_TPFLAGS_READY );
8881+ if (initial ) {
8882+ type_add_flags (type , Py_TPFLAGS_READY );
8883+ } else {
8884+ assert (type -> tp_flags & Py_TPFLAGS_READY );
8885+ }
8886+
88618887 stop_readying (type );
88628888
88638889 assert (_PyType_CheckConsistency (type ));
@@ -8906,15 +8932,16 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self,
89068932 assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_DICT ));
89078933 assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_WEAKREF ));
89088934
8909- if (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 ) {
8910- assert (initial );
8935+ if (initial ) {
8936+ assert (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 );
89118937
89128938 type_add_flags (self , _Py_TPFLAGS_STATIC_BUILTIN );
89138939 type_add_flags (self , Py_TPFLAGS_IMMUTABLETYPE );
89148940
8915- assert (NEXT_GLOBAL_VERSION_TAG <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
89168941 if (self -> tp_version_tag == 0 ) {
8917- _PyType_SetVersion (self , NEXT_GLOBAL_VERSION_TAG ++ );
8942+ unsigned int next_version_tag = next_global_version_tag ();
8943+ assert (next_version_tag != 0 );
8944+ _PyType_SetVersion (self , next_version_tag );
89188945 }
89198946 }
89208947 else {
0 commit comments