diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/cpu_manager.cpp | 193 |
1 files changed, 37 insertions, 156 deletions
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 09d9c5163..9fc78f033 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -21,23 +21,24 @@ CpuManager::~CpuManager() = default; void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core) { - cpu_manager.RunThread(stop_token, core); + cpu_manager.RunThread(core); } void CpuManager::Initialize() { - running_mode = true; - if (is_multicore) { - for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { - core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); - } - } else { - core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0); + num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1; + gpu_barrier = std::make_unique<Common::Barrier>(num_cores + 1); + + for (std::size_t core = 0; core < num_cores; core++) { + core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); } } void CpuManager::Shutdown() { - running_mode = false; - Pause(false); + for (std::size_t core = 0; core < num_cores; core++) { + if (core_data[core].host_thread.joinable()) { + core_data[core].host_thread.join(); + } + } } std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() { @@ -48,8 +49,8 @@ std::function<void(void*)> CpuManager::GetIdleThreadStartFunc() { return IdleThreadFunction; } -std::function<void(void*)> CpuManager::GetSuspendThreadStartFunc() { - return SuspendThreadFunction; +std::function<void(void*)> CpuManager::GetShutdownThreadStartFunc() { + return ShutdownThreadFunction; } void CpuManager::GuestThreadFunction(void* cpu_manager_) { @@ -79,17 +80,12 @@ void CpuManager::IdleThreadFunction(void* cpu_manager_) { } } -void CpuManager::SuspendThreadFunction(void* cpu_manager_) { - CpuManager* cpu_manager = static_cast<CpuManager*>(cpu_manager_); - if (cpu_manager->is_multicore) { - cpu_manager->MultiCoreRunSuspendThread(); - } else { - cpu_manager->SingleCoreRunSuspendThread(); - } +void CpuManager::ShutdownThreadFunction(void* cpu_manager) { + static_cast<CpuManager*>(cpu_manager)->ShutdownThread(); } -void* CpuManager::GetStartFuncParamater() { - return static_cast<void*>(this); +void* CpuManager::GetStartFuncParameter() { + return this; } /////////////////////////////////////////////////////////////////////////////// @@ -99,7 +95,7 @@ void* CpuManager::GetStartFuncParamater() { void CpuManager::MultiCoreRunGuestThread() { auto& kernel = system.Kernel(); kernel.CurrentScheduler()->OnThreadStart(); - auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); + auto* thread = kernel.CurrentScheduler()->GetSchedulerCurrentThread(); auto& host_context = thread->GetHostContext(); host_context->SetRewindPoint(GuestRewindFunction, this); MultiCoreRunGuestLoop(); @@ -110,12 +106,10 @@ void CpuManager::MultiCoreRunGuestLoop() { while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); - system.EnterDynarmicProfile(); while (!physical_core->IsInterrupted()) { physical_core->Run(); physical_core = &kernel.CurrentPhysicalCore(); } - system.ExitDynarmicProfile(); { Kernel::KScopedDisableDispatch dd(kernel); physical_core->ArmInterface().ClearExclusiveState(); @@ -131,58 +125,6 @@ void CpuManager::MultiCoreRunIdleThread() { } } -void CpuManager::MultiCoreRunSuspendThread() { - auto& kernel = system.Kernel(); - kernel.CurrentScheduler()->OnThreadStart(); - while (true) { - auto core = kernel.CurrentPhysicalCoreIndex(); - auto& scheduler = *kernel.CurrentScheduler(); - Kernel::KThread* current_thread = scheduler.GetCurrentThread(); - Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context); - ASSERT(scheduler.ContextSwitchPending()); - ASSERT(core == kernel.CurrentPhysicalCoreIndex()); - scheduler.RescheduleCurrentCore(); - } -} - -void CpuManager::MultiCorePause(bool paused) { - if (!paused) { - bool all_not_barrier = false; - while (!all_not_barrier) { - all_not_barrier = true; - for (const auto& data : core_data) { - all_not_barrier &= !data.is_running.load() && data.initialized.load(); - } - } - for (auto& data : core_data) { - data.enter_barrier->Set(); - } - if (paused_state.load()) { - bool all_barrier = false; - while (!all_barrier) { - all_barrier = true; - for (const auto& data : core_data) { - all_barrier &= data.is_paused.load() && data.initialized.load(); - } - } - for (auto& data : core_data) { - data.exit_barrier->Set(); - } - } - } else { - /// Wait until all cores are paused. - bool all_barrier = false; - while (!all_barrier) { - all_barrier = true; - for (const auto& data : core_data) { - all_barrier &= data.is_paused.load() && data.initialized.load(); - } - } - /// Don't release the barrier - } - paused_state = paused; -} - /////////////////////////////////////////////////////////////////////////////// /// SingleCore /// /////////////////////////////////////////////////////////////////////////////// @@ -190,7 +132,7 @@ void CpuManager::MultiCorePause(bool paused) { void CpuManager::SingleCoreRunGuestThread() { auto& kernel = system.Kernel(); kernel.CurrentScheduler()->OnThreadStart(); - auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); + auto* thread = kernel.CurrentScheduler()->GetSchedulerCurrentThread(); auto& host_context = thread->GetHostContext(); host_context->SetRewindPoint(GuestRewindFunction, this); SingleCoreRunGuestLoop(); @@ -200,12 +142,10 @@ void CpuManager::SingleCoreRunGuestLoop() { auto& kernel = system.Kernel(); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); - system.EnterDynarmicProfile(); if (!physical_core->IsInterrupted()) { physical_core->Run(); physical_core = &kernel.CurrentPhysicalCore(); } - system.ExitDynarmicProfile(); kernel.SetIsPhantomModeForSingleCore(true); system.CoreTiming().Advance(); kernel.SetIsPhantomModeForSingleCore(false); @@ -228,25 +168,11 @@ void CpuManager::SingleCoreRunIdleThread() { } } -void CpuManager::SingleCoreRunSuspendThread() { - auto& kernel = system.Kernel(); - kernel.CurrentScheduler()->OnThreadStart(); - while (true) { - auto core = kernel.GetCurrentHostThreadID(); - auto& scheduler = *kernel.CurrentScheduler(); - Kernel::KThread* current_thread = scheduler.GetCurrentThread(); - Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[0].host_context); - ASSERT(scheduler.ContextSwitchPending()); - ASSERT(core == kernel.GetCurrentHostThreadID()); - scheduler.RescheduleCurrentCore(); - } -} - void CpuManager::PreemptSingleCore(bool from_running_enviroment) { { auto& kernel = system.Kernel(); auto& scheduler = kernel.Scheduler(current_core); - Kernel::KThread* current_thread = scheduler.GetCurrentThread(); + Kernel::KThread* current_thread = scheduler.GetSchedulerCurrentThread(); if (idle_count >= 4 || from_running_enviroment) { if (!from_running_enviroment) { system.CoreTiming().Idle(); @@ -258,7 +184,7 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) { } current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); system.CoreTiming().ResetTicks(); - scheduler.Unload(scheduler.GetCurrentThread()); + scheduler.Unload(scheduler.GetSchedulerCurrentThread()); auto& next_scheduler = kernel.Scheduler(current_core); Common::Fiber::YieldTo(current_thread->GetHostContext(), *next_scheduler.ControlContext()); @@ -267,47 +193,23 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) { // May have changed scheduler { auto& scheduler = system.Kernel().Scheduler(current_core); - scheduler.Reload(scheduler.GetCurrentThread()); + scheduler.Reload(scheduler.GetSchedulerCurrentThread()); if (!scheduler.IsIdle()) { idle_count = 0; } } } -void CpuManager::SingleCorePause(bool paused) { - if (!paused) { - bool all_not_barrier = false; - while (!all_not_barrier) { - all_not_barrier = !core_data[0].is_running.load() && core_data[0].initialized.load(); - } - core_data[0].enter_barrier->Set(); - if (paused_state.load()) { - bool all_barrier = false; - while (!all_barrier) { - all_barrier = core_data[0].is_paused.load() && core_data[0].initialized.load(); - } - core_data[0].exit_barrier->Set(); - } - } else { - /// Wait until all cores are paused. - bool all_barrier = false; - while (!all_barrier) { - all_barrier = core_data[0].is_paused.load() && core_data[0].initialized.load(); - } - /// Don't release the barrier - } - paused_state = paused; -} +void CpuManager::ShutdownThread() { + auto& kernel = system.Kernel(); + auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0; + auto* current_thread = kernel.GetCurrentEmuThread(); -void CpuManager::Pause(bool paused) { - if (is_multicore) { - MultiCorePause(paused); - } else { - SingleCorePause(paused); - } + Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context); + UNREACHABLE(); } -void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { +void CpuManager::RunThread(std::size_t core) { /// Initialization system.RegisterCoreThread(core); std::string name; @@ -320,45 +222,24 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { Common::SetCurrentThreadName(name.c_str()); Common::SetCurrentThreadPriority(Common::ThreadPriority::High); auto& data = core_data[core]; - data.enter_barrier = std::make_unique<Common::Event>(); - data.exit_barrier = std::make_unique<Common::Event>(); data.host_context = Common::Fiber::ThreadToFiber(); - data.is_running = false; - data.initialized = true; - const bool sc_sync = !is_async_gpu && !is_multicore; - bool sc_sync_first_use = sc_sync; // Cleanup SCOPE_EXIT({ data.host_context->Exit(); - data.enter_barrier.reset(); - data.exit_barrier.reset(); - data.initialized = false; MicroProfileOnThreadExit(); }); - /// Running - while (running_mode) { - data.is_running = false; - data.enter_barrier->Wait(); - if (sc_sync_first_use) { - system.GPU().ObtainContext(); - sc_sync_first_use = false; - } - - // Emulation was stopped - if (stop_token.stop_requested()) { - return; - } + // Running + gpu_barrier->Sync(); - auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); - data.is_running = true; - Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext()); - data.is_running = false; - data.is_paused = true; - data.exit_barrier->Wait(); - data.is_paused = false; + if (!is_async_gpu && !is_multicore) { + system.GPU().ObtainContext(); } + + auto* current_thread = system.Kernel().CurrentScheduler()->GetIdleThread(); + Kernel::SetCurrentThread(system.Kernel(), current_thread); + Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext()); } } // namespace Core |