[*] NT Condvar hardening: Windows XP-7 hardening of the spin condition when racing against multiple threads

This commit is contained in:
Reece Wilson 2024-02-08 03:54:48 +00:00
parent 12fd03a6dd
commit 2b0ed79729
2 changed files with 46 additions and 0 deletions

View File

@ -158,6 +158,11 @@ namespace Aurora::Threading::Primitives
return true; return true;
} }
if (!gUseNativeWaitCondvar)
{
this->SignalSpuriously();
}
this->AddWaiter(); this->AddWaiter();
} }
} }
@ -213,6 +218,11 @@ namespace Aurora::Threading::Primitives
return bRet; return bRet;
} }
if (!gUseNativeWaitCondvar)
{
this->SignalSpuriously();
}
this->AddWaiter(); this->AddWaiter();
} }
} }
@ -325,6 +335,41 @@ namespace Aurora::Threading::Primitives
#endif #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() void ConditionVariableNT::Signal()
{ {
#if !defined(AURORA_FORCE_SRW_LOCKS) #if !defined(AURORA_FORCE_SRW_LOCKS)

View File

@ -19,6 +19,7 @@ namespace Aurora::Threading::Primitives
bool WaitForSignalNsEx(Win32ConditionMutex *pMutex, AuUInt64 timeout, bool bSpin = true); bool WaitForSignalNsEx(Win32ConditionMutex *pMutex, AuUInt64 timeout, bool bSpin = true);
void Signal(); void Signal();
auline void SignalSpuriously();
void Broadcast(); void Broadcast();
void BroadcastN(AuUInt32 nBroadcast); void BroadcastN(AuUInt32 nBroadcast);