SingleCore: Move Host Timing from a sepparate thread to main cpu thread.
This commit is contained in:
		| @@ -158,6 +158,8 @@ struct System::Impl { | |||||||
|         kernel.SetMulticore(is_multicore); |         kernel.SetMulticore(is_multicore); | ||||||
|         cpu_manager.SetMulticore(is_multicore); |         cpu_manager.SetMulticore(is_multicore); | ||||||
|         cpu_manager.SetAsyncGpu(is_async_gpu); |         cpu_manager.SetAsyncGpu(is_async_gpu); | ||||||
|  |         core_timing.SetMulticore(is_multicore); | ||||||
|  |         cpu_manager.SetRenderWindow(emu_window); | ||||||
|  |  | ||||||
|         core_timing.Initialize([&system]() { system.RegisterHostThread(); }); |         core_timing.Initialize([&system]() { system.RegisterHostThread(); }); | ||||||
|         kernel.Initialize(); |         kernel.Initialize(); | ||||||
|   | |||||||
| @@ -55,7 +55,9 @@ void CoreTiming::Initialize(std::function<void(void)>&& on_thread_init_) { | |||||||
|     event_fifo_id = 0; |     event_fifo_id = 0; | ||||||
|     const auto empty_timed_callback = [](u64, s64) {}; |     const auto empty_timed_callback = [](u64, s64) {}; | ||||||
|     ev_lost = CreateEvent("_lost_event", empty_timed_callback); |     ev_lost = CreateEvent("_lost_event", empty_timed_callback); | ||||||
|     timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); |     if (is_multicore) { | ||||||
|  |         timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void CoreTiming::Shutdown() { | void CoreTiming::Shutdown() { | ||||||
| @@ -63,7 +65,9 @@ void CoreTiming::Shutdown() { | |||||||
|     shutting_down = true; |     shutting_down = true; | ||||||
|     pause_event.Set(); |     pause_event.Set(); | ||||||
|     event.Set(); |     event.Set(); | ||||||
|     timer_thread->join(); |     if (timer_thread) { | ||||||
|  |         timer_thread->join(); | ||||||
|  |     } | ||||||
|     ClearPendingEvents(); |     ClearPendingEvents(); | ||||||
|     timer_thread.reset(); |     timer_thread.reset(); | ||||||
|     has_started = false; |     has_started = false; | ||||||
| @@ -78,12 +82,14 @@ void CoreTiming::SyncPause(bool is_paused) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     Pause(is_paused); |     Pause(is_paused); | ||||||
|     if (!is_paused) { |     if (timer_thread) { | ||||||
|         pause_event.Set(); |         if (!is_paused) { | ||||||
|  |             pause_event.Set(); | ||||||
|  |         } | ||||||
|  |         event.Set(); | ||||||
|  |         while (paused_set != is_paused) | ||||||
|  |             ; | ||||||
|     } |     } | ||||||
|     event.Set(); |  | ||||||
|     while (paused_set != is_paused) |  | ||||||
|         ; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| bool CoreTiming::IsRunning() const { | bool CoreTiming::IsRunning() const { | ||||||
|   | |||||||
| @@ -67,6 +67,11 @@ public: | |||||||
|     /// Tears down all timing related functionality. |     /// Tears down all timing related functionality. | ||||||
|     void Shutdown(); |     void Shutdown(); | ||||||
|  |  | ||||||
|  |     /// Sets if emulation is multicore or single core, must be set before Initialize | ||||||
|  |     void SetMulticore(bool is_multicore) { | ||||||
|  |         this->is_multicore = is_multicore; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /// Pauses/Unpauses the execution of the timer thread. |     /// Pauses/Unpauses the execution of the timer thread. | ||||||
|     void Pause(bool is_paused); |     void Pause(bool is_paused); | ||||||
|  |  | ||||||
| @@ -147,6 +152,8 @@ private: | |||||||
|     std::atomic<bool> has_started{}; |     std::atomic<bool> has_started{}; | ||||||
|     std::function<void(void)> on_thread_init{}; |     std::function<void(void)> on_thread_init{}; | ||||||
|  |  | ||||||
|  |     bool is_multicore{}; | ||||||
|  |  | ||||||
|     std::array<std::atomic<u64>, Core::Hardware::NUM_CPU_CORES> ticks_count{}; |     std::array<std::atomic<u64>, Core::Hardware::NUM_CPU_CORES> ticks_count{}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -242,8 +242,11 @@ void CpuManager::SingleCoreRunGuestLoop() { | |||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         physical_core.ClearExclusive(); |  | ||||||
|         system.ExitDynarmicProfile(); |         system.ExitDynarmicProfile(); | ||||||
|  |         thread->SetPhantomMode(true); | ||||||
|  |         system.CoreTiming().Advance(); | ||||||
|  |         thread->SetPhantomMode(false); | ||||||
|  |         physical_core.ClearExclusive(); | ||||||
|         PreemptSingleCore(); |         PreemptSingleCore(); | ||||||
|         auto& scheduler = kernel.Scheduler(current_core); |         auto& scheduler = kernel.Scheduler(current_core); | ||||||
|         scheduler.TryDoContextSwitch(); |         scheduler.TryDoContextSwitch(); | ||||||
| @@ -255,6 +258,7 @@ void CpuManager::SingleCoreRunIdleThread() { | |||||||
|     while (true) { |     while (true) { | ||||||
|         auto& physical_core = kernel.CurrentPhysicalCore(); |         auto& physical_core = kernel.CurrentPhysicalCore(); | ||||||
|         PreemptSingleCore(); |         PreemptSingleCore(); | ||||||
|  |         idle_count++; | ||||||
|         auto& scheduler = physical_core.Scheduler(); |         auto& scheduler = physical_core.Scheduler(); | ||||||
|         scheduler.TryDoContextSwitch(); |         scheduler.TryDoContextSwitch(); | ||||||
|     } |     } | ||||||
| @@ -280,15 +284,24 @@ void CpuManager::SingleCoreRunSuspendThread() { | |||||||
| void CpuManager::PreemptSingleCore() { | void CpuManager::PreemptSingleCore() { | ||||||
|     preemption_count = 0; |     preemption_count = 0; | ||||||
|     std::size_t old_core = current_core; |     std::size_t old_core = current_core; | ||||||
|     current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); |  | ||||||
|     auto& scheduler = system.Kernel().Scheduler(old_core); |     auto& scheduler = system.Kernel().Scheduler(old_core); | ||||||
|     Kernel::Thread* current_thread = scheduler.GetCurrentThread(); |     Kernel::Thread* current_thread = scheduler.GetCurrentThread(); | ||||||
|  |     if (idle_count >= 4) { | ||||||
|  |         current_thread->SetPhantomMode(true); | ||||||
|  |         system.CoreTiming().Advance(); | ||||||
|  |         current_thread->SetPhantomMode(false); | ||||||
|  |     } | ||||||
|  |     current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); | ||||||
|     scheduler.Unload(); |     scheduler.Unload(); | ||||||
|     auto& next_scheduler = system.Kernel().Scheduler(current_core); |     auto& next_scheduler = system.Kernel().Scheduler(current_core); | ||||||
|     Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext()); |     Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext()); | ||||||
|     /// May have changed scheduler |     /// May have changed scheduler | ||||||
|     auto& current_scheduler = system.Kernel().Scheduler(current_core); |     auto& current_scheduler = system.Kernel().Scheduler(current_core); | ||||||
|     current_scheduler.Reload(); |     current_scheduler.Reload(); | ||||||
|  |     auto* currrent_thread2 = current_scheduler.GetCurrentThread(); | ||||||
|  |     if (!currrent_thread2->IsIdleThread()) { | ||||||
|  |         idle_count = 0; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void CpuManager::SingleCorePause(bool paused) { | void CpuManager::SingleCorePause(bool paused) { | ||||||
|   | |||||||
| @@ -104,6 +104,7 @@ private: | |||||||
|     bool is_multicore{}; |     bool is_multicore{}; | ||||||
|     std::atomic<std::size_t> current_core{}; |     std::atomic<std::size_t> current_core{}; | ||||||
|     std::size_t preemption_count{}; |     std::size_t preemption_count{}; | ||||||
|  |     std::size_t idle_count{}; | ||||||
|     static constexpr std::size_t max_cycle_runs = 5; |     static constexpr std::size_t max_cycle_runs = 5; | ||||||
|     Core::Frontend::EmuWindow* render_window; |     Core::Frontend::EmuWindow* render_window; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -303,7 +303,7 @@ struct KernelCore::Impl { | |||||||
|         } |         } | ||||||
|         const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler(); |         const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler(); | ||||||
|         const Kernel::Thread* current = sched.GetCurrentThread(); |         const Kernel::Thread* current = sched.GetCurrentThread(); | ||||||
|         if (current != nullptr) { |         if (current != nullptr && !current->IsPhantomMode()) { | ||||||
|             result.guest_handle = current->GetGlobalHandle(); |             result.guest_handle = current->GetGlobalHandle(); | ||||||
|         } else { |         } else { | ||||||
|             result.guest_handle = InvalidHandle; |             result.guest_handle = InvalidHandle; | ||||||
|   | |||||||
| @@ -597,6 +597,14 @@ public: | |||||||
|         is_continuous_on_svc = is_continuous; |         is_continuous_on_svc = is_continuous; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     bool IsPhantomMode() const { | ||||||
|  |         return is_phantom_mode; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void SetPhantomMode(bool phantom) { | ||||||
|  |         is_phantom_mode = phantom; | ||||||
|  |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     friend class GlobalScheduler; |     friend class GlobalScheduler; | ||||||
|     friend class Scheduler; |     friend class Scheduler; | ||||||
| @@ -699,6 +707,7 @@ private: | |||||||
|     bool is_continuous_on_svc = false; |     bool is_continuous_on_svc = false; | ||||||
|  |  | ||||||
|     bool will_be_terminated = false; |     bool will_be_terminated = false; | ||||||
|  |     bool is_phantom_mode = false; | ||||||
|  |  | ||||||
|     bool was_running = false; |     bool was_running = false; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user