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_cpu.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/core/core_cpu.cpp (limited to 'src/core/core_cpu.cpp') diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp new file mode 100644 index 000000000..81c0e212d --- /dev/null +++ b/src/core/core_cpu.cpp @@ -0,0 +1,72 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#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_cpu.h" +#include "core/core_timing.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/scheduler.h" +#include "core/hle/kernel/thread.h" +#include "core/settings.h" + +namespace Core { + +Cpu::Cpu() { + if (Settings::values.use_cpu_jit) { +#ifdef ARCHITECTURE_x86_64 + arm_interface = std::make_shared(); +#else + cpu_core = std::make_shared(); + NGLOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); +#endif + } else { + arm_interface = std::make_shared(); + } + + scheduler = std::make_unique(arm_interface.get()); +} + +void Cpu::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, "Idling"); + CoreTiming::Idle(); + CoreTiming::Advance(); + PrepareReschedule(); + } else { + CoreTiming::Advance(); + if (tight_loop) { + arm_interface->Run(); + } else { + arm_interface->Step(); + } + } + + Reschedule(); +} + +void Cpu::SingleStep() { + return RunLoop(false); +} + +void Cpu::PrepareReschedule() { + arm_interface->PrepareReschedule(); + reschedule_pending = true; +} + +void Cpu::Reschedule() { + if (!reschedule_pending) { + return; + } + + reschedule_pending = false; + scheduler->Reschedule(); +} + +} // namespace Core -- 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_cpu.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'src/core/core_cpu.cpp') diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 81c0e212d..6bdfdd7df 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include + #include "common/logging/log.h" #ifdef ARCHITECTURE_x86_64 #include "core/arm/dynarmic/arm_dynarmic.h" @@ -16,7 +19,9 @@ namespace Core { -Cpu::Cpu() { +Cpu::Cpu(std::shared_ptr cpu_barrier, size_t core_index) + : cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} { + if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 arm_interface = std::make_shared(); @@ -32,15 +37,25 @@ Cpu::Cpu() { } void Cpu::RunLoop(bool tight_loop) { + // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step + cpu_barrier->Rendezvous(); + // 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, "Idling"); - CoreTiming::Idle(); - CoreTiming::Advance(); + NGLOG_TRACE(Core, "Core-{} idling", core_index); + + if (IsMainCore()) { + CoreTiming::Idle(); + CoreTiming::Advance(); + } + PrepareReschedule(); } else { - CoreTiming::Advance(); + if (IsMainCore()) { + CoreTiming::Advance(); + } + if (tight_loop) { arm_interface->Run(); } else { -- cgit v1.2.3 From a434fdcb102e96ddf564dc0973d7073d49bf19fc Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 2 May 2018 22:36:51 -0400 Subject: core: Implement multicore support. --- src/core/core_cpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/core_cpu.cpp') diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 6bdfdd7df..a556f12e9 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -33,7 +33,7 @@ Cpu::Cpu(std::shared_ptr cpu_barrier, size_t core_index) arm_interface = std::make_shared(); } - scheduler = std::make_unique(arm_interface.get()); + scheduler = std::make_shared(arm_interface.get()); } void Cpu::RunLoop(bool tight_loop) { -- 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_cpu.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'src/core/core_cpu.cpp') diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index a556f12e9..bd9869d28 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -19,6 +19,30 @@ namespace Core { +void CpuBarrier::NotifyEnd() { + std::unique_lock lock(mutex); + end = true; + condition.notify_all(); +} + +bool CpuBarrier::Rendezvous() { + if (end) { + return false; + } else { + std::unique_lock lock(mutex); + + --cores_waiting; + if (!cores_waiting) { + cores_waiting = NUM_CPU_CORES; + condition.notify_all(); + return true; + } + + condition.wait(lock); + return true; + } +} + Cpu::Cpu(std::shared_ptr cpu_barrier, size_t core_index) : cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} { @@ -38,7 +62,10 @@ Cpu::Cpu(std::shared_ptr cpu_barrier, size_t core_index) void Cpu::RunLoop(bool tight_loop) { // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step - cpu_barrier->Rendezvous(); + if (!cpu_barrier->Rendezvous()) { + // If rendezvous failed, session has been killed + return; + } // 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 -- 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_cpu.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/core/core_cpu.cpp') diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index bd9869d28..099f2bb1a 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -26,9 +26,12 @@ void CpuBarrier::NotifyEnd() { } bool CpuBarrier::Rendezvous() { - if (end) { - return false; - } else { + if (!Settings::values.use_multi_core) { + // Meaningless when running in single-core mode + return true; + } + + if (!end) { std::unique_lock lock(mutex); --cores_waiting; @@ -41,6 +44,8 @@ bool CpuBarrier::Rendezvous() { condition.wait(lock); return true; } + + return false; } Cpu::Cpu(std::shared_ptr cpu_barrier, size_t core_index) -- cgit v1.2.3