/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuSleep.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "AuSleep.hpp" #include "AuWaitFor.hpp" #if defined(AURORA_IS_POSIX_DERIVED) #include #endif #if defined(AURORA_IS_MODERNNT_DERIVED) #include #include #endif namespace Aurora::Threading { AUKN_SYM void Sleep(AuUInt64 qwTimeout) { #if defined(AURORA_IS_MODERNNT_DERIVED) ::Sleep(qwTimeout); #else SleepNs(AuMSToNS(qwTimeout)); #endif } AUKN_SYM void SleepNs(AuUInt64 qwTimeout) { #if defined(AURORA_IS_LINUX_DERIVED) || defined(AURORA_IS_BSD_DERIVED) auto qwEndTime = AuTime::SteadyClockNS() + qwTimeout; if (auto uSleepMnSec = qwTimeout / 1000) { if ((usleep(uSleepMnSec) == -1) && (errno == EINTR)) { AuUInt64 qwNow; while ((qwNow = AuTime::SteadyClockNS()) < qwEndTime) { if (auto uSleepMnSec = (qwEndTime - qwNow) / 1000) { usleep(uSleepMnSec); } else { break; } } } } #else #if defined(AURORA_IS_MODERNNT_DERIVED) if (pNtDelayExecution) { auto uEndTimeSteadyNS = AuTime::SteadyClockNS() + qwTimeout; auto uEndTimeSteadyNS2 = uEndTimeSteadyNS; #if defined(_AURORA_WANT_STRICT_NT_WAKEUP_TIME_NO_WALL_CLOCK_SHIFT_ALLOWED) auto uEndTimeWall = AuTime::CurrentClockNS() + qwTimeout; auto uTargetTimeNt = AuTime::ConvertTimestampNs(uEndTimeWall); Win32DropSchedulerResolution(); #else if (!AuSwInfo::IsWindows8Point1OrGreater()) { if (qwTimeout < 500000) { uEndTimeSteadyNS -= 10'000ull; (void)YieldPollNs(true, uEndTimeSteadyNS, [=]() { return false; }); return; } if (qwTimeout < AuMSToNS(1)) { uEndTimeSteadyNS -= 250'000ull; } Win32DropSchedulerResolution(); } else { if (qwTimeout < AuMSToNS(1)) { uEndTimeSteadyNS -= 100'000ull; } } #endif AuUInt64 uNowNS {}; while ((uNowNS = AuTime::SteadyClockNS()) < uEndTimeSteadyNS2) { LARGE_INTEGER word; #if defined(_AURORA_WANT_STRICT_NT_WAKEUP_TIME_NO_WALL_CLOCK_SHIFT_ALLOWED) word.QuadPart = uTargetTimeNt; #else if (AuThreadPrimitives::ThrdCfg::gPlatformIsSMPProcessorOptimized) { if (uEndTimeSteadyNS2 - uNowNS <= 100000ull) { for (AU_ITERATE_N(i, 32)) { AuThreadPrimitives::SMPPause(); } continue; } } AuSInt sDelta1 = uEndTimeSteadyNS - uNowNS; word.QuadPart = 0; if (sDelta1 > 0) { word.QuadPart = -(sDelta1 / 100ull); } if (!word.QuadPart) { if (AuThreadPrimitives::ThrdCfg::gPlatformIsSMPProcessorOptimized) { for (AU_ITERATE_N(i, 32)) { AuThreadPrimitives::SMPPause(); } continue; } else { break; } } #endif pNtDelayExecution(FALSE, &word); } return; } #endif auto status = YieldPollNs(true, qwTimeout + Time::SteadyClockNS(), [=]() { return false; }); #endif } void InitSleep() { // ... } }