From 75b71275e742c394c9931b687ce3d75f0da23ea5 Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Sun, 9 Jul 2023 20:52:31 +0100 Subject: [PATCH] [*] Made past and present NT condvar optional spin steps configurable via the runtime config --- Include/Aurora/Runtime.hpp | 19 ++++++----- .../Primitives/AuConditionVariable.NT.cpp | 32 +++++++++++++------ 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/Include/Aurora/Runtime.hpp b/Include/Aurora/Runtime.hpp index f7648fad..ee74b1fb 100644 --- a/Include/Aurora/Runtime.hpp +++ b/Include/Aurora/Runtime.hpp @@ -346,19 +346,18 @@ namespace Aurora struct ThreadingConfig { + // WARN: these values are not final + bool bNoThreadNames { false }; bool bPlatformIsSMPProcessorOptimized { true }; // Whether to attempt to using mm_pause or similar before yielding into the kernel - AuUInt8 uSpinLoopPowerA { 7 }; // Nudgable spinloop power. This is our local userland niceness factor; where 1 << n is the amount of yield instructions to stall for - + AuUInt8 uSpinLoopPowerA { 7 }; // Nudgable spinloop power. This is our local userland niceness factor; where 1 << n is the amount of yield instructions to stall for bool bEnableAggressiveScheduling { false }; - bool bEnableAgrSchedulingRatelimit { true }; - bool bPreferNt51XpMutexesOver8 { false }; // Fun Fact: Undocumented Windows XP APIs are still better than whatever the fuck shit fest they sharted out under Windows Vista and maybe 8.1 - bool bPerferNt51XpCondvarsOver8 { false }; // Wth the former set of apis, we are still nothing more than a futex intended for nothing more than x86 bittestandset with undefined - }; // bahviour on the higher bits, and we're crippled by some annoying thread switch function. Windows Vista superseded the dumb kernel-io - // based switching apis everyone thought they had to use with bloat on top of this very same 5.1 era api. - // ~~ And to end it all off, Windows 8.1 wait/wake on address forces relative millisecond precision, in the first (?) MS OS to drop tick based [re]scheduling. ~~ (officially) - // Our main mutex is one edge case where undcoumented XP era scheduling apis are better than the garbage indiasoft wants you to use in . - + bool bEnableAgrSchedulingRatelimit { true }; + bool bPreferNt51XpMutexesOver8 { false }; + bool bPerferNt51XpCondvarsOver8 { false }; + bool bPerferNtCondvarModernWinSpin { true }; // to reevaluate (true could cause double spinning depending on the nt version! prediction: true regardless) + bool bPerferNtCondvarOlderWinSpin { true }; // to reevaluate (true could cause excessive context switching in signaling thread! prediction: back to false) + }; struct RuntimeStartInfo { diff --git a/Source/Threading/Primitives/AuConditionVariable.NT.cpp b/Source/Threading/Primitives/AuConditionVariable.NT.cpp index 3830239d..616fb0d4 100644 --- a/Source/Threading/Primitives/AuConditionVariable.NT.cpp +++ b/Source/Threading/Primitives/AuConditionVariable.NT.cpp @@ -93,17 +93,20 @@ namespace Aurora::Threading::Primitives if (gUseNativeWaitCondvar) { // Reverted: 5b495f7fd9495aa55395666e166ac499955215dc - if (!bIOU) + if (gRuntimeConfig.threadingConfig.bPerferNtCondvarModernWinSpin) { - bool b = true; - #if 0 - bIOU = CheckOut(b); - #else - if (CheckOut(b)) + if (!bIOU) { - return true; + bool b = true; + #if 0 + bIOU = CheckOut(b); + #else + if (CheckOut(b)) + { + return true; + } + #endif } - #endif } AuUInt8 uBlockBit { 1 }; @@ -111,6 +114,16 @@ namespace Aurora::Threading::Primitives } else { + // Reverted: 5b495f7fd9495aa55395666e166ac499955215dc + if (gRuntimeConfig.threadingConfig.bPerferNtCondvarOlderWinSpin) + { + if (!bIOU) + { + bool b = true; + bIOU = CheckOut(b); + } + } + bRet = pNtWaitForKeyedEvent(gKeyedEventHandle, &this->wlist, 0, &word) != NTSTATUS_TIMEOUT; } @@ -135,10 +148,11 @@ namespace Aurora::Threading::Primitives AuUInt8 uBlockBit { 1 }; pWakeByAddressAll(&this->wlist); // this is kinda sad - bRet = InternalLTSWaitOnAddressHighRes(&this->wlist, &uBlockBit, 1, uEndTimeSteady); // why is this even being called? + bRet = InternalLTSWaitOnAddressHighRes(&this->wlist, &uBlockBit, 1, uEndTimeSteady); // why? } else { + // Obligatory Windows XP+ resched bRet = pNtWaitForKeyedEvent(gKeyedEventHandle, &this->wlist, 0, nullptr) != NTSTATUS_TIMEOUT; }