diff --git a/Include/Aurora/Threading/Waitables/FutexCondWaitable.hpp b/Include/Aurora/Threading/Waitables/FutexCondWaitable.hpp index c3294fbb..737d54f9 100644 --- a/Include/Aurora/Threading/Waitables/FutexCondWaitable.hpp +++ b/Include/Aurora/Threading/Waitables/FutexCondWaitable.hpp @@ -169,22 +169,38 @@ namespace Aurora::Threading::Waitables volatile AuUInt32 uAtomicSleeping {}; private: + auline bool TryLock3() + { + auto old = this->uAtomicState; + return ((old != 0 && AuAtomicCompareExchange(&this->uAtomicState, old - 1, old) == old)); + } + auline bool TryLock2() { - for (AU_ITERATE_N(i, AuUInt(GetTotalSpinCountTimeout()))) + if (TryLock3()) { - #if defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64) - _mm_pause(); - #else - Threading::ContextYield(); - #endif + return true; + } - auto old = this->uAtomicState; - if ((old != 0 && AuAtomicCompareExchange(&this->uAtomicState, old - 1, old) == old)) + #if defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64) + AuUInt uCount(GetTotalSpinCountTimeout()); + for (AU_ITERATE_N(i, uCount)) + { + _mm_pause(); + + if (TryLock3()) { return true; } } + #else + static const AuUInt32 kRef { 0 }; + + if (TryWaitOnAddress(&this->uAtomicState, &kRef, sizeof(kRef))) + { + return TryLock3(); + } + #endif return false; } diff --git a/Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp b/Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp index a3917595..e28980e3 100644 --- a/Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp +++ b/Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp @@ -19,23 +19,26 @@ namespace Aurora::Threading::Waitables AU_NO_COPY_NO_MOVE(FutexSemaphoreWaitable); + auline bool TryLockNoSpin() + { + auto uState = this->uAtomicState; + return (uState != 0 && AuAtomicCompareExchange(&this->uAtomicState, uState - 1, uState) == uState); + } + inline bool TryLock() override { + if (TryLockNoSpin()) { - auto uState = this->uAtomicState; - if (uState != 0 && AuAtomicCompareExchange(&this->uAtomicState, uState - 1, uState) == uState) - { - return true; - } + return true; } #if defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64) - for (AU_ITERATE_N(i, AuUInt(GetTotalSpinCountTimeout()))) + AuUInt uCount(GetTotalSpinCountTimeout()); + for (AU_ITERATE_N(i, uCount)) { _mm_pause(); - auto uState = this->uAtomicState; - if (uState != 0 && AuAtomicCompareExchange(&this->uAtomicState, uState - 1, uState) == uState) + if (TryLockNoSpin()) { return true; } @@ -44,11 +47,7 @@ namespace Aurora::Threading::Waitables static const AuUInt32 kRef { 0 }; if (TryWaitOnAddress(&this->uAtomicState, &kRef, sizeof(kRef))) { - auto uState = this->uAtomicState; - if (uState != 0 && AuAtomicCompareExchange(&this->uAtomicState, uState - 1, uState) == uState) - { - return true; - } + return TryLockNoSpin(); } #endif @@ -89,7 +88,12 @@ namespace Aurora::Threading::Waitables { static const AuUInt32 kRef { 0 }; - while (!TryLock()) + if (TryLock()) + { + return; + } + + while (!TryLockNoSpin()) { AuAtomicAdd(&this->uAtomicSleeping, 1u); WaitOnAddress((void *)&this->uAtomicState, &kRef, sizeof(kRef), 0); @@ -111,9 +115,19 @@ namespace Aurora::Threading::Waitables { static const AuUInt32 kRef { 0 }; + if (TryLockNoSpin()) + { + return true; + } + auto qwEndTime = Time::SteadyClockNS() + qwTimeout; - while (!TryLock()) + if (TryLock()) + { + return true; + } + + while (!TryLockNoSpin()) { bool bStatus {}; diff --git a/Include/Aurora/Threading/Waitables/FutexWaitable.hpp b/Include/Aurora/Threading/Waitables/FutexWaitable.hpp index a1ac0ec3..c8c1f5d2 100644 --- a/Include/Aurora/Threading/Waitables/FutexWaitable.hpp +++ b/Include/Aurora/Threading/Waitables/FutexWaitable.hpp @@ -32,7 +32,8 @@ namespace Aurora::Threading::Waitables } #if defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64) - for (AU_ITERATE_N(i, AuUInt(GetTotalSpinCountTimeout()))) + AuUInt uCount(GetTotalSpinCountTimeout()); + for (AU_ITERATE_N(i, uCount)) { _mm_pause(); @@ -110,13 +111,18 @@ namespace Aurora::Threading::Waitables { static const AuUInt32 kRef { 1 }; - if (TryLock()) + if (TryLockNoSpin()) { return true; } auto qwEndTime = Time::SteadyClockNS() + qwTimeout; + if (TryLock()) + { + return true; + } + while (!TryLockNoSpin()) { bool bStatus {};