@@ -54,7 +54,6 @@ class object "PyObject *" "&PyBaseObject_Type"
54
54
PyUnicode_CheckExact(name) && \
55
55
(PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE)
56
56
57
- #define NEXT_GLOBAL_VERSION_TAG _PyRuntime.types.next_version_tag
58
57
#define NEXT_VERSION_TAG (interp ) \
59
58
(interp)->types.next_version_tag
60
59
@@ -266,8 +265,8 @@ static_ext_type_lookup(PyInterpreterState *interp, size_t index,
266
265
assert (index < _Py_MAX_MANAGED_STATIC_EXT_TYPES );
267
266
268
267
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 ) ;
271
270
assert ((interp_count == 0 ) ==
272
271
(_PyRuntime .types .managed_static .types [full_index ].type == NULL ));
273
272
* p_interp_count = interp_count ;
@@ -344,7 +343,7 @@ managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self,
344
343
: index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES ;
345
344
346
345
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 ));
348
347
(void )_Py_atomic_add_int64 (
349
348
& _PyRuntime .types .managed_static .types [full_index ].interp_count , 1 );
350
349
@@ -393,7 +392,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
393
392
: & (interp -> types .for_extensions .initialized [index ]);
394
393
assert (state != NULL );
395
394
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 );
397
396
assert (_PyRuntime .types .managed_static .types [full_index ].type == state -> type );
398
397
399
398
assert (state -> type != NULL );
@@ -403,7 +402,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
403
402
(void )_Py_atomic_add_int64 (
404
403
& _PyRuntime .types .managed_static .types [full_index ].interp_count , -1 );
405
404
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 ) );
407
406
_PyRuntime .types .managed_static .types [full_index ].type = NULL ;
408
407
409
408
managed_static_type_index_clear (self );
@@ -1359,6 +1358,19 @@ _PyType_LookupByVersion(unsigned int version)
1359
1358
#error "_Py_ATTR_CACHE_UNUSED must be bigger than max"
1360
1359
#endif
1361
1360
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
+
1362
1374
static int
1363
1375
assign_version_tag (PyInterpreterState * interp , PyTypeObject * type )
1364
1376
{
@@ -1389,11 +1401,12 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
1389
1401
}
1390
1402
if (type -> tp_flags & Py_TPFLAGS_IMMUTABLETYPE ) {
1391
1403
/* 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 ) {
1393
1406
/* We have run out of version numbers */
1394
1407
return 0 ;
1395
1408
}
1396
- set_version_unlocked (type , NEXT_GLOBAL_VERSION_TAG ++ );
1409
+ set_version_unlocked (type , next_version_tag );
1397
1410
assert (type -> tp_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
1398
1411
}
1399
1412
else {
@@ -9007,7 +9020,11 @@ type_ready_set_new(PyTypeObject *type, int initial)
9007
9020
&& base == & PyBaseObject_Type
9008
9021
&& !(type -> tp_flags & Py_TPFLAGS_HEAPTYPE ))
9009
9022
{
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
+ }
9011
9028
}
9012
9029
9013
9030
if (!(type -> tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION )) {
@@ -9021,13 +9038,17 @@ type_ready_set_new(PyTypeObject *type, int initial)
9021
9038
}
9022
9039
}
9023
9040
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
+ }
9026
9045
}
9027
9046
}
9028
9047
else {
9029
9048
// Py_TPFLAGS_DISALLOW_INSTANTIATION sets tp_new to NULL
9030
- type -> tp_new = NULL ;
9049
+ if (initial ) {
9050
+ type -> tp_new = NULL ;
9051
+ }
9031
9052
}
9032
9053
return 0 ;
9033
9054
}
@@ -9160,7 +9181,12 @@ type_ready(PyTypeObject *type, int initial)
9160
9181
}
9161
9182
9162
9183
/* 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
+
9164
9190
stop_readying (type );
9165
9191
9166
9192
assert (_PyType_CheckConsistency (type ));
@@ -9209,15 +9235,16 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self,
9209
9235
assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_DICT ));
9210
9236
assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_WEAKREF ));
9211
9237
9212
- if (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 ) {
9213
- assert (initial );
9238
+ if (initial ) {
9239
+ assert (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 );
9214
9240
9215
9241
type_add_flags (self , _Py_TPFLAGS_STATIC_BUILTIN );
9216
9242
type_add_flags (self , Py_TPFLAGS_IMMUTABLETYPE );
9217
9243
9218
- assert (NEXT_GLOBAL_VERSION_TAG <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
9219
9244
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 );
9221
9248
}
9222
9249
}
9223
9250
else {
0 commit comments