[*] NT: backport unix optimization - no spin during spurious wake up

This commit is contained in:
Reece Wilson 2023-07-10 13:12:17 +01:00
parent 536522743a
commit a977f0d1b5
4 changed files with 35 additions and 10 deletions

View File

@ -48,17 +48,32 @@ namespace Aurora::Threading::Primitives
#else
return DoTryIf([=]()
{
return !AuAtomicTestAndSet(&this->lock_.uWaitCount, 0);
return this->TryLockNoSpin();
});
#endif
}
bool Win32ConditionMutex::TryLockNoSpin()
{
#if defined(AURORA_FORCE_SRW_LOCKS)
return ::TryAcquireSRWLockExclusive(&this->lock_);
#else
return AuAtomicTestAndSet(&this->lock_.uWaitCount, 0) == 0;
#endif
}
void Win32ConditionMutex::Lock()
{
#if defined(AURORA_FORCE_SRW_LOCKS)
::AcquireSRWLockExclusive(&this->lock_);
#else
while (!TryLock())
if (this->TryLock())
{
return;
}
while (!this->TryLockNoSpin())
{
auto &uValueRef = this->lock_.uWaitCount;
auto uValue = uValueRef | 1;

View File

@ -24,6 +24,7 @@ namespace Aurora::Threading::Primitives
inline HANDLE gKeyedEventHandle { INVALID_HANDLE_VALUE };
// Actually NT5.x
struct NT4Mutex
{
volatile AuUInt32 uWaitCount {}; // yields while bits are high, dec to release one from the semaphore yield
@ -39,6 +40,8 @@ namespace Aurora::Threading::Primitives
auline void Unlock() override;
AuUInt GetOSHandle() override;
auline bool TryLockNoSpin();
#if !defined(AURORA_FORCE_SRW_LOCKS)
NT4Mutex lock_;
#else

View File

@ -48,10 +48,15 @@ namespace Aurora::Threading::Primitives
{
return DoTryIf([=]()
{
return AuAtomicTestAndSet(&this->state_, 0) == 0;
return this->TryLockNoSpin();
});
}
bool MutexImpl::TryLockNoSpin()
{
return AuAtomicTestAndSet(&this->state_, 0) == 0;
}
bool MutexImpl::HasLockImplementation()
{
return true;
@ -77,7 +82,7 @@ namespace Aurora::Threading::Primitives
{
bool returnValue = false;
if (TryLock())
if (this->TryLock())
{
return true;
}
@ -87,7 +92,7 @@ namespace Aurora::Threading::Primitives
if (gUseNativeWaitMutex)
{
while (!TryLock())
while (!this->TryLockNoSpin())
{
auto &uValueRef = this->state_;
auto uValue = uValueRef | 1;
@ -110,13 +115,13 @@ namespace Aurora::Threading::Primitives
::AcquireSRWLockShared(&this->atomicHolder_);
BOOL status = false;
while (!this->TryLock())
while (!this->TryLockNoSpin())
{
AuUInt32 uTimeoutMS = INFINITE;
if (uTimeout != 0)
{
uStartTime = Time::SteadyClockNS();
auto uStartTime = Time::SteadyClockNS();
if (uStartTime >= uEndTime)
{
goto exitWin32;
@ -146,7 +151,7 @@ namespace Aurora::Threading::Primitives
if (!uTimeout)
{
while (!TryLock())
while (!this->TryLockNoSpin())
{
auto &uValueRef = this->state_;
auto uValue = uValueRef | 1;
@ -169,14 +174,14 @@ namespace Aurora::Threading::Primitives
auto uEndTimeWall = AuTime::CurrentClockNS() + uTimeout;
bool bFailed {};
while (bFailed || (!TryLock()))
while (bFailed || (!this->TryLockNoSpin()))
{
auto uValue = uValueRef | 1;
if (!bFailed &&
AuTime::SteadyClockNS() >= uEndTimeSteady)
{
returnValue = TryLock();
returnValue = this->TryLock();
break;
}

View File

@ -22,6 +22,8 @@ namespace Aurora::Threading::Primitives
bool LockNS(AuUInt64 timeout) override;
void Unlock() override;
auline bool TryLockNoSpin();
private:
#if defined(AURORA_FORCE_SRW_LOCKS)
SRWLOCK atomicHolder_;