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

View File

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