[+] AuUInt32 GetTotalSpinCountTimeout()
[*] Fixup FutexWaitable
This commit is contained in:
parent
2d2d66f410
commit
f1a08d25e7
@ -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();
|
||||
}
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 {};
|
||||
};
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user