From 3196d957b02266293b68a60c75c3db9a00faf1f6 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 29 Jun 2022 01:29:24 +0200 Subject: [PATCH] Adress Feedback. --- src/common/x64/native_clock.cpp | 1 - src/core/core_timing.cpp | 43 ++++++++++++++++++++------------- src/core/core_timing.h | 4 ++- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index c0d38cf6b..6aaa8cdf9 100644 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp @@ -89,7 +89,6 @@ u64 NativeClock::GetRTSC() { new_time_point.inner.accumulated_ticks = current_time_point.inner.accumulated_ticks + diff; } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack, current_time_point.pack, current_time_point.pack)); - /// The clock cannot be more precise than the guest timer, remove the lower bits return new_time_point.inner.accumulated_ticks; } diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index ac117161c..140578069 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -6,6 +6,7 @@ #include #include +#include "common/logging/log.h" #include "common/microprofile.h" #include "common/thread.h" #include "core/core_timing.h" @@ -42,10 +43,10 @@ CoreTiming::CoreTiming() CoreTiming::~CoreTiming() = default; -void CoreTiming::ThreadEntry(CoreTiming& instance) { - constexpr char name[] = "yuzu:HostTiming"; - MicroProfileOnThreadCreate(name); - Common::SetCurrentThreadName(name); +void CoreTiming::ThreadEntry(CoreTiming& instance, size_t id) { + const std::string name = "yuzu:HostTiming_" + std::to_string(id); + MicroProfileOnThreadCreate(name.c_str()); + Common::SetCurrentThreadName(name.c_str()); Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical); instance.on_thread_init(); instance.ThreadLoop(); @@ -61,9 +62,10 @@ void CoreTiming::Initialize(std::function&& on_thread_init_) { ev_lost = CreateEvent("_lost_event", empty_timed_callback); if (is_multicore) { const auto hardware_concurrency = std::thread::hardware_concurrency(); - worker_threads.emplace_back(ThreadEntry, std::ref(*this)); + size_t id = 0; + worker_threads.emplace_back(ThreadEntry, std::ref(*this), id++); if (hardware_concurrency > 8) { - worker_threads.emplace_back(ThreadEntry, std::ref(*this)); + worker_threads.emplace_back(ThreadEntry, std::ref(*this), id++); } } } @@ -71,11 +73,10 @@ void CoreTiming::Initialize(std::function&& on_thread_init_) { void CoreTiming::Shutdown() { is_paused = true; shutting_down = true; - { - std::unique_lock main_lock(event_mutex); - event_cv.notify_all(); - wait_pause_cv.notify_all(); - } + std::atomic_thread_fence(std::memory_order_release); + + event_cv.notify_all(); + wait_pause_cv.notify_all(); for (auto& thread : worker_threads) { thread.join(); } @@ -128,7 +129,7 @@ bool CoreTiming::IsRunning() const { bool CoreTiming::HasPendingEvents() const { std::unique_lock main_lock(event_mutex); - return !event_queue.empty(); + return !event_queue.empty() || pending_events.load(std::memory_order_relaxed) != 0; } void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, @@ -139,6 +140,7 @@ void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, const u64 timeout = static_cast((GetGlobalTimeNs() + ns_into_future).count()); event_queue.emplace_back(Event{timeout, event_fifo_id++, user_data, event_type}); + pending_events.fetch_add(1, std::memory_order_relaxed); std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); @@ -158,6 +160,7 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr& event_type, if (itr != event_queue.end()) { event_queue.erase(itr, event_queue.end()); std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); + pending_events.fetch_sub(1, std::memory_order_relaxed); } } @@ -223,15 +226,21 @@ std::optional CoreTiming::Advance() { Event evt = std::move(event_queue.front()); std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>()); event_queue.pop_back(); - event_mutex.unlock(); if (const auto event_type{evt.type.lock()}) { - std::unique_lock lk(event_type->guard); - event_type->callback(evt.user_data, std::chrono::nanoseconds{static_cast( - GetGlobalTimeNs().count() - evt.time)}); + sequence_mutex.lock(); + event_mutex.unlock(); + + event_type->guard.lock(); + sequence_mutex.unlock(); + const s64 delay = static_cast(GetGlobalTimeNs().count() - evt.time); + event_type->callback(evt.user_data, std::chrono::nanoseconds{delay}); + event_type->guard.unlock(); + + event_mutex.lock(); + pending_events.fetch_sub(1, std::memory_order_relaxed); } - event_mutex.lock(); global_timer = GetGlobalTimeNs().count(); } diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 4fef6fcce..a86553e08 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h @@ -132,7 +132,7 @@ private: /// Clear all pending events. This should ONLY be done on exit. void ClearPendingEvents(); - static void ThreadEntry(CoreTiming& instance); + static void ThreadEntry(CoreTiming& instance, size_t id); void ThreadLoop(); std::unique_ptr clock; @@ -145,6 +145,7 @@ private: // accomodated by the standard adaptor class. std::vector event_queue; u64 event_fifo_id = 0; + std::atomic pending_events{}; std::shared_ptr ev_lost; std::atomic has_started{}; @@ -156,6 +157,7 @@ private: std::condition_variable wait_pause_cv; std::condition_variable wait_signal_cv; mutable std::mutex event_mutex; + mutable std::mutex sequence_mutex; std::atomic paused_state{}; bool is_paused{};