[+] AuUInt32 GetTotalSpinCountTimeout()

[*] Fixup FutexWaitable
This commit is contained in:
Reece Wilson 2023-08-20 09:47:31 +01:00
parent 2d2d66f410
commit f1a08d25e7
5 changed files with 49 additions and 20 deletions

View File

@ -14,4 +14,5 @@ namespace Aurora::Threading
AUKN_SYM void SetSpinCountTimeout(AuUInt8 uTimeout);
AUKN_SYM AuUInt8 GetSpinCountTimeout();
AUKN_SYM void SetThreadLocalAdditionalSpinCountTimeout(AuUInt8 uTimeout);
AUKN_SYM AuUInt32 GetTotalSpinCountTimeout();
}

View File

@ -171,7 +171,7 @@ namespace Aurora::Threading::Waitables
auline bool TryLock2()
{
for (AU_ITERATE_N(i, AuUInt(1u) << AuUInt(Threading::GetSpinCountTimeout())))
for (AU_ITERATE_N(i, AuUInt(GetTotalSpinCountTimeout())))
{
#if defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64)
_mm_pause();

View File

@ -30,7 +30,7 @@ namespace Aurora::Threading::Waitables
}
#if defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64)
for (AU_ITERATE_N(i, AuUInt(1u) << AuUInt(Threading::GetSpinCountTimeout())))
for (AU_ITERATE_N(i, AuUInt(GetTotalSpinCountTimeout())))
{
_mm_pause();

View File

@ -19,28 +19,33 @@ namespace Aurora::Threading::Waitables
AU_NO_COPY_NO_MOVE(FutexWaitable);
inline bool TryLockNoSpin()
{
return AuAtomicTestAndSet(&this->uAtomicState, 0u) == 0;
}
inline bool TryLock() override
{
if (AuAtomicTestAndSet(&this->uAtomicState, 0u))
if (TryLockNoSpin())
{
return true;
}
#if defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64)
for (AU_ITERATE_N(i, AuUInt(1u) << AuUInt(Threading::GetSpinCountTimeout())))
for (AU_ITERATE_N(i, AuUInt(GetTotalSpinCountTimeout())))
{
_mm_pause();
if (AuAtomicTestAndSet(&this->uAtomicState, 0u))
if (TryLockNoSpin())
{
return true;
}
}
#else
static const AuUInt32 kRef { 1 };
if (TryWaitOnAddress(&this->uAtomicState, &kRef, sizeof(kRef)))
if (TryWaitOnAddress((void *)&this->uAtomicState, &kRef, sizeof(kRef)))
{
if (AuAtomicTestAndSet(&this->uAtomicState, 0u))
if (TryLockNoSpin())
{
return true;
}
@ -62,11 +67,15 @@ namespace Aurora::Threading::Waitables
inline void Unlock() override
{
#if defined(AURORA_COMPILER_MSVC)
this->uAtomicState = 0;
#else
__sync_lock_release(&this->uAtomicState);
#endif
if (auto uSleeping = this->uAtomicSleeping)
{
WakeOnAddress(&this->uAtomicState);
WakeOnAddress((const void *)&this->uAtomicState);
}
}
@ -74,10 +83,15 @@ namespace Aurora::Threading::Waitables
{
static const AuUInt32 kRef { 1 };
while (!TryLock())
if (TryLock())
{
return;
}
while (!TryLockNoSpin())
{
AuAtomicAdd(&this->uAtomicSleeping, 1u);
WaitOnAddress(&this->uAtomicState, &kRef, sizeof(kRef), 0);
WaitOnAddress((void *)&this->uAtomicState, &kRef, sizeof(kRef), 0);
AuAtomicSub(&this->uAtomicSleeping, 1u);
}
}
@ -95,24 +109,25 @@ namespace Aurora::Threading::Waitables
inline bool LockNS(AuUInt64 qwTimeout) override
{
static const AuUInt32 kRef { 1 };
if (AuAtomicTestAndSet(&this->uAtomicState, 0u))
if (TryLock())
{
return true;
}
auto qwEndTime = Time::SteadyClockNS() + qwTimeout;
while (!TryLock())
while (!TryLockNoSpin())
{
bool bStatus {};
AuAtomicAdd(&this->uAtomicSleeping, 1u);
bStatus = WaitOnAddressSteady(&this->uAtomicState, &kRef, sizeof(kRef), qwEndTime);
bStatus = WaitOnAddressSteady((void *)&this->uAtomicState, &kRef, sizeof(kRef), qwEndTime);
AuAtomicSub(&this->uAtomicSleeping, 1u);
if (!bStatus)
{
return TryLock();
return TryLockNoSpin();
}
}
@ -122,29 +137,30 @@ namespace Aurora::Threading::Waitables
inline bool LockAbsNS(AuUInt64 qwTimeoutAbs) override
{
static const AuUInt32 kRef { 1 };
if (AuAtomicTestAndSet(&this->uAtomicState, 0u))
if (TryLock())
{
return true;
}
while (!TryLock())
while (!TryLockNoSpin())
{
bool bStatus {};
AuAtomicAdd(&this->uAtomicSleeping, 1u);
bStatus = WaitOnAddressSteady(&this->uAtomicState, &kRef, sizeof(kRef), qwTimeoutAbs);
bStatus = WaitOnAddressSteady((void *)&this->uAtomicState, &kRef, sizeof(kRef), qwTimeoutAbs);
AuAtomicSub(&this->uAtomicSleeping, 1u);
if (!bStatus)
{
return TryLock();
return TryLockNoSpin();
}
}
return true;
}
AuUInt32 uAtomicState {};
AuUInt32 uAtomicSleeping {};
volatile AuUInt32 uAtomicState {};
volatile AuUInt32 uAtomicSleeping {};
};
}

View File

@ -25,6 +25,18 @@ namespace Aurora::Threading
gHasThreadLocalTimeout = 1;
tlSpinCountLocal = uTimeout;
}
AUKN_SYM AuUInt32 GetTotalSpinCountTimeout()
{
AuUInt32 uCount {};
uCount = 1u << AuUInt32(gRuntimeConfig.threadingConfig.uSpinLoopPowerA);
if (gHasThreadLocalTimeout)
{
uCount += 1u << AuUInt32(tlSpinCountLocal);
}
return uCount;
}
}
namespace Aurora::Threading::Primitives