@@ -76,13 +76,73 @@ class object "PyObject *" "&PyBaseObject_Type"
7676#define ASSERT_TYPE_LOCK_HELD () \
7777 _Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(TYPE_LOCK)
7878
79+ static void
80+ types_stop_world (void )
81+ {
82+ PyInterpreterState * interp = _PyInterpreterState_GET ();
83+ _PyEval_StopTheWorld (interp );
84+ }
85+
86+ static void
87+ types_start_world (void )
88+ {
89+ PyInterpreterState * interp = _PyInterpreterState_GET ();
90+ _PyEval_StartTheWorld (interp );
91+ }
92+
93+ // This is used to temporarily prevent the TYPE_LOCK from being suspended
94+ // when held by the topmost critical section.
95+ static void
96+ type_lock_prevent_release (void )
97+ {
98+ PyThreadState * tstate = _PyThreadState_GET ();
99+ uintptr_t * tagptr = & tstate -> critical_section ;
100+ PyCriticalSection * c = (PyCriticalSection * )(* tagptr & ~_Py_CRITICAL_SECTION_MASK );
101+ if (!(* tagptr & _Py_CRITICAL_SECTION_TWO_MUTEXES )) {
102+ assert (c -> _cs_mutex == TYPE_LOCK );
103+ c -> _cs_mutex = NULL ;
104+ }
105+ else {
106+ PyCriticalSection2 * c2 = (PyCriticalSection2 * )c ;
107+ if (c -> _cs_mutex == TYPE_LOCK ) {
108+ c -> _cs_mutex = c2 -> _cs_mutex2 ;
109+ c2 -> _cs_mutex2 = NULL ;
110+ }
111+ else {
112+ assert (c2 -> _cs_mutex2 == TYPE_LOCK );
113+ c2 -> _cs_mutex2 = NULL ;
114+ }
115+ }
116+ }
117+
118+ static void
119+ type_lock_allow_release (void )
120+ {
121+ PyThreadState * tstate = _PyThreadState_GET ();
122+ uintptr_t * tagptr = & tstate -> critical_section ;
123+ PyCriticalSection * c = (PyCriticalSection * )(* tagptr & ~_Py_CRITICAL_SECTION_MASK );
124+ if (!(* tagptr & _Py_CRITICAL_SECTION_TWO_MUTEXES )) {
125+ assert (c -> _cs_mutex == NULL );
126+ c -> _cs_mutex = TYPE_LOCK ;
127+ }
128+ else {
129+ PyCriticalSection2 * c2 = (PyCriticalSection2 * )c ;
130+ assert (c2 -> _cs_mutex2 == NULL );
131+ c2 -> _cs_mutex2 = TYPE_LOCK ;
132+ }
133+ }
134+
79135#else
80136
81137#define BEGIN_TYPE_LOCK ()
82138#define END_TYPE_LOCK ()
83139#define BEGIN_TYPE_DICT_LOCK (d )
84140#define END_TYPE_DICT_LOCK ()
85141#define ASSERT_TYPE_LOCK_HELD ()
142+ #define types_stop_world ()
143+ #define types_start_world ()
144+ #define type_lock_prevent_release ()
145+ #define type_lock_allow_release ()
86146
87147#endif
88148
@@ -541,7 +601,6 @@ clear_tp_bases(PyTypeObject *self, int final)
541601static inline PyObject *
542602lookup_tp_mro (PyTypeObject * self )
543603{
544- ASSERT_TYPE_LOCK_HELD ();
545604 return self -> tp_mro ;
546605}
547606
@@ -580,8 +639,19 @@ set_tp_mro(PyTypeObject *self, PyObject *mro, int initial)
580639 /* Other checks are done via set_tp_bases. */
581640 _Py_SetImmortal (mro );
582641 }
642+ else {
643+ PyUnstable_Object_EnableDeferredRefcount (mro );
644+ }
645+ }
646+ if (!initial ) {
647+ type_lock_prevent_release ();
648+ types_stop_world ();
583649 }
584650 self -> tp_mro = mro ;
651+ if (!initial ) {
652+ types_start_world ();
653+ type_lock_allow_release ();
654+ }
585655}
586656
587657static inline void
@@ -1627,18 +1697,11 @@ static PyObject *
16271697type_get_mro (PyObject * tp , void * Py_UNUSED (closure ))
16281698{
16291699 PyTypeObject * type = PyTypeObject_CAST (tp );
1630- PyObject * mro ;
1631-
1632- BEGIN_TYPE_LOCK ();
1633- mro = lookup_tp_mro (type );
1700+ PyObject * mro = lookup_tp_mro (type );
16341701 if (mro == NULL ) {
1635- mro = Py_None ;
1636- } else {
1637- Py_INCREF (mro );
1702+ Py_RETURN_NONE ;
16381703 }
1639-
1640- END_TYPE_LOCK ();
1641- return mro ;
1704+ return Py_NewRef (mro );
16421705}
16431706
16441707static PyTypeObject * best_base (PyObject * );
0 commit comments