[*] Reoptimize semaphore wait paths

This commit is contained in:
Reece Wilson 2023-08-22 15:28:09 +01:00
parent 03a3532a20
commit a4d317a48d
3 changed files with 97 additions and 2 deletions

View File

@ -68,7 +68,7 @@ namespace Aurora::Threading::Primitives
AuUInt64 uStart {}; AuUInt64 uStart {};
AuUInt64 uEnd {}; AuUInt64 uEnd {};
if (this->TryLockHeavy()) if (this->TryLockNoSpin())
{ {
return true; return true;
} }
@ -84,6 +84,11 @@ namespace Aurora::Threading::Primitives
Time::monoabsns2ts(&tspec, uEnd); Time::monoabsns2ts(&tspec, uEnd);
} }
if (this->TryLockHeavy())
{
return true;
}
AuAtomicAdd<AuUInt32>(&this->dwSleeping_, 1u); AuAtomicAdd<AuUInt32>(&this->dwSleeping_, 1u);
auto old = this->dwState_; auto old = this->dwState_;
@ -137,6 +142,89 @@ namespace Aurora::Threading::Primitives
AuAtomicSub<AuUInt32>(&this->dwSleeping_, 1u); AuAtomicSub<AuUInt32>(&this->dwSleeping_, 1u);
return true; return true;
} }
bool SemaphoreImpl::LockAbsMS(AuUInt64 timeout)
{
return this->LockAbsNS(AuMSToNS<AuUInt64>(timeout));
}
bool SemaphoreImpl::LockAbsNS(AuUInt64 uTimeout)
{
AuUInt64 uEnd {};
if (this->TryLockNoSpin())
{
return true;
}
errno = 0;
struct timespec tspec;
if (uTimeout != 0)
{
uEnd = uTimeout;
Time::monoabsns2ts(&tspec, uEnd);
}
if (this->TryLockHeavy())
{
return true;
}
AuAtomicAdd<AuUInt32>(&this->dwSleeping_, 1u);
auto old = this->dwState_;
//!tryLock (with old in a scope we can access)
while (!((old != 0) &&
(AuAtomicCompareExchange(&this->dwState_, old - 1, old) == old)))
{
if (uTimeout != 0)
{
if (Time::SteadyClockNS() >= uEnd)
{
AuAtomicSub<AuUInt32>(&this->dwSleeping_, 1u);
return false;
}
int ret {};
do
{
ret = futex_wait(&this->dwState_, 0, &tspec);
}
while (ret == EINTR);
}
else
{
int ret {};
bool bStatus {};
do
{
if ((ret = futex_wait(&this->dwState_, 0)) == 0)
{
bStatus = true;
continue;
}
if (ret == EAGAIN || errno == EAGAIN)
{
bStatus = true;
continue;
}
}
while (ret == EINTR);
RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "semaphore wait failed: {}", ret)
}
old = this->dwState_;
}
AuAtomicSub<AuUInt32>(&this->dwSleeping_, 1u);
return true;
}
void SemaphoreImpl::Lock() void SemaphoreImpl::Lock()
{ {

View File

@ -19,6 +19,8 @@ namespace Aurora::Threading::Primitives
bool TryLock() override; bool TryLock() override;
bool LockMS(AuUInt64 timeout) override; bool LockMS(AuUInt64 timeout) override;
bool LockNS(AuUInt64 timeout) override; bool LockNS(AuUInt64 timeout) override;
bool LockAbsMS(AuUInt64 timeout) override;
bool LockAbsNS(AuUInt64 timeout) override;
void Lock() override; void Lock() override;
void Unlock(AuUInt16 count) override; void Unlock(AuUInt16 count) override;
void Unlock() override; void Unlock() override;

View File

@ -67,7 +67,7 @@ namespace Aurora::Threading::Primitives
bool SemaphoreImpl::LockNS(AuUInt64 uTimeout) bool SemaphoreImpl::LockNS(AuUInt64 uTimeout)
{ {
if (this->TryLockHeavy()) if (this->TryLockNoSpin())
{ {
return true; return true;
} }
@ -75,6 +75,11 @@ namespace Aurora::Threading::Primitives
AuUInt64 uStart = AuTime::SteadyClockNS(); AuUInt64 uStart = AuTime::SteadyClockNS();
AuUInt64 uEnd = uTimeout ? uStart + uTimeout : 0; AuUInt64 uEnd = uTimeout ? uStart + uTimeout : 0;
if (this->TryLockHeavy())
{
return true;
}
if (gUseNativeWaitSemapahore) if (gUseNativeWaitSemapahore)
{ {
AuUInt32 uYieldCounter {}; AuUInt32 uYieldCounter {};