https://github.com/python/cpython/commit/c2ca7724af94df6e078a4b2e86d1be8c410d9940
commit: c2ca7724af94df6e078a4b2e86d1be8c410d9940
branch: main
author: Daniele Parmeggiani <[email protected]>
committer: colesbury <[email protected]>
date: 2026-06-16T16:56:37Z
summary:
gh-150902: Optimize PyCriticalSection2 to skip locking the same locks held by
the current CS2
This mimics an optimization already present for the single-mutex critical
section.
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-13-14-42.gh-issue-150902.-CWZ66.rst
M Include/internal/pycore_critical_section.h
M Python/critical_section.c
diff --git a/Include/internal/pycore_critical_section.h
b/Include/internal/pycore_critical_section.h
index 2a2846b1296b901..51d99d74ca159f6 100644
--- a/Include/internal/pycore_critical_section.h
+++ b/Include/internal/pycore_critical_section.h
@@ -196,10 +196,9 @@ _PyCriticalSection2_Begin(PyThreadState *tstate,
PyCriticalSection2 *c, PyObject
static inline void
_PyCriticalSection2_End(PyThreadState *tstate, PyCriticalSection2 *c)
{
- // if mutex1 is NULL, we used the fast path in
- // _PyCriticalSection_BeginSlow for mutexes that are already held,
- // which should only happen when mutex1 and mutex2 were the same mutex,
- // and mutex2 should also be NULL.
+ // if mutex1 is NULL, we used the fast path in either
+ // _PyCriticalSection_BeginSlow or _PyCriticalSection2_BeginSlow for
mutexes
+ // that are already held, and mutex2 should also be NULL.
if (c->_cs_base._cs_mutex == NULL) {
assert(c->_cs_mutex2 == NULL);
return;
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-13-14-42.gh-issue-150902.-CWZ66.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-13-14-42.gh-issue-150902.-CWZ66.rst
new file mode 100644
index 000000000000000..e3b7cd387b439fe
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-13-14-42.gh-issue-150902.-CWZ66.rst
@@ -0,0 +1 @@
+Apply an existing optimization of PyCriticalSection (single mutex) to
PyCriticalSection2: avoid acquiring the same locks that the current CS has
already acquired.
diff --git a/Python/critical_section.c b/Python/critical_section.c
index 98e23eda7cdd77e..dbee6f236a73bea 100644
--- a/Python/critical_section.c
+++ b/Python/critical_section.c
@@ -72,6 +72,22 @@ _PyCriticalSection2_BeginSlow(PyThreadState *tstate,
PyCriticalSection2 *c, PyMu
c->_cs_base._cs_prev = 0;
return;
}
+ // Same optimization as in _PyCriticalSection_BeginSlow: skip locking when
+ // recursively acquiring the same locks.
+ if (tstate->critical_section &&
+ tstate->critical_section & _Py_CRITICAL_SECTION_TWO_MUTEXES) {
+ PyCriticalSection2 *prev2 = (PyCriticalSection2 *)
+ untag_critical_section(tstate->critical_section);
+ assert((uintptr_t)m1 < (uintptr_t)m2);
+ assert((uintptr_t)prev2->_cs_base._cs_mutex <
+ (uintptr_t)prev2->_cs_mutex2);
+ if (prev2->_cs_base._cs_mutex == m1 && prev2->_cs_mutex2 == m2) {
+ c->_cs_base._cs_mutex = NULL;
+ c->_cs_mutex2 = NULL;
+ c->_cs_base._cs_prev = 0;
+ return;
+ }
+ }
c->_cs_base._cs_mutex = NULL;
c->_cs_mutex2 = NULL;
c->_cs_base._cs_prev = tstate->critical_section;
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]