mirror of
https://github.com/python/cpython.git
synced 2026-02-23 23:50:54 +00:00
gh-144513: Skip critical section locking during stop-the-world (gh-144524)
When the interpreter is in a stop-the-world pause, critical sections don't need to acquire locks since no other threads can be running. This avoids a potential deadlock where lock fairness hands off ownership to a thread that has already suspended for stop-the-world.
This commit is contained in:
parent
5bb3bbb9c6
commit
0fdf6a9a71
3 changed files with 103 additions and 1 deletions
|
|
@ -1,7 +1,8 @@
|
|||
#include "Python.h"
|
||||
|
||||
#include "pycore_lock.h"
|
||||
#include "pycore_critical_section.h"
|
||||
#include "pycore_interp.h"
|
||||
#include "pycore_lock.h"
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
static_assert(_Alignof(PyCriticalSection) >= 4,
|
||||
|
|
@ -42,6 +43,15 @@ _PyCriticalSection_BeginSlow(PyThreadState *tstate, PyCriticalSection *c, PyMute
|
|||
}
|
||||
}
|
||||
}
|
||||
// If the world is stopped, we don't need to acquire the lock because
|
||||
// there are no other threads that could be accessing the object.
|
||||
// Without this check, acquiring a critical section while the world is
|
||||
// stopped could lead to a deadlock.
|
||||
if (tstate->interp->stoptheworld.world_stopped) {
|
||||
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;
|
||||
|
|
@ -56,6 +66,12 @@ _PyCriticalSection2_BeginSlow(PyThreadState *tstate, PyCriticalSection2 *c, PyMu
|
|||
int is_m1_locked)
|
||||
{
|
||||
#ifdef Py_GIL_DISABLED
|
||||
if (tstate->interp->stoptheworld.world_stopped) {
|
||||
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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue