diff --git a/Include/Aurora/Runtime.hpp b/Include/Aurora/Runtime.hpp index a65ac2cc..d05a7624 100644 --- a/Include/Aurora/Runtime.hpp +++ b/Include/Aurora/Runtime.hpp @@ -380,7 +380,8 @@ namespace Aurora #else AuUInt64 bPreferEmulatedWakeOnAddress : 1 { !AuBuild::kIsNtDerived /*everybody else requires us to hit the kernel. */ }; #endif - AuUInt64 bPreferWaitOnAddressAlwaysSpin : 1 { true }; // ..., if emulated! if double-spinning under higher level locks, disable me. + AuUInt64 bPreferWaitOnAddressAlwaysSpin : 1 { true }; // ..., if emulated! if double-spinning under higher level locks, disable me. + AuUInt64 bPreferWaitOnAddressAlwaysSpinNative : 1 { false }; // ..., if not emulated! noting that most kernels and user-schedulers will spin for you AuUInt64 bPreferRWLockReadLockSpin : 1 { true }; AuUInt64 bUWPNanosecondEmulationCheckFirst : 1 { false }; AuUInt64 uUWPNanosecondEmulationMaxYields : 7 { 12 }; diff --git a/Include/Aurora/Threading/Waitables/FutexCondWaitable.hpp b/Include/Aurora/Threading/Waitables/FutexCondWaitable.hpp index a52d2ffb..4612bac9 100644 --- a/Include/Aurora/Threading/Waitables/FutexCondWaitable.hpp +++ b/Include/Aurora/Threading/Waitables/FutexCondWaitable.hpp @@ -184,37 +184,12 @@ namespace Aurora::Threading::Waitables return true; } - #if (defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64)) && !defined(AURORA_RUNTIME_FORCE_ADAPTIVE_FUTEX) - AuUInt uCount(GetTotalSpinCountTime()); - #if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) - auto uPerfCounter = __rdtsc() + uCount; - while (__rdtsc() < uPerfCounter) - #else - for (AU_ITERATE_N(i, uCount)) - #endif - { - #if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) - _mm_pause(); - _mm_pause(); - _mm_pause(); - _mm_pause(); - #else - // TBD - #endif - - if (TryLock3()) - { - return true; - } - } - #else static const AuUInt32 kRef { 0 }; - if (TryWaitOnAddress(&this->uAtomicState, &kRef, sizeof(kRef))) + if (TryWaitOnAddress((const void *)&this->uAtomicState, &kRef, sizeof(kRef))) { return TryLock3(); } - #endif return false; } @@ -227,7 +202,7 @@ namespace Aurora::Threading::Waitables { bool bStatus {}; - bStatus = WaitOnAddressSteady((void *)&this->uAtomicState, &kRef, sizeof(kRef), qwTimeout); + bStatus = WaitOnAddressSteady((const void *)&this->uAtomicState, &kRef, sizeof(kRef), qwTimeout, true); if (!bStatus) { diff --git a/Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp b/Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp index dcd43226..7098e828 100644 --- a/Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp +++ b/Include/Aurora/Threading/Waitables/FutexSemaphoreWaitable.hpp @@ -32,36 +32,11 @@ namespace Aurora::Threading::Waitables return true; } - #if (defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64)) && !defined(AURORA_RUNTIME_FORCE_ADAPTIVE_FUTEX) - AuUInt uCount(GetTotalSpinCountTime()); - #if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) - auto uPerfCounter = __rdtsc() + uCount; - while (__rdtsc() < uPerfCounter) - #else - for (AU_ITERATE_N(i, uCount)) - #endif - { - #if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) - _mm_pause(); - _mm_pause(); - _mm_pause(); - _mm_pause(); - #else - // TBD - #endif - - if (TryLockNoSpin()) - { - return true; - } - } - #else static const AuUInt32 kRef { 0 }; - if (TryWaitOnAddress(&this->uAtomicState, &kRef, sizeof(kRef))) + if (TryWaitOnAddress((const void *)&this->uAtomicState, &kRef, sizeof(kRef))) { return TryLockNoSpin(); } - #endif return false; } @@ -108,7 +83,7 @@ namespace Aurora::Threading::Waitables while (!TryLockNoSpin()) { AuAtomicAdd(&this->uAtomicSleeping, 1u); - WaitOnAddress((void *)&this->uAtomicState, &kRef, sizeof(kRef), 0); + WaitOnAddress((const void *)&this->uAtomicState, &kRef, sizeof(kRef), 0, true); AuAtomicSub(&this->uAtomicSleeping, 1u); } } @@ -144,7 +119,7 @@ namespace Aurora::Threading::Waitables bool bStatus {}; AuAtomicAdd(&this->uAtomicSleeping, 1u); - bStatus = WaitOnAddressSteady((void *)&this->uAtomicState, &kRef, sizeof(kRef), qwEndTime); + bStatus = WaitOnAddressSteady((const void *)&this->uAtomicState, &kRef, sizeof(kRef), qwEndTime, true); AuAtomicSub(&this->uAtomicSleeping, 1u); if (!bStatus) @@ -165,7 +140,7 @@ namespace Aurora::Threading::Waitables bool bStatus {}; AuAtomicAdd(&this->uAtomicSleeping, 1u); - bStatus = WaitOnAddressSteady((void *)&this->uAtomicState, &kRef, sizeof(kRef), qwTimeoutAbs); + bStatus = WaitOnAddressSteady((const void *)&this->uAtomicState, &kRef, sizeof(kRef), qwTimeoutAbs, true); AuAtomicSub(&this->uAtomicSleeping, 1u); if (!bStatus) diff --git a/Include/Aurora/Threading/Waitables/FutexWaitable.hpp b/Include/Aurora/Threading/Waitables/FutexWaitable.hpp index 32d90cfc..df736e14 100644 --- a/Include/Aurora/Threading/Waitables/FutexWaitable.hpp +++ b/Include/Aurora/Threading/Waitables/FutexWaitable.hpp @@ -31,39 +31,14 @@ namespace Aurora::Threading::Waitables return true; } - #if (defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64)) && !defined(AURORA_RUNTIME_FORCE_ADAPTIVE_FUTEX) - AuUInt uCount(GetTotalSpinCountTime()); - #if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) - auto uPerfCounter = __rdtsc() + uCount; - while (__rdtsc() < uPerfCounter) - #else - for (AU_ITERATE_N(i, uCount)) - #endif - { - #if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) - _mm_pause(); - _mm_pause(); - _mm_pause(); - _mm_pause(); - #else - // TBD - #endif - - if (TryLockNoSpin()) - { - return true; - } - } - #else static const AuUInt32 kRef { 1 }; - if (TryWaitOnAddress((void *)&this->uAtomicState, &kRef, sizeof(kRef))) + if (TryWaitOnAddress((const void *)&this->uAtomicState, &kRef, sizeof(kRef))) { if (TryLockNoSpin()) { return true; } } - #endif return false; } @@ -100,7 +75,7 @@ namespace Aurora::Threading::Waitables while (!TryLockNoSpin()) { AuAtomicAdd(&this->uAtomicSleeping, 1u); - WaitOnAddress((void *)&this->uAtomicState, &kRef, sizeof(kRef), 0); + WaitOnAddress((const void *)&this->uAtomicState, &kRef, sizeof(kRef), 0, true); AuAtomicSub(&this->uAtomicSleeping, 1u); } } @@ -136,7 +111,7 @@ namespace Aurora::Threading::Waitables bool bStatus {}; AuAtomicAdd(&this->uAtomicSleeping, 1u); - bStatus = WaitOnAddressSteady((void *)&this->uAtomicState, &kRef, sizeof(kRef), qwEndTime); + bStatus = WaitOnAddressSteady((const void *)&this->uAtomicState, &kRef, sizeof(kRef), qwEndTime, true); AuAtomicSub(&this->uAtomicSleeping, 1u); if (!bStatus) @@ -162,7 +137,7 @@ namespace Aurora::Threading::Waitables bool bStatus {}; AuAtomicAdd(&this->uAtomicSleeping, 1u); - bStatus = WaitOnAddressSteady((void *)&this->uAtomicState, &kRef, sizeof(kRef), qwTimeoutAbs); + bStatus = WaitOnAddressSteady((const void *)&this->uAtomicState, &kRef, sizeof(kRef), qwTimeoutAbs, true); AuAtomicSub(&this->uAtomicSleeping, 1u); if (!bStatus) diff --git a/Include/Aurora/Threading/WakeOnAddress.hpp b/Include/Aurora/Threading/WakeOnAddress.hpp index a5ae04c5..bc6ebc40 100644 --- a/Include/Aurora/Threading/WakeOnAddress.hpp +++ b/Include/Aurora/Threading/WakeOnAddress.hpp @@ -4,6 +4,25 @@ File: WakeOnAddress.hpp Date: 2023-3-11 Author: Reece + Note: In emulation mode (*): + 1: Wakes occur in FIFO order + 2: uWordSize can be any length not exceeding 32 bytes + otherwise + 1: Wakes are orderless + 2: uWordSize must be less than or equal to 8 bytes + 3: only the least significant 32bits are guaranteed to be used as wake signals + + * By default: UNIXes and targets below/inc Windows 7 will be in userland emulation mode for performance reasons. + * Linux and other targets can directly interface with their futex interface under a smaller wrapper; + * however, these applications are limited to internal synchronization primitives. The added bloat + * of the WaitOnAddress/FUTEX/atomic wait emulation layer improves performance in real world dumb + * code with spurious wakes, odd word sizes, and pointer alignments. Not to mention some targets + * are stuck with semaphores or condition variables to start off with, and therefore need this + * for the sake of porting modern applications. The aforementioned synchronization primitives + * are written with OS specific optimizations in mind, and therefore consider emulation bloat. + * bPreferEmulatedWakeOnAddress disables the emulation layer, if theres a reasonable native + * interfaces available. + * Defer to ThreadingConfig::bPreferEmulatedWakeOnAddress = !AuBuild::kIsNtDerived ***/ #pragma once @@ -20,15 +39,17 @@ namespace Aurora::Threading const void *pCompareAddress, AuUInt8 uWordSize); - // Relative timeout variant of nanosecond resolution WoA. nanoseconds in steady clock time. 0 = indefinite + // Relative timeout variant of nanosecond resolution WoA. 0 = indefinite AUKN_SYM bool WaitOnAddress(const void *pTargetAddress, const void *pCompareAddress, AuUInt8 uWordSize, - AuUInt64 qwNanoseconds); + AuUInt64 qwNanoseconds, + AuOptional optAlreadySpun = {} /*hint: do not spin before switching. subject to global config.*/); // Absolute timeout variant of nanosecond resolution WoA. Nanoseconds are in steady clock time. 0 = indefinite AUKN_SYM bool WaitOnAddressSteady(const void *pTargetAddress, const void *pCompareAddress, AuUInt8 uWordSize, - AuUInt64 qwNanoseconds); + AuUInt64 qwNanoseconds, + AuOptional optAlreadySpun = {} /*hint: do not spin before switching. subject to global config.*/); } \ No newline at end of file diff --git a/Source/Threading/AuWakeOnAddress.cpp b/Source/Threading/AuWakeOnAddress.cpp index 42bc8b6f..85e0fe5b 100644 --- a/Source/Threading/AuWakeOnAddress.cpp +++ b/Source/Threading/AuWakeOnAddress.cpp @@ -112,7 +112,7 @@ namespace Aurora::Threading if (state.qwNanosecondsAbs) { - if (!WaitBuffer::From(this->pAddress, this->uSize).Compare(state)) + if (!WaitBuffer::Compare(this->pAddress, this->uSize, state)) { return true; } @@ -122,7 +122,7 @@ namespace Aurora::Threading while (uNow < uEndTime) { - if (!WaitBuffer::From(this->pAddress, this->uSize).Compare(state)) + if (!WaitBuffer::Compare(this->pAddress, this->uSize, state)) { return true; } @@ -138,11 +138,11 @@ namespace Aurora::Threading uNow = AuTime::SteadyClockNS(); } - return !WaitBuffer::From(this->pAddress, this->uSize).Compare(state); + return !WaitBuffer::Compare(this->pAddress, this->uSize, state); } else { - while (WaitBuffer::From(this->pAddress, this->uSize).Compare(state)) + while (WaitBuffer::Compare(this->pAddress, this->uSize, state)) { this->variable.WaitForSignalNsEx(&this->mutex, 0); } @@ -215,6 +215,28 @@ namespace Aurora::Threading return AuMove(wait); } + bool WaitBuffer::Compare(const void *pBuf, AuUInt8 uSize, WaitState &state) + { + if (!state.uDownsizeMask) + { + return AuMemcmp(pBuf, state.compare.buffer, AuMin(uSize, state.compare.uSize)) == 0; + } + else + { + auto uMask = state.uDownsizeMask.value(); + + auto &uSrcWord = *AuReinterpretCast(pBuf); + auto &uCmpWord = *AuReinterpretCast(state.compare.buffer); + + return (uSrcWord & uMask) == (uCmpWord & uMask); + } + } + + bool WaitBuffer::Compare(const void *pBuf, AuUInt8 uSize, const void *pBuf2) + { + return AuMemcmp(pBuf, pBuf2, uSize) == 0; + } + bool WaitBuffer::Compare(const void *pBuf) { return AuMemcmp(this->buffer, pBuf, this->uSize) == 0; @@ -230,8 +252,8 @@ namespace Aurora::Threading { auto uMask = state.uDownsizeMask.value(); - auto &uSrcWord = *AuReinterpretCast(this->buffer); - auto &uCmpWord = *AuReinterpretCast(state.compare.buffer); + auto &uSrcWord = *AuReinterpretCast(this->buffer); + auto &uCmpWord = *AuReinterpretCast(state.compare.buffer); return (uSrcWord & uMask) == (uCmpWord & uMask); } @@ -406,7 +428,7 @@ namespace Aurora::Threading ) { WaitState state; - SysAssertDbg(uWordSize <= 8); + SysAssertDbg(uWordSize <= 32); auto pWaitEntry = gProcessWaitables.WaitBufferFrom(pTargetAddress, uWordSize); state.compare = WaitBuffer::From(pCompareAddress, uWordSize); @@ -524,7 +546,8 @@ namespace Aurora::Threading AuUInt8 uWordSize, AuUInt64 uAbsTimeSteadyClock, AuUInt64 uRelativeNanoseconds, - AuOptional uAbsTimeAltClock /* hint */) + AuOptional uAbsTimeAltClock /* hint */, + bool bSpun = false) { #if defined(AURORA_IS_MODERNNT_DERIVED) @@ -547,7 +570,7 @@ namespace Aurora::Threading { if (uAbsTimeSteadyClock <= uNow) { - return !WaitBuffer::From(pCompareAddress, uWordSize).Compare(pTargetAddress); + return !expect.Compare(pTargetAddress); } word.QuadPart = -(AuInt64(uAbsTimeSteadyClock - uNow) / 100ull); @@ -589,7 +612,7 @@ namespace Aurora::Threading if (iDelta <= 0) { - return !WaitBuffer::From(pCompareAddress, uWordSize).Compare(pTargetAddress); + return !WaitBuffer::Compare(pCompareAddress, uWordSize, pTargetAddress); } uRelativeNanoseconds = iDelta; @@ -604,11 +627,14 @@ namespace Aurora::Threading { // take a copy auto expect = WaitBuffer::From(pCompareAddress, uWordSize); - + // first: cpu spin to avoid the kernel all together - if (TryWaitOnAddress((void *)pTargetAddress, (void *)pCompareAddress, uWordSize)) + if (!bSpun) { - return true; + if (TryWaitOnAddress((void *)pTargetAddress, (void *)pCompareAddress, uWordSize)) + { + return true; + } } // second: yield @@ -637,8 +663,11 @@ namespace Aurora::Threading // first: wait on the address with an ms scale timeout (void)pWaitOnAddress((void *)pTargetAddress, (void *)pCompareAddress, uWordSize, uMS); + // take a copy + auto expect = WaitBuffer::From(pCompareAddress, uWordSize); + // never trust the error value/status provided by wait addresses - instead, do a quick compare - if (!WaitBuffer::From(pCompareAddress, uWordSize).Compare(pTargetAddress)) + if (!expect.Compare(pTargetAddress)) { // best case: we woke up during the ms-res waitonaddress return true; @@ -651,9 +680,9 @@ namespace Aurora::Threading { uMS = AuNSToMS(uAbsTimeSteadyClock - uNow); - if (Primitives::DoTryIf([=]() + if (Primitives::DoTryIf([&]() { - return !WaitBuffer::From(pCompareAddress, uWordSize).Compare(pTargetAddress); + return !expect.Compare(pTargetAddress); })) { // hit it within the span of 1 << SpinLoopPowerA SMT stalls @@ -722,14 +751,14 @@ namespace Aurora::Threading #endif - return !WaitBuffer::From(pCompareAddress, uWordSize).Compare(pTargetAddress); + return !WaitBuffer::Compare(pCompareAddress, uWordSize, pTargetAddress); } static void RunOSWaitOnAddressNoTimedNoErrors(const void *pTargetAddress, const void *pCompareAddress, WaitState &state) { - while (WaitBuffer::From(pTargetAddress, state.uWordSize).Compare(state)) + while (WaitBuffer::Compare(pTargetAddress, state.uWordSize, state)) { if (!RunOSWaitOnAddressNoTimed(pTargetAddress, pCompareAddress, state.uWordSize)) { @@ -739,16 +768,17 @@ namespace Aurora::Threading } static bool RunOSWaitOnAddressTimedSteady(const void *pTargetAddress, - const void *pCompareAddress, - WaitState &state) + const void *pCompareAddress, + WaitState &state, + bool bSpun = false) { - if (!WaitBuffer::From(pTargetAddress, state.uWordSize).Compare(state)) + if (!WaitBuffer::Compare(pTargetAddress, state.uWordSize, state)) { return true; } - (void)RunOSWaitOnAddressTimed(pTargetAddress, pCompareAddress, state.uWordSize, state.qwNanosecondsAbs.value(), { }, { }); - return !WaitBuffer::From(pTargetAddress, state.uWordSize).Compare(state); + (void)RunOSWaitOnAddressTimed(pTargetAddress, pCompareAddress, state.uWordSize, state.qwNanosecondsAbs.value(), { }, { }, bSpun); + return !WaitBuffer::Compare(pTargetAddress, state.uWordSize, state); } static void RunOSWakeNOnAddress(const void *pAddress, @@ -828,7 +858,7 @@ namespace Aurora::Threading else { state.qwNanosecondsAbs = qwNanosecondsAbs; - return RunOSWaitOnAddressTimedSteady(pWaitAddress, pCompareAddress2, state); + return RunOSWaitOnAddressTimedSteady(pWaitAddress, pCompareAddress2, state, true); } } @@ -853,55 +883,30 @@ namespace Aurora::Threading AUKN_SYM bool WaitOnAddress(const void *pTargetAddress, const void *pCompareAddress, AuUInt8 uWordSize, - AuUInt64 qwNanoseconds) + AuUInt64 qwNanoseconds, + AuOptional optAlreadySpun) { - bool bWaitOnAddress = IsWaitOnRecommended(); - if (bWaitOnAddress) + // Avoid SteadyTime syscall in the event of HAL retardation (missing KUSER QPC, Linux vDSO, etc) + if (!WaitBuffer::Compare(pTargetAddress, uWordSize, pCompareAddress)) { - auto [pWaitAddress, uDelta, uMask] = DecodeAddress(pTargetAddress, uWordSize); - auto pCompareAddress2 = AuReinterpretCast(pCompareAddress) - uDelta; - - WaitState state; - state.uDownsizeMask = uMask; - state.compare = uMask ? - WaitBuffer::From(pCompareAddress2, 4) : - WaitBuffer::From(pCompareAddress2, uWordSize); - state.uWordSize = uMask ? 4 : uWordSize; - - if (!qwNanoseconds) - { - RunOSWaitOnAddressNoTimedNoErrors(pWaitAddress, pCompareAddress2, state); - return true; - } - else - { - state.qwNanosecondsAbs = qwNanoseconds + AuTime::SteadyClockNS(); - return RunOSWaitOnAddressTimedSteady(pWaitAddress, pCompareAddress2, state); - } - } - else - { - if (Primitives::ThrdCfg::gPreferWaitOnAddressAlwaysSpin) - { - if (TryWaitOnAddress(pTargetAddress, pCompareAddress, uWordSize)) - { - return true; - } - } - - return WaitOnAddressWide(pTargetAddress, pCompareAddress, uWordSize, qwNanoseconds, {}, false); + return true; } - return false; + return WaitOnAddressSteady(pTargetAddress, + pCompareAddress, + uWordSize, + qwNanoseconds ? qwNanoseconds + AuTime::SteadyClockNS() : 0, + optAlreadySpun); } AUKN_SYM bool TryWaitOnAddress(const void *pTargetAddress, const void *pCompareAddress, AuUInt8 uWordSize) { - return Primitives::DoTryIf([=]() + auto expect = WaitBuffer::From(pCompareAddress, uWordSize); + return Primitives::DoTryIf([&]() { - return !WaitBuffer::From(pCompareAddress, uWordSize).Compare(pTargetAddress); + return !expect.Compare(pTargetAddress); }); } @@ -959,7 +964,8 @@ namespace Aurora::Threading AUKN_SYM bool WaitOnAddressSteady(const void *pTargetAddress, const void *pCompareAddress, AuUInt8 uWordSize, - AuUInt64 qwNanoseconds) + AuUInt64 qwNanoseconds, + AuOptional optAlreadySpun) { bool bWaitOnAddress = IsWaitOnRecommended(); if (bWaitOnAddress) @@ -974,6 +980,18 @@ namespace Aurora::Threading WaitBuffer::From(pCompareAddress2, uWordSize); state.uWordSize = uMask ? 4 : uWordSize; + bool bSpun {}; + if (Primitives::ThrdCfg::gPreferWaitOnAddressAlwaysSpinNative && + optAlreadySpun.value_or(false)) + { + if (TryWaitOnAddress(pTargetAddress, pCompareAddress, uWordSize)) + { + return true; + } + + bSpun = true; + } + if (!qwNanoseconds) { RunOSWaitOnAddressNoTimedNoErrors(pWaitAddress, pCompareAddress2, state); @@ -982,12 +1000,13 @@ namespace Aurora::Threading else { state.qwNanosecondsAbs = qwNanoseconds; - return RunOSWaitOnAddressTimedSteady(pWaitAddress, pCompareAddress2, state); + return RunOSWaitOnAddressTimedSteady(pWaitAddress, pCompareAddress2, state, bSpun); } } else { - if (Primitives::ThrdCfg::gPreferWaitOnAddressAlwaysSpin) + if (Primitives::ThrdCfg::gPreferWaitOnAddressAlwaysSpin && + optAlreadySpun.value_or(false)) { if (TryWaitOnAddress(pTargetAddress, pCompareAddress, uWordSize)) { diff --git a/Source/Threading/AuWakeOnAddress.hpp b/Source/Threading/AuWakeOnAddress.hpp index fa8cab9e..c089ec25 100644 --- a/Source/Threading/AuWakeOnAddress.hpp +++ b/Source/Threading/AuWakeOnAddress.hpp @@ -18,10 +18,13 @@ namespace Aurora::Threading struct WaitBuffer { - char buffer[8]; + char buffer[32]; AuUInt8 uSize; static WaitBuffer From(const void *pBuf, AuUInt8 uSize); + static bool Compare(const void *pBuf, AuUInt8 uSize, WaitState &state); + static bool Compare(const void *pBuf, AuUInt8 uSize, const void *pBuf2); + bool Compare(const void *pBuf); bool Compare(WaitState &state); }; diff --git a/Source/Threading/Primitives/SMTYield.cpp b/Source/Threading/Primitives/SMTYield.cpp index b3faf326..11fc6b55 100644 --- a/Source/Threading/Primitives/SMTYield.cpp +++ b/Source/Threading/Primitives/SMTYield.cpp @@ -164,6 +164,7 @@ namespace Aurora::Threading::Primitives ThrdCfg::gPreferLinuxCondMutexSpinTryLock = gRuntimeConfig.threadingConfig.bPreferLinuxCondMutexSpinTryLock; ThrdCfg::gPreferEmulatedWakeOnAddress = gRuntimeConfig.threadingConfig.bPreferEmulatedWakeOnAddress; ThrdCfg::gPreferWaitOnAddressAlwaysSpin = gRuntimeConfig.threadingConfig.bPreferWaitOnAddressAlwaysSpin; + ThrdCfg::gPreferWaitOnAddressAlwaysSpinNative = gRuntimeConfig.threadingConfig.bPreferWaitOnAddressAlwaysSpinNative; ThrdCfg::gPreferRWLockReadLockSpin = gRuntimeConfig.threadingConfig.bPreferRWLockReadLockSpin; ThrdCfg::gUWPNanosecondEmulationCheckFirst = gRuntimeConfig.threadingConfig.bUWPNanosecondEmulationCheckFirst; ThrdCfg::gUWPNanosecondEmulationMaxYields = gRuntimeConfig.threadingConfig.uUWPNanosecondEmulationMaxYields; diff --git a/Source/Threading/Primitives/SMTYield.hpp b/Source/Threading/Primitives/SMTYield.hpp index d54c561c..ca67b36c 100644 --- a/Source/Threading/Primitives/SMTYield.hpp +++ b/Source/Threading/Primitives/SMTYield.hpp @@ -32,6 +32,7 @@ namespace Aurora::Threading::Primitives inline bool gPreferLinuxCondMutexSpinTryLock {}; inline bool gPreferEmulatedWakeOnAddress {}; inline bool gPreferWaitOnAddressAlwaysSpin {}; + inline bool gPreferWaitOnAddressAlwaysSpinNative {}; inline bool gPreferRWLockReadLockSpin {}; inline bool gUWPNanosecondEmulationCheckFirst {}; inline AuUInt32 gUWPNanosecondEmulationMaxYields {};