[*] Optimize Linux semaphore

This commit is contained in:
Reece Wilson 2023-08-17 23:06:02 +01:00
parent b6ff6b1623
commit 2a1556d80c
2 changed files with 25 additions and 11 deletions

View File

@ -14,7 +14,7 @@
namespace Aurora::Threading::Primitives
{
SemaphoreImpl::SemaphoreImpl(long intialValue) : value_(intialValue)
SemaphoreImpl::SemaphoreImpl(long intialValue) : dwState_(intialValue)
{
}
@ -33,12 +33,17 @@ namespace Aurora::Threading::Primitives
return true;
}
bool SemaphoreImpl::TryLockNoSpin()
{
auto old = this->dwState_;
return (old != 0 && AuAtomicCompareExchange(&this->dwState_, old - 1, old) == old);
}
bool SemaphoreImpl::TryLock()
{
return DoTryIf([=]()
{
auto old = this->value_;
return (old != 0 && AuAtomicCompareExchange(&this->value_, old - 1, old) == old);
return this->TryLockNoSpin();
});
}
@ -68,22 +73,25 @@ namespace Aurora::Threading::Primitives
Time::monoabsns2ts(&tspec, uEnd);
}
auto old = this->value_;
AuAtomicAdd<AuUInt32>(&this->dwSleeping_, 1u);
auto old = this->dwState_;
//!tryLock (with old in a scope we can access)
while (!((old != 0) &&
(AuAtomicCompareExchange(&this->value_, old - 1, old) == old)))
(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->value_, 0, &tspec);
ret = futex_wait(&this->dwState_, 0, &tspec);
}
while (ret == EINTR);
}
@ -94,7 +102,7 @@ namespace Aurora::Threading::Primitives
do
{
if ((ret = futex_wait(&this->value_, 0)) == 0)
if ((ret = futex_wait(&this->dwState_, 0)) == 0)
{
bStatus = true;
continue;
@ -112,9 +120,10 @@ namespace Aurora::Threading::Primitives
RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "semaphore wait failed: {}", ret)
}
old = this->value_;
old = this->dwState_;
}
AuAtomicSub<AuUInt32>(&this->dwSleeping_, 1u);
return true;
}
@ -126,8 +135,11 @@ namespace Aurora::Threading::Primitives
void SemaphoreImpl::Unlock(long count)
{
AuAtomicAdd<AuUInt32>(&this->value_, count);
futex_wake(&this->value_, count);
AuAtomicAdd<AuUInt32>(&this->dwState_, count);
if (this->dwSleeping_)
{
futex_wake(&this->dwState_, count);
}
}
void SemaphoreImpl::Unlock()

View File

@ -14,6 +14,7 @@ namespace Aurora::Threading::Primitives
SemaphoreImpl(long intialValue = 0);
~SemaphoreImpl();
bool TryLockNoSpin();
bool HasOSHandle(AuMach &mach) override;
bool HasLockImplementation() override;
bool TryLock() override;
@ -24,6 +25,7 @@ namespace Aurora::Threading::Primitives
void Unlock() override;
private:
AuUInt32 value_ {};
AuUInt32 dwState_ {};
AuUInt32 dwSleeping_ {};
};
}