From 559024593086d04e24a99a9f77490a3f97cf952d Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 1 May 2018 22:21:38 -0400 Subject: core: Move common CPU core things to its own class. --- src/core/core.cpp | 57 +++++++++---------------------------------------------- 1 file changed, 9 insertions(+), 48 deletions(-) (limited to 'src/core/core.cpp') diff --git a/src/core/core.cpp b/src/core/core.cpp index 9e2229d02..0af78c18c 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -5,10 +5,6 @@ #include #include #include "common/logging/log.h" -#ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic.h" -#endif -#include "core/arm/unicorn/arm_unicorn.h" #include "core/core.h" #include "core/core_timing.h" #include "core/gdbstub/gdbstub.h" @@ -33,9 +29,6 @@ System::~System() = default; System::ResultStatus System::RunLoop(bool tight_loop) { status = ResultStatus::Success; - if (!cpu_core) { - return ResultStatus::ErrorNotInitialized; - } if (GDBStub::IsServerEnabled()) { GDBStub::HandlePacket(); @@ -52,24 +45,7 @@ System::ResultStatus System::RunLoop(bool tight_loop) { } } - // If we don't have a currently active thread then don't execute instructions, - // instead advance to the next event and try to yield to the next thread - if (Kernel::GetCurrentThread() == nullptr) { - NGLOG_TRACE(Core_ARM, "Idling"); - CoreTiming::Idle(); - CoreTiming::Advance(); - PrepareReschedule(); - } else { - CoreTiming::Advance(); - if (tight_loop) { - cpu_core->Run(); - } else { - cpu_core->Step(); - } - } - - HW::Update(); - Reschedule(); + cpu_cores[0]->RunLoop(tight_loop); return status; } @@ -133,23 +109,13 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file } void System::PrepareReschedule() { - cpu_core->PrepareReschedule(); - reschedule_pending = true; + cpu_cores[0]->PrepareReschedule(); } PerfStats::Results System::GetAndResetPerfStats() { return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); } -void System::Reschedule() { - if (!reschedule_pending) { - return; - } - - reschedule_pending = false; - Core::System::GetInstance().Scheduler().Reschedule(); -} - System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { NGLOG_DEBUG(HW_Memory, "initialized OK"); @@ -157,15 +123,8 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { current_process = Kernel::Process::Create("main"); - if (Settings::values.use_cpu_jit) { -#ifdef ARCHITECTURE_x86_64 - cpu_core = std::make_shared(); -#else - cpu_core = std::make_shared(); - NGLOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); -#endif - } else { - cpu_core = std::make_shared(); + for (auto& cpu_core : cpu_cores) { + cpu_core = std::make_unique(); } gpu_core = std::make_unique(); @@ -176,7 +135,6 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { HW::Init(); Kernel::Init(system_mode); - scheduler = std::make_unique(cpu_core.get()); Service::Init(service_manager); GDBStub::Init(); @@ -207,13 +165,16 @@ void System::Shutdown() { VideoCore::Shutdown(); GDBStub::Shutdown(); Service::Shutdown(); - scheduler.reset(); Kernel::Shutdown(); HW::Shutdown(); service_manager.reset(); telemetry_session.reset(); gpu_core.reset(); - cpu_core.reset(); + + for (auto& cpu_core : cpu_cores) { + cpu_core.reset(); + } + CoreTiming::Shutdown(); app_loader.reset(); -- cgit v1.2.3 From 9776ff91797423a9cf19571faafe4648fb5a1d1d Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 2 May 2018 21:26:14 -0400 Subject: core: Create a thread for each CPU core, keep in lock-step with a barrier. --- src/core/core.cpp | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'src/core/core.cpp') diff --git a/src/core/core.cpp b/src/core/core.cpp index 0af78c18c..066423f23 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -27,6 +27,13 @@ namespace Core { System::~System() = default; +/// Runs a CPU core while the system is powered on +static void RunCpuCore(std::shared_ptr cpu_state) { + while (Core::System().GetInstance().IsPoweredOn()) { + cpu_state->RunLoop(true); + } +} + System::ResultStatus System::RunLoop(bool tight_loop) { status = ResultStatus::Success; @@ -109,7 +116,7 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file } void System::PrepareReschedule() { - cpu_cores[0]->PrepareReschedule(); + CurrentCpuCore().PrepareReschedule(); } PerfStats::Results System::GetAndResetPerfStats() { @@ -123,14 +130,13 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { current_process = Kernel::Process::Create("main"); - for (auto& cpu_core : cpu_cores) { - cpu_core = std::make_unique(); + cpu_barrier = std::make_shared(); + for (size_t index = 0; index < cpu_cores.size(); ++index) { + cpu_cores[index] = std::make_shared(cpu_barrier, index); } gpu_core = std::make_unique(); - telemetry_session = std::make_unique(); - service_manager = std::make_shared(); HW::Init(); @@ -142,6 +148,14 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { return ResultStatus::ErrorVideoCore; } + // Create threads for CPU cores 1-3, and build thread_to_cpu map + // CPU core 0 is run on the main thread + thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; + for (size_t index = 0; index < cpu_core_threads.size(); ++index) { + cpu_core_threads[index] = std::make_unique(RunCpuCore, cpu_cores[index + 1]); + thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; + } + NGLOG_DEBUG(Core, "Initialized OK"); // Reset counters and set time origin to current frame @@ -171,9 +185,15 @@ void System::Shutdown() { telemetry_session.reset(); gpu_core.reset(); + // Close all CPU/threading state + thread_to_cpu.clear(); for (auto& cpu_core : cpu_cores) { cpu_core.reset(); } + for (auto& thread : cpu_core_threads) { + thread->join(); + thread.reset(); + } CoreTiming::Shutdown(); -- cgit v1.2.3 From cba69fdcd439c5f225bbddf1dad70e6326edd0dc Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 3 May 2018 00:16:12 -0400 Subject: core: Support session close with multicore. --- src/core/core.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src/core/core.cpp') diff --git a/src/core/core.cpp b/src/core/core.cpp index 066423f23..1e6be34c8 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -37,6 +37,9 @@ static void RunCpuCore(std::shared_ptr cpu_state) { System::ResultStatus System::RunLoop(bool tight_loop) { status = ResultStatus::Success; + // Update thread_to_cpu in case Core 0 is run from a different host thread + thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; + if (GDBStub::IsServerEnabled()) { GDBStub::HandlePacket(); @@ -186,17 +189,21 @@ void System::Shutdown() { gpu_core.reset(); // Close all CPU/threading state - thread_to_cpu.clear(); - for (auto& cpu_core : cpu_cores) { - cpu_core.reset(); - } + cpu_barrier->NotifyEnd(); for (auto& thread : cpu_core_threads) { thread->join(); thread.reset(); } + thread_to_cpu.clear(); + for (auto& cpu_core : cpu_cores) { + cpu_core.reset(); + } + cpu_barrier.reset(); + // Close core timing CoreTiming::Shutdown(); + // Close app loader app_loader.reset(); NGLOG_DEBUG(Core, "Shutdown OK"); -- cgit v1.2.3 From 9bf2a428f9e9359763be1bfd90c32371044c711e Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 3 May 2018 00:34:54 -0400 Subject: core: Add a configuration setting for use_multi_core. --- src/core/core.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'src/core/core.cpp') diff --git a/src/core/core.cpp b/src/core/core.cpp index 1e6be34c8..59c8940f7 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -126,6 +126,21 @@ PerfStats::Results System::GetAndResetPerfStats() { return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); } +const std::shared_ptr& System::Scheduler(size_t core_index) { + if (!Settings::values.use_multi_core) { + // Always use Core 0 scheduler when multicore is disabled + return cpu_cores[0]->Scheduler(); + } + + ASSERT(core_index < NUM_CPU_CORES); + return cpu_cores[core_index]->Scheduler(); +} + +ARM_Interface& System::ArmInterface(size_t core_index) { + ASSERT(core_index < NUM_CPU_CORES); + return cpu_cores[core_index]->ArmInterface(); +} + System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { NGLOG_DEBUG(HW_Memory, "initialized OK"); @@ -154,9 +169,12 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { // Create threads for CPU cores 1-3, and build thread_to_cpu map // CPU core 0 is run on the main thread thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; - for (size_t index = 0; index < cpu_core_threads.size(); ++index) { - cpu_core_threads[index] = std::make_unique(RunCpuCore, cpu_cores[index + 1]); - thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; + if (Settings::values.use_multi_core) { + for (size_t index = 0; index < cpu_core_threads.size(); ++index) { + cpu_core_threads[index] = + std::make_unique(RunCpuCore, cpu_cores[index + 1]); + thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; + } } NGLOG_DEBUG(Core, "Initialized OK"); @@ -190,9 +208,11 @@ void System::Shutdown() { // Close all CPU/threading state cpu_barrier->NotifyEnd(); - for (auto& thread : cpu_core_threads) { - thread->join(); - thread.reset(); + if (Settings::values.use_multi_core) { + for (auto& thread : cpu_core_threads) { + thread->join(); + thread.reset(); + } } thread_to_cpu.clear(); for (auto& cpu_core : cpu_cores) { -- cgit v1.2.3 From 8aa5d25f826c8969a1e9938d8c8e12fa6df8be82 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 5 May 2018 23:54:43 -0400 Subject: threading: Reschedule only on cores that are necessary. --- src/core/core.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core/core.cpp') diff --git a/src/core/core.cpp b/src/core/core.cpp index 59c8940f7..6cbfc3035 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -141,6 +141,11 @@ ARM_Interface& System::ArmInterface(size_t core_index) { return cpu_cores[core_index]->ArmInterface(); } +Cpu& System::CpuCore(size_t core_index) { + ASSERT(core_index < NUM_CPU_CORES); + return *cpu_cores[core_index]; +} + System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { NGLOG_DEBUG(HW_Memory, "initialized OK"); -- cgit v1.2.3 From edc52250b8157a9d2b8c909225114c98c7ea609e Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 7 May 2018 22:57:39 -0400 Subject: core: Run all CPU cores separately, even in single-thread mode. --- src/core/core.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'src/core/core.cpp') diff --git a/src/core/core.cpp b/src/core/core.cpp index 6cbfc3035..84ab876cc 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -34,6 +34,19 @@ static void RunCpuCore(std::shared_ptr cpu_state) { } } +Cpu& System::CurrentCpuCore() { + // If multicore is enabled, use host thread to figure out the current CPU core + if (Settings::values.use_multi_core) { + const auto& search = thread_to_cpu.find(std::this_thread::get_id()); + ASSERT(search != thread_to_cpu.end()); + ASSERT(search->second); + return *search->second; + } + + // Otherwise, use single-threaded mode active_core variable + return *cpu_cores[active_core]; +} + System::ResultStatus System::RunLoop(bool tight_loop) { status = ResultStatus::Success; @@ -55,7 +68,13 @@ System::ResultStatus System::RunLoop(bool tight_loop) { } } - cpu_cores[0]->RunLoop(tight_loop); + for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) { + cpu_cores[active_core]->RunLoop(tight_loop); + if (Settings::values.use_multi_core) { + // Cores 1-3 are run on other threads in this mode + break; + } + } return status; } @@ -127,11 +146,6 @@ PerfStats::Results System::GetAndResetPerfStats() { } const std::shared_ptr& System::Scheduler(size_t core_index) { - if (!Settings::values.use_multi_core) { - // Always use Core 0 scheduler when multicore is disabled - return cpu_cores[0]->Scheduler(); - } - ASSERT(core_index < NUM_CPU_CORES); return cpu_cores[core_index]->Scheduler(); } -- cgit v1.2.3