@@ -104,12 +104,29 @@ extern "C" {
104104# define Py_END_CRITICAL_SECTION2 () \
105105 _PyCriticalSection2_End(&_cs2); \
106106 }
107+
108+ // Asserts that the mutex is locked. The mutex must be held by the
109+ // top-most critical section otherwise there's the possibility
110+ // that the mutex would be swalled out in some code paths.
111+ #define _Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED (mutex ) \
112+ _PyCriticalSection_AssertHeld(mutex)
113+
114+ // Asserts that the mutex for the given object is locked. The mutex must
115+ // be held by the top-most critical section otherwise there's the
116+ // possibility that the mutex would be swalled out in some code paths.
117+ #define _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (op ) \
118+ _Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(&_PyObject_CAST(op)->ob_mutex)
119+
120+
121+
107122#else /* !Py_GIL_DISABLED */
108123// The critical section APIs are no-ops with the GIL.
109124# define Py_BEGIN_CRITICAL_SECTION (op )
110125# define Py_END_CRITICAL_SECTION ()
111126# define Py_BEGIN_CRITICAL_SECTION2 (a , b )
112127# define Py_END_CRITICAL_SECTION2 ()
128+ # define _Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED (mutex )
129+ # define _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (op )
113130#endif /* !Py_GIL_DISABLED */
114131
115132typedef struct {
@@ -236,6 +253,19 @@ _PyCriticalSection2_End(_PyCriticalSection2 *c)
236253PyAPI_FUNC (void )
237254_PyCriticalSection_SuspendAll (PyThreadState * tstate );
238255
256+ #ifdef Py_GIL_DISABLED
257+
258+ static inline void
259+ _PyCriticalSection_AssertHeld (PyMutex * mutex ) {
260+ #ifdef Py_DEBUG
261+ PyThreadState * tstate = _PyThreadState_GET ();
262+ _PyCriticalSection * cs = (_PyCriticalSection * )tstate -> critical_section ;
263+ assert (cs != NULL && cs -> mutex == mutex );
264+ #endif
265+ }
266+
267+ #endif
268+
239269#ifdef __cplusplus
240270}
241271#endif
0 commit comments