diff options
author | T. Wouters <thomas@python.org> | 2024-12-23 12:31:33 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-23 12:31:33 (GMT) |
commit | 180d417e9f9456defd4c5b53cae678c318287921 (patch) | |
tree | cdcc1e622b3e5a11f61d739dd514dde31048e643 /Python | |
parent | 831b6de6d725c697f2f61fd35c4448cd8a9354ff (diff) | |
download | cpython-180d417e9f9456defd4c5b53cae678c318287921.zip cpython-180d417e9f9456defd4c5b53cae678c318287921.tar.gz cpython-180d417e9f9456defd4c5b53cae678c318287921.tar.bz2 |
gh-114203: Optimise simple recursive critical sections (#128126)
Add a fast path to (single-mutex) critical section locking _iff_ the mutex
is already held by the currently active, top-most critical section of this
thread. This can matter a lot for indirectly recursive critical sections
without intervening critical sections.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/critical_section.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/Python/critical_section.c b/Python/critical_section.c index 62ed255..73857b8 100644 --- a/Python/critical_section.c +++ b/Python/critical_section.c @@ -8,11 +8,28 @@ static_assert(_Alignof(PyCriticalSection) >= 4, "critical section must be aligned to at least 4 bytes"); #endif +#ifdef Py_GIL_DISABLED +static PyCriticalSection * +untag_critical_section(uintptr_t tag) +{ + return (PyCriticalSection *)(tag & ~_Py_CRITICAL_SECTION_MASK); +} +#endif + void _PyCriticalSection_BeginSlow(PyCriticalSection *c, PyMutex *m) { #ifdef Py_GIL_DISABLED PyThreadState *tstate = _PyThreadState_GET(); + // As an optimisation for locking the same object recursively, skip + // locking if the mutex is currently locked by the top-most critical + // section. + if (tstate->critical_section && + untag_critical_section(tstate->critical_section)->_cs_mutex == m) { + c->_cs_mutex = NULL; + c->_cs_prev = 0; + return; + } c->_cs_mutex = NULL; c->_cs_prev = (uintptr_t)tstate->critical_section; tstate->critical_section = (uintptr_t)c; @@ -42,13 +59,6 @@ _PyCriticalSection2_BeginSlow(PyCriticalSection2 *c, PyMutex *m1, PyMutex *m2, #endif } -#ifdef Py_GIL_DISABLED -static PyCriticalSection * -untag_critical_section(uintptr_t tag) -{ - return (PyCriticalSection *)(tag & ~_Py_CRITICAL_SECTION_MASK); -} -#endif // Release all locks held by critical sections. This is called by // _PyThreadState_Detach. |