From 606cdb17d3b8f3b4898c1f0a87691058074ad11a Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 1 Aug 2022 23:34:34 -0400 Subject: [PATCH] core_timing: Sleep in discrete intervals, yield during spin --- src/core/core_timing.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index a75bfea60e..8d1ee3b516 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -281,20 +281,21 @@ void CoreTiming::ThreadLoop() { paused_set = false; const auto next_time = Advance(); if (next_time) { - // There are more events left in the queue, sleep until the next event. - const auto diff_ns{*next_time - GetGlobalTimeNs().count()}; - if (diff_ns > 0) { - // Only try to sleep if the remaining time is >= 1ms. Take off 500 microseconds - // from the target time to account for possible over-sleeping, and spin the - // remaining. - const auto sleep_time_ns{diff_ns - 500LL * 1'000LL}; - const auto sleep_time_ms{sleep_time_ns / 1'000'000LL}; - if (sleep_time_ms >= 1) { - event.WaitFor(std::chrono::nanoseconds(sleep_time_ns)); + // There are more events left in the queue, wait until the next event. + const auto wait_time = *next_time - GetGlobalTimeNs().count(); + if (wait_time > 0) { + // Assume a timer resolution of 1ms. + static constexpr s64 TimerResolutionNS = 1000000; + + // Sleep in discrete intervals of the timer resolution, and spin the rest. + const auto sleep_time = wait_time - (wait_time % TimerResolutionNS); + if (sleep_time > 0) { + event.WaitFor(std::chrono::nanoseconds(sleep_time)); } - const auto end_time{std::chrono::nanoseconds(*next_time)}; - while (!paused && !event.IsSet() && GetGlobalTimeNs() < end_time) { + while (!paused && !event.IsSet() && GetGlobalTimeNs().count() < *next_time) { + // Yield to reduce thread starvation. + std::this_thread::yield(); } if (event.IsSet()) {