diff --git a/Source/Threading/AuSleep.cpp b/Source/Threading/AuSleep.cpp index 698ac031..906ef719 100644 --- a/Source/Threading/AuSleep.cpp +++ b/Source/Threading/AuSleep.cpp @@ -59,16 +59,27 @@ namespace Aurora::Threading if (pNtDelayExecution) { - auto endTimeSteady = AuTime::SteadyClockNS() + qwTimeout; - auto endTimeWall = AuTime::CurrentClockNS() + qwTimeout; - auto targetTimeNt = AuTime::ConvertTimestampNs(endTimeWall); + auto uWndTimeSteadyNS = AuTime::SteadyClockNS() + qwTimeout; + #if defined(_AURORA_WANT_STRICT_NT_WAKEUP_TIME_NO_WALL_CLOCK_SHIFT_ALLOWED) + auto uEndTimeWall = AuTime::CurrentClockNS() + qwTimeout; + auto uTargetTimeNt = AuTime::ConvertTimestampNs(uEndTimeWall); + #endif Win32DropSchedulerResolution(); - while (AuTime::SteadyClockNS() < endTimeSteady) + AuUInt64 uNowNS {}; + while ((uNowNS = AuTime::SteadyClockNS()) < uWndTimeSteadyNS) { LARGE_INTEGER word; - word.QuadPart = targetTimeNt; + #if defined(_AURORA_WANT_STRICT_NT_WAKEUP_TIME_NO_WALL_CLOCK_SHIFT_ALLOWED) + word.QuadPart = uTargetTimeNt; + #else + word.QuadPart = -((uWndTimeSteadyNS - uNowNS) / 100ull); + if (!word.QuadPart) + { + break; + } + #endif pNtDelayExecution(FALSE, &word); } diff --git a/Source/Threading/Primitives/AuConditionVariable.NT.cpp b/Source/Threading/Primitives/AuConditionVariable.NT.cpp index eff7ce39..663b9bee 100644 --- a/Source/Threading/Primitives/AuConditionVariable.NT.cpp +++ b/Source/Threading/Primitives/AuConditionVariable.NT.cpp @@ -55,15 +55,16 @@ namespace Aurora::Threading::Primitives if (qwTimeout) { + #if defined(_AURORA_WANT_STRICT_NT_WAKEUP_TIME_NO_WALL_CLOCK_SHIFT_ALLOWED) auto uEndTimeSteady = gUseNativeWaitCondvar ? AuTime::SteadyClockNS() + qwTimeout : 0; auto uEndTimeWall = AuTime::CurrentClockNS() + qwTimeout; auto uTargetTimeNt = AuTime::ConvertTimestampNs(uEndTimeWall); + #else + auto uEndTimeSteady = AuTime::SteadyClockNS() + qwTimeout; + #endif while (true) { - LARGE_INTEGER word; - word.QuadPart = uTargetTimeNt; - if (bRet) { if (gUseNativeWaitCondvar) @@ -99,7 +100,25 @@ namespace Aurora::Threading::Primitives } } - bRet = pNtWaitForKeyedEvent(gKeyedEventHandle, (void *)&this->wlist, 0, &word) == 0; + { + LARGE_INTEGER word; + #if defined(_AURORA_WANT_STRICT_NT_WAKEUP_TIME_NO_WALL_CLOCK_SHIFT_ALLOWED) + word.QuadPart = uTargetTimeNt; + #else + auto uNow = AuTime::SteadyClockNS(); + + if (uEndTimeSteady > uNow) + { + word.QuadPart = -((uEndTimeSteady - uNow) / 100ull); + } + else + { + word.QuadPart = 0; + } + #endif + + bRet = pNtWaitForKeyedEvent(gKeyedEventHandle, (void *)&this->wlist, 0, &word) == 0; + } } } else /* unblock NtReleaseKeyedEvent after an atomic this->wlist change <-> NtReleaseKeyedEvent race condition. */ diff --git a/Source/Threading/Primitives/AuMutex.NT.cpp b/Source/Threading/Primitives/AuMutex.NT.cpp index 10088f56..5ab962a2 100644 --- a/Source/Threading/Primitives/AuMutex.NT.cpp +++ b/Source/Threading/Primitives/AuMutex.NT.cpp @@ -183,15 +183,18 @@ namespace Aurora::Threading::Primitives returnValue = true; auto uEndTimeSteady = AuTime::SteadyClockNS() + uTimeout; + #if defined(_AURORA_WANT_STRICT_NT_WAKEUP_TIME_NO_WALL_CLOCK_SHIFT_ALLOWED) auto uEndTimeWall = AuTime::CurrentClockNS() + uTimeout; + #endif bool bFailed {}; while (bFailed || (!this->TryLockNoSpin())) { auto uValue = uValueRef | 1; + AuUInt64 uNowNS {}; - if (!bFailed && - AuTime::SteadyClockNS() >= uEndTimeSteady) + if ((!bFailed) && + ((uNowNS = AuTime::SteadyClockNS()) >= uEndTimeSteady)) { returnValue = this->TryLock(); break; @@ -199,10 +202,13 @@ namespace Aurora::Threading::Primitives if (bFailed || AuAtomicCompareExchange(&uValueRef, uValue + kFutexBitWait, uValue) == uValue) { - auto uTargetTimeNt = AuTime::ConvertTimestampNs(uEndTimeWall); LARGE_INTEGER word; - word.QuadPart = uTargetTimeNt; + #if defined(_AURORA_WANT_STRICT_NT_WAKEUP_TIME_NO_WALL_CLOCK_SHIFT_ALLOWED) + word.QuadPart = AuTime::ConvertTimestampNs(uEndTimeWall); + #else + word.QuadPart = -((uEndTimeSteady - uNowNS) / 100ull); + #endif auto uStatus = pNtWaitForKeyedEvent(gKeyedEventHandle, (void *)&this->state_, 0, &word); if (uStatus == NTSTATUS_TIMEOUT)