1
0
Fork 0
forked from suyu/suyu

core_timing: Sleep in discrete intervals, yield during spin

This commit is contained in:
Morph 2022-08-01 23:34:34 -04:00
parent 658e1ee426
commit 606cdb17d3

View file

@ -281,20 +281,21 @@ void CoreTiming::ThreadLoop() {
paused_set = false; paused_set = false;
const auto next_time = Advance(); const auto next_time = Advance();
if (next_time) { if (next_time) {
// There are more events left in the queue, sleep until the next event. // There are more events left in the queue, wait until the next event.
const auto diff_ns{*next_time - GetGlobalTimeNs().count()}; const auto wait_time = *next_time - GetGlobalTimeNs().count();
if (diff_ns > 0) { if (wait_time > 0) {
// Only try to sleep if the remaining time is >= 1ms. Take off 500 microseconds // Assume a timer resolution of 1ms.
// from the target time to account for possible over-sleeping, and spin the static constexpr s64 TimerResolutionNS = 1000000;
// remaining.
const auto sleep_time_ns{diff_ns - 500LL * 1'000LL}; // Sleep in discrete intervals of the timer resolution, and spin the rest.
const auto sleep_time_ms{sleep_time_ns / 1'000'000LL}; const auto sleep_time = wait_time - (wait_time % TimerResolutionNS);
if (sleep_time_ms >= 1) { if (sleep_time > 0) {
event.WaitFor(std::chrono::nanoseconds(sleep_time_ns)); event.WaitFor(std::chrono::nanoseconds(sleep_time));
} }
const auto end_time{std::chrono::nanoseconds(*next_time)}; while (!paused && !event.IsSet() && GetGlobalTimeNs().count() < *next_time) {
while (!paused && !event.IsSet() && GetGlobalTimeNs() < end_time) { // Yield to reduce thread starvation.
std::this_thread::yield();
} }
if (event.IsSet()) { if (event.IsSet()) {