[*] 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 #else
return DoTryIf([=]() return DoTryIf([=]()
{ {
return !AuAtomicTestAndSet(&this->lock_.uWaitCount, 0); return this->TryLockNoSpin();
}); });
#endif #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() void Win32ConditionMutex::Lock()
{ {
#if defined(AURORA_FORCE_SRW_LOCKS) #if defined(AURORA_FORCE_SRW_LOCKS)
::AcquireSRWLockExclusive(&this->lock_); ::AcquireSRWLockExclusive(&this->lock_);
#else #else
while (!TryLock())
if (this->TryLock())
{
return;
}
while (!this->TryLockNoSpin())
{ {
auto &uValueRef = this->lock_.uWaitCount; auto &uValueRef = this->lock_.uWaitCount;
auto uValue = uValueRef | 1; auto uValue = uValueRef | 1;

View File

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

View File

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

View File

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