[*] NT Semaphore optimization

This commit is contained in:
Reece Wilson 2023-08-24 13:55:31 +01:00
parent 935d1b6ab2
commit 100964ac87
2 changed files with 86 additions and 9 deletions

View File

@ -60,6 +60,11 @@ namespace Aurora::Threading::Primitives
}
}
AuUInt32 *SemaphoreImpl::GetSleepCounter()
{
return (AuUInt32 *)&this->var;
}
bool SemaphoreImpl::LockMS(AuUInt64 uTimeout)
{
return LockNS(AuMSToNS<AuUInt64>(uTimeout));
@ -84,11 +89,17 @@ namespace Aurora::Threading::Primitives
{
AuUInt32 uYieldCounter {};
auto old = this->dwState_;
//!tryLock (with old in a scope we can access)
while (!((old != 0) &&
(AuAtomicCompareExchange(&this->dwState_, old - 1, old) == old)))
{
if (!InternalLTSWaitOnAddressHighRes(&this->dwState_, &old, sizeof(this->dwState_), uEnd))
static const AuUInt32 kExpect { 0 };
auto pCounter = GetSleepCounter();
AuAtomicAdd(pCounter, 1u);
bool bStatus = InternalLTSWaitOnAddressHighRes(&this->dwState_, (void *)&kExpect, sizeof(kExpect), uEnd);
AuAtomicSub(pCounter, 1u);
if (!bStatus)
{
return false;
}
@ -122,9 +133,69 @@ namespace Aurora::Threading::Primitives
}
this->mutex.Unlock();
return true;
}
}
bool SemaphoreImpl::LockAbsNS(AuUInt64 qwTimeoutAbs)
{
if (this->TryLockHeavy())
{
return true;
}
return true;
if (gUseNativeWaitSemapahore)
{
AuUInt32 uYieldCounter {};
auto old = this->dwState_;
while (!((old != 0) &&
(AuAtomicCompareExchange(&this->dwState_, old - 1, old) == old)))
{
static const AuUInt32 kExpect { 0 };
auto pCounter = GetSleepCounter();
AuAtomicAdd(pCounter, 1u);
bool bStatus = InternalLTSWaitOnAddressHighRes(&this->dwState_, (void *)&kExpect, sizeof(kExpect), qwTimeoutAbs);
AuAtomicSub(pCounter, 1u);
if (!bStatus)
{
return false;
}
old = this->dwState_;
}
return true;
}
else
{
this->mutex.Lock();
while (!TryLockNoSpin())
{
if (qwTimeoutAbs != 0)
{
auto uStart = Time::SteadyClockNS();
if (uStart >= qwTimeoutAbs)
{
this->mutex.Unlock();
return false;
}
var.WaitForSignalNsEx(&this->mutex, qwTimeoutAbs - uStart);
}
else
{
var.WaitForSignalNsEx(&this->mutex, 0);
}
}
this->mutex.Unlock();
return true;
}
}
void SemaphoreImpl::Lock()
@ -138,13 +209,17 @@ namespace Aurora::Threading::Primitives
if (gUseNativeWaitSemapahore)
{
AuAtomicAdd<AuUInt32>(&this->dwState_, count);
if (count == 1)
if (AuAtomicLoad(GetSleepCounter()))
{
pWakeByAddressSingle(&this->dwState_);
}
else
{
pWakeByAddressAll(&this->dwState_);
if (count == 1)
{
pWakeByAddressSingle(&this->dwState_);
}
else
{
pWakeByAddressAll(&this->dwState_);
}
}
}
else

View File

@ -22,6 +22,7 @@ namespace Aurora::Threading::Primitives
bool TryLock() override;
bool LockMS(AuUInt64 timeout) override;
bool LockNS(AuUInt64 timeout) override;
bool LockAbsNS(AuUInt64 qwTimeoutAbs) override;
void Lock() override;
void Unlock(AuUInt16 count) override;
void Unlock() override;
@ -29,6 +30,7 @@ namespace Aurora::Threading::Primitives
auline bool TryLockNoSpin();
auline bool TryLockHeavy();
auline AuUInt32 *GetSleepCounter();
private:
AuUInt32 dwState_ {};
ConditionMutexInternal mutex;