[*] Optimize Linux semaphore
This commit is contained in:
parent
b6ff6b1623
commit
2a1556d80c
@ -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()
|
||||||
|
@ -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_ {};
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user