[*] Guess I should finalize this for linux. The verbosity of writing a cas in the wait loops is stupid if we arent doing anything special with the bits.

This commit is contained in:
Reece Wilson 2023-09-12 16:12:54 +01:00
parent 00260294b2
commit 4b0a7c651a
4 changed files with 87 additions and 25 deletions

View File

@ -75,9 +75,7 @@ namespace Aurora::Threading::Primitives
AuAtomicAdd(&this->uSleeping_, 1u); AuAtomicAdd(&this->uSleeping_, 1u);
auto state = this->uState_; while (!this->TryLockNoSpin())
while (!(state == 0 &&
AuAtomicCompareExchange<AuUInt32>(&this->uState_, 1, state) == state))
{ {
if (uTimeout != 0) if (uTimeout != 0)
{ {
@ -90,7 +88,7 @@ namespace Aurora::Threading::Primitives
int ret {}; int ret {};
do do
{ {
ret = futex_wait(&this->uState_, state, &tspec); ret = futex_wait(&this->uState_, 1, &tspec);
} }
while (ret == -EINTR); while (ret == -EINTR);
} }
@ -101,7 +99,7 @@ namespace Aurora::Threading::Primitives
do do
{ {
if ((ret = futex_wait(&this->uState_, state)) == 0) if ((ret = futex_wait(&this->uState_, 1)) == 0)
{ {
bStatus = true; bStatus = true;
break; break;
@ -118,8 +116,6 @@ namespace Aurora::Threading::Primitives
RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret) RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret)
} }
state = this->uState_;
} }
AuAtomicSub(&this->uSleeping_, 1u); AuAtomicSub(&this->uSleeping_, 1u);
@ -170,9 +166,7 @@ namespace Aurora::Threading::Primitives
AuAtomicAdd(&this->uSleeping_, 1u); AuAtomicAdd(&this->uSleeping_, 1u);
auto state = this->uState_; while (!this->TryLockNoSpin())
while (!(state == 0 &&
AuAtomicCompareExchange<AuUInt32>(&this->uState_, 1, state) == state))
{ {
int ret {}; int ret {};
@ -180,7 +174,7 @@ namespace Aurora::Threading::Primitives
do do
{ {
if ((ret = futex_wait(&this->uState_, state)) == 0) if ((ret = futex_wait(&this->uState_, 1)) == 0)
{ {
bStatus = true; bStatus = true;
break; break;
@ -196,8 +190,6 @@ namespace Aurora::Threading::Primitives
while (ret == -EINTR); while (ret == -EINTR);
RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret) RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret)
state = this->uState_;
} }
AuAtomicSub(&this->uSleeping_, 1u); AuAtomicSub(&this->uSleeping_, 1u);

View File

@ -101,9 +101,7 @@ namespace Aurora::Threading::Primitives
Time::monoabsns2ts(&tspec, uEnd); Time::monoabsns2ts(&tspec, uEnd);
} }
auto state = this->state_; while (!this->TryLockNoSpin())
while (!(state == 0 &&
AuAtomicCompareExchange<AuUInt32>(&this->state_, 1, state) == state))
{ {
if (uTimeout != 0) if (uTimeout != 0)
{ {
@ -116,7 +114,7 @@ namespace Aurora::Threading::Primitives
int ret {}; int ret {};
do do
{ {
ret = futex_wait(&this->state_, state, &tspec); ret = futex_wait(&this->state_, 1, &tspec);
} }
while (ret == -EINTR); while (ret == -EINTR);
} }
@ -127,7 +125,7 @@ namespace Aurora::Threading::Primitives
do do
{ {
if ((ret = futex_wait(&this->state_, state)) == 0) if ((ret = futex_wait(&this->state_, 1)) == 0)
{ {
bStatus = true; bStatus = true;
break; break;
@ -144,8 +142,84 @@ namespace Aurora::Threading::Primitives
RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret) RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret)
} }
}
state = this->state_; AuAtomicSub(&this->dwSleeping_, 1u);
return true;
}
bool MutexImpl::LockAbsNS(AuUInt64 uTimeout)
{
struct timespec tspec;
if (this->TryLockNoSpin())
{
return true;
}
if (uTimeout != 0)
{
Time::monoabsns2ts(&tspec, uTimeout);
}
if (ThrdCfg::gPreferLinuxPrimitivesFutexNoSpin)
{
if (this->TryLockNoSpin())
{
return true;
}
}
else
{
if (this->TryLockHeavy())
{
return true;
}
}
AuAtomicAdd(&this->dwSleeping_, 1u);
while (!this->TryLockNoSpin())
{
if (uTimeout != 0)
{
if (Time::SteadyClockNS() >= uTimeout)
{
AuAtomicSub(&this->dwSleeping_, 1u);
return false;
}
int ret {};
do
{
ret = futex_wait(&this->state_, 1, &tspec);
}
while (ret == -EINTR);
}
else
{
int ret {};
bool bStatus {};
do
{
if ((ret = futex_wait(&this->state_, 1)) == 0)
{
bStatus = true;
break;
}
if (ret == -EAGAIN)
{
bStatus = true;
break;
}
}
while (ret == -EINTR);
RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret)
}
} }
AuAtomicSub(&this->dwSleeping_, 1u); AuAtomicSub(&this->dwSleeping_, 1u);

View File

@ -20,6 +20,7 @@ namespace Aurora::Threading::Primitives
void SlowLock() override; void SlowLock() override;
bool LockMS(AuUInt64 timeout) override; bool LockMS(AuUInt64 timeout) override;
bool LockNS(AuUInt64 timeout) override; bool LockNS(AuUInt64 timeout) override;
bool LockAbsNS(AuUInt64 uTimeout);
void Unlock() override; void Unlock() override;
auline bool TryLockNoSpin(); auline bool TryLockNoSpin();

View File

@ -192,10 +192,7 @@ namespace Aurora::Threading::Primitives
AuAtomicAdd<AuUInt32>(&this->dwSleeping_, 1u); AuAtomicAdd<AuUInt32>(&this->dwSleeping_, 1u);
auto old = this->dwState_; while (!this->TryLockNoSpin())
//!tryLock (with old in a scope we can access)
while (!((old != 0) &&
(AuAtomicCompareExchange(&this->dwState_, old - 1, old) == old)))
{ {
if (uTimeout != 0) if (uTimeout != 0)
{ {
@ -236,8 +233,6 @@ namespace Aurora::Threading::Primitives
RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "semaphore wait failed: {}", ret) RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "semaphore wait failed: {}", ret)
} }
old = this->dwState_;
} }
AuAtomicSub<AuUInt32>(&this->dwSleeping_, 1u); AuAtomicSub<AuUInt32>(&this->dwSleeping_, 1u);