diff options
| -rw-r--r-- | src/common/thread.h | 4 | ||||
| -rw-r--r-- | src/core/core_timing.cpp | 38 |
2 files changed, 31 insertions, 11 deletions
diff --git a/src/common/thread.h b/src/common/thread.h index 1552f58e0..e17a7850f 100644 --- a/src/common/thread.h +++ b/src/common/thread.h | |||
| @@ -54,6 +54,10 @@ public: | |||
| 54 | is_set = false; | 54 | is_set = false; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | [[nodiscard]] bool IsSet() { | ||
| 58 | return is_set; | ||
| 59 | } | ||
| 60 | |||
| 57 | private: | 61 | private: |
| 58 | std::condition_variable condvar; | 62 | std::condition_variable condvar; |
| 59 | std::mutex mutex; | 63 | std::mutex mutex; |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 2dbb99c8b..b45c1b918 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -243,17 +243,17 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 243 | basic_lock.lock(); | 243 | basic_lock.lock(); |
| 244 | 244 | ||
| 245 | if (evt.reschedule_time != 0) { | 245 | if (evt.reschedule_time != 0) { |
| 246 | const auto next_schedule_time{new_schedule_time.has_value() | ||
| 247 | ? new_schedule_time.value().count() | ||
| 248 | : evt.reschedule_time}; | ||
| 249 | |||
| 246 | // If this event was scheduled into a pause, its time now is going to be way behind. | 250 | // If this event was scheduled into a pause, its time now is going to be way behind. |
| 247 | // Re-set this event to continue from the end of the pause. | 251 | // Re-set this event to continue from the end of the pause. |
| 248 | auto next_time{evt.time + evt.reschedule_time}; | 252 | auto next_time{evt.time + next_schedule_time}; |
| 249 | if (evt.time < pause_end_time) { | 253 | if (evt.time < pause_end_time) { |
| 250 | next_time = pause_end_time + evt.reschedule_time; | 254 | next_time = pause_end_time + next_schedule_time; |
| 251 | } | 255 | } |
| 252 | 256 | ||
| 253 | const auto next_schedule_time{new_schedule_time.has_value() | ||
| 254 | ? new_schedule_time.value().count() | ||
| 255 | : evt.reschedule_time}; | ||
| 256 | |||
| 257 | event_queue.emplace_back( | 257 | event_queue.emplace_back( |
| 258 | Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time}); | 258 | Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time}); |
| 259 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | 259 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); |
| @@ -264,8 +264,7 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | if (!event_queue.empty()) { | 266 | if (!event_queue.empty()) { |
| 267 | const s64 next_time = event_queue.front().time - global_timer; | 267 | return event_queue.front().time; |
| 268 | return next_time; | ||
| 269 | } else { | 268 | } else { |
| 270 | return std::nullopt; | 269 | return std::nullopt; |
| 271 | } | 270 | } |
| @@ -278,11 +277,28 @@ void CoreTiming::ThreadLoop() { | |||
| 278 | paused_set = false; | 277 | paused_set = false; |
| 279 | const auto next_time = Advance(); | 278 | const auto next_time = Advance(); |
| 280 | if (next_time) { | 279 | if (next_time) { |
| 281 | if (*next_time > 0) { | 280 | // There are more events left in the queue, sleep until the next event. |
| 282 | std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time); | 281 | const auto diff_ns{*next_time - GetGlobalTimeNs().count()}; |
| 283 | event.WaitFor(next_time_ns); | 282 | if (diff_ns > 0) { |
| 283 | // Only try to sleep if the remaining time is >= 1ms. Take off 500 microseconds | ||
| 284 | // from the target time to account for possible over-sleeping, and spin the | ||
| 285 | // remaining. | ||
| 286 | const auto sleep_time_ns{diff_ns - 500LL * 1'000LL}; | ||
| 287 | const auto sleep_time_ms{sleep_time_ns / 1'000'000LL}; | ||
| 288 | if (sleep_time_ms >= 1) { | ||
| 289 | event.WaitFor(std::chrono::nanoseconds(sleep_time_ns)); | ||
| 290 | } | ||
| 291 | |||
| 292 | const auto end_time{std::chrono::nanoseconds(*next_time)}; | ||
| 293 | while (!paused && !event.IsSet() && GetGlobalTimeNs() < end_time) { | ||
| 294 | } | ||
| 295 | |||
| 296 | if (event.IsSet()) { | ||
| 297 | event.Reset(); | ||
| 298 | } | ||
| 284 | } | 299 | } |
| 285 | } else { | 300 | } else { |
| 301 | // Queue is empty, wait until another event is scheduled and signals us to continue. | ||
| 286 | wait_set = true; | 302 | wait_set = true; |
| 287 | event.Wait(); | 303 | event.Wait(); |
| 288 | } | 304 | } |