Просмотр исходного кода

core_timing: Sleep in discrete intervals, yield during spin

Morph 4 лет назад
Родитель
Сommit
606cdb17d3
1 измененных файлов с 13 добавлено и 12 удалено
  1. 13 12
      src/core/core_timing.cpp

+ 13 - 12
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()) {