Zebediah Figura (@zfigura) commented about dlls/ntdll/sync.c:
{
/* Not locked exclusive, and no exclusive waiters.
* We can try to grab it. */
++new.s.owners;
wait = FALSE;
}
else
{
wait = TRUE;
}
} while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
/* Someone else is also appending to the list, they have linked their
* node to `prev`, but hasn't changed lock->Ptr yet. So we wait for
* the lock to change and retry. */
RtlWaitOnAddress(&lock->Ptr, &expected.Ptr, sizeof(expected.Ptr),
NULL);
I worry about the prospect of making this a futex wait, because as cheap as futexes are, we are in an extremely hot path here. Considering that what we're racing against should be two consecutive cmpxchg instructions, with no intervening calculations or memory accesses, I think spinning may be the right answer here.
I don't know if that means that we explicitly spin until the lock changes, or we just return FALSE and go through srwlock_wait() again.