[*] NT Condvar hardening: Windows XP-7 hardening of the spin condition when racing against multiple threads
This commit is contained in:
parent
12fd03a6dd
commit
2b0ed79729
@ -158,6 +158,11 @@ namespace Aurora::Threading::Primitives
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!gUseNativeWaitCondvar)
|
||||
{
|
||||
this->SignalSpuriously();
|
||||
}
|
||||
|
||||
this->AddWaiter();
|
||||
}
|
||||
}
|
||||
@ -213,6 +218,11 @@ namespace Aurora::Threading::Primitives
|
||||
return bRet;
|
||||
}
|
||||
|
||||
if (!gUseNativeWaitCondvar)
|
||||
{
|
||||
this->SignalSpuriously();
|
||||
}
|
||||
|
||||
this->AddWaiter();
|
||||
}
|
||||
}
|
||||
@ -324,6 +334,41 @@ namespace Aurora::Threading::Primitives
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConditionVariableNT::SignalSpuriously()
|
||||
{
|
||||
#if !defined(AURORA_FORCE_SRW_LOCKS)
|
||||
auto original = this->wlist;
|
||||
auto expected = original;
|
||||
expected = expected >> kShiftCountByBits;
|
||||
|
||||
if (expected)
|
||||
{
|
||||
// NOTE: missing this->signalCount atomic increment to force another AddWaiter under successful keyedevent return
|
||||
while (expected)
|
||||
{
|
||||
if (AuAtomicCompareExchange(&this->wlist, ((expected - 1) << kShiftCountByBits) /*intentional clear*/, original) == original)
|
||||
{
|
||||
if (gUseNativeWaitCondvar)
|
||||
{
|
||||
InternalLTSWakeOne((void *)&this->wlist);
|
||||
}
|
||||
else
|
||||
{
|
||||
pNtReleaseKeyedEvent(gKeyedEventHandle, (void *)&this->wlist, FALSE, nullptr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
original = this->wlist;
|
||||
expected = original >> kShiftCountByBits;
|
||||
}
|
||||
}
|
||||
#else
|
||||
::WakeConditionVariable(&this->winCond_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConditionVariableNT::Signal()
|
||||
{
|
||||
|
@ -19,6 +19,7 @@ namespace Aurora::Threading::Primitives
|
||||
|
||||
bool WaitForSignalNsEx(Win32ConditionMutex *pMutex, AuUInt64 timeout, bool bSpin = true);
|
||||
void Signal();
|
||||
auline void SignalSpuriously();
|
||||
void Broadcast();
|
||||
void BroadcastN(AuUInt32 nBroadcast);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user