mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
Bill Tutt:
Calling Sleep(0) for a spinlock can cause a priority inversion, adding comments to explain what's going on.
This commit is contained in:
parent
65e69002a2
commit
ede8c6eea1
1 changed files with 24 additions and 1 deletions
|
@ -50,9 +50,32 @@ static PVOID WINAPI interlocked_cmp_xchg(PVOID *dest, PVOID exc, PVOID comperand
|
||||||
{
|
{
|
||||||
static LONG spinlock = 0 ;
|
static LONG spinlock = 0 ;
|
||||||
PVOID result ;
|
PVOID result ;
|
||||||
|
DWORD dwSleep = 0;
|
||||||
|
|
||||||
/* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */
|
/* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */
|
||||||
while(InterlockedExchange(&spinlock, 1)) Sleep(0) ;
|
while(InterlockedExchange(&spinlock, 1))
|
||||||
|
{
|
||||||
|
// Using Sleep(0) can cause a priority inversion.
|
||||||
|
// Sleep(0) only yields the processor if there's
|
||||||
|
// another thread of the same priority that's
|
||||||
|
// ready to run. If a high-priority thread is
|
||||||
|
// trying to acquire the lock, which is held by
|
||||||
|
// a low-priority thread, then the low-priority
|
||||||
|
// thread may never get scheduled and hence never
|
||||||
|
// free the lock. NT attempts to avoid priority
|
||||||
|
// inversions by temporarily boosting the priority
|
||||||
|
// of low-priority runnable threads, but the problem
|
||||||
|
// can still occur if there's a medium-priority
|
||||||
|
// thread that's always runnable. If Sleep(1) is used,
|
||||||
|
// then the thread unconditionally yields the CPU. We
|
||||||
|
// only do this for the second and subsequent even
|
||||||
|
// iterations, since a millisecond is a long time to wait
|
||||||
|
// if the thread can be scheduled in again sooner
|
||||||
|
// (~100,000 instructions).
|
||||||
|
// Avoid priority inversion: 0, 1, 0, 1,...
|
||||||
|
Sleep(dwSleep);
|
||||||
|
dwSleep = !dwSleep;
|
||||||
|
}
|
||||||
result = *dest ;
|
result = *dest ;
|
||||||
if (result == comperand)
|
if (result == comperand)
|
||||||
*dest = exc ;
|
*dest = exc ;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue