mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	SingleCore: Move Host Timing from a sepparate thread to main cpu thread.
This commit is contained in:
		
							parent
							
								
									5d3a2be04f
								
							
						
					
					
						commit
						f2ade343e2
					
				@ -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);
 | 
				
			||||||
 | 
					    if (is_multicore) {
 | 
				
			||||||
        timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this));
 | 
					        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();
 | 
				
			||||||
 | 
					    if (timer_thread) {
 | 
				
			||||||
        timer_thread->join();
 | 
					        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 (timer_thread) {
 | 
				
			||||||
        if (!is_paused) {
 | 
					        if (!is_paused) {
 | 
				
			||||||
            pause_event.Set();
 | 
					            pause_event.Set();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        event.Set();
 | 
					        event.Set();
 | 
				
			||||||
        while (paused_set != is_paused)
 | 
					        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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user