diff options
| author | 2020-01-25 18:55:32 -0400 | |
|---|---|---|
| committer | 2020-01-25 18:55:32 -0400 | |
| commit | 4d6a86b03fe6ae0d98838a21613b66d5196150af (patch) | |
| tree | 21f4b8e63e6435b2d816936af8b494882a3cdfb2 /src/core/core_cpu.cpp | |
| parent | Kernel: Implement Physical Core. (diff) | |
| download | yuzu-4d6a86b03fe6ae0d98838a21613b66d5196150af.tar.gz yuzu-4d6a86b03fe6ae0d98838a21613b66d5196150af.tar.xz yuzu-4d6a86b03fe6ae0d98838a21613b66d5196150af.zip | |
Core: Refactor CPU Management.
This commit moves ARM Interface and Scheduler handling into the kernel.
Diffstat (limited to 'src/core/core_cpu.cpp')
| -rw-r--r-- | src/core/core_cpu.cpp | 76 |
1 files changed, 10 insertions, 66 deletions
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 630cd4feb..bcfdf0198 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #include "core/core.h" | 14 | #include "core/core.h" |
| 15 | #include "core/core_cpu.h" | 15 | #include "core/core_cpu.h" |
| 16 | #include "core/core_timing.h" | 16 | #include "core/core_timing.h" |
| 17 | #include "core/hle/kernel/kernel.h" | ||
| 18 | #include "core/hle/kernel/physical_core.h" | ||
| 17 | #include "core/hle/kernel/scheduler.h" | 19 | #include "core/hle/kernel/scheduler.h" |
| 18 | #include "core/hle/kernel/thread.h" | 20 | #include "core/hle/kernel/thread.h" |
| 19 | #include "core/hle/lock.h" | 21 | #include "core/hle/lock.h" |
| @@ -21,68 +23,15 @@ | |||
| 21 | 23 | ||
| 22 | namespace Core { | 24 | namespace Core { |
| 23 | 25 | ||
| 24 | void CpuBarrier::NotifyEnd() { | 26 | Cpu::Cpu(System& system, std::size_t core_index) |
| 25 | std::unique_lock lock{mutex}; | 27 | : global_scheduler{system.GlobalScheduler()}, |
| 26 | end = true; | 28 | physical_core{system.Kernel().PhysicalCore(core_index)}, core_timing{system.CoreTiming()}, |
| 27 | condition.notify_all(); | 29 | core_index{core_index} { |
| 28 | } | ||
| 29 | |||
| 30 | bool CpuBarrier::Rendezvous() { | ||
| 31 | if (!Settings::values.use_multi_core) { | ||
| 32 | // Meaningless when running in single-core mode | ||
| 33 | return true; | ||
| 34 | } | ||
| 35 | |||
| 36 | if (!end) { | ||
| 37 | std::unique_lock lock{mutex}; | ||
| 38 | |||
| 39 | --cores_waiting; | ||
| 40 | if (!cores_waiting) { | ||
| 41 | cores_waiting = NUM_CPU_CORES; | ||
| 42 | condition.notify_all(); | ||
| 43 | return true; | ||
| 44 | } | ||
| 45 | |||
| 46 | condition.wait(lock); | ||
| 47 | return true; | ||
| 48 | } | ||
| 49 | |||
| 50 | return false; | ||
| 51 | } | ||
| 52 | |||
| 53 | Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, | ||
| 54 | std::size_t core_index) | ||
| 55 | : cpu_barrier{cpu_barrier}, global_scheduler{system.GlobalScheduler()}, | ||
| 56 | core_timing{system.CoreTiming()}, core_index{core_index} { | ||
| 57 | #ifdef ARCHITECTURE_x86_64 | ||
| 58 | arm_interface = std::make_unique<ARM_Dynarmic>(system, exclusive_monitor, core_index); | ||
| 59 | #else | ||
| 60 | arm_interface = std::make_unique<ARM_Unicorn>(system); | ||
| 61 | LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); | ||
| 62 | #endif | ||
| 63 | |||
| 64 | scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index); | ||
| 65 | } | 30 | } |
| 66 | 31 | ||
| 67 | Cpu::~Cpu() = default; | 32 | Cpu::~Cpu() = default; |
| 68 | 33 | ||
| 69 | std::unique_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor( | ||
| 70 | [[maybe_unused]] Memory::Memory& memory, [[maybe_unused]] std::size_t num_cores) { | ||
| 71 | #ifdef ARCHITECTURE_x86_64 | ||
| 72 | return std::make_unique<DynarmicExclusiveMonitor>(memory, num_cores); | ||
| 73 | #else | ||
| 74 | // TODO(merry): Passthrough exclusive monitor | ||
| 75 | return nullptr; | ||
| 76 | #endif | ||
| 77 | } | ||
| 78 | |||
| 79 | void Cpu::RunLoop(bool tight_loop) { | 34 | void Cpu::RunLoop(bool tight_loop) { |
| 80 | // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step | ||
| 81 | if (!cpu_barrier.Rendezvous()) { | ||
| 82 | // If rendezvous failed, session has been killed | ||
| 83 | return; | ||
| 84 | } | ||
| 85 | |||
| 86 | Reschedule(); | 35 | Reschedule(); |
| 87 | 36 | ||
| 88 | // If we don't have a currently active thread then don't execute instructions, | 37 | // If we don't have a currently active thread then don't execute instructions, |
| @@ -92,12 +41,10 @@ void Cpu::RunLoop(bool tight_loop) { | |||
| 92 | core_timing.Idle(); | 41 | core_timing.Idle(); |
| 93 | } else { | 42 | } else { |
| 94 | if (tight_loop) { | 43 | if (tight_loop) { |
| 95 | arm_interface->Run(); | 44 | physical_core.Run(); |
| 96 | } else { | 45 | } else { |
| 97 | arm_interface->Step(); | 46 | physical_core.Step(); |
| 98 | } | 47 | } |
| 99 | // We are stopping a run, exclusive state must be cleared | ||
| 100 | arm_interface->ClearExclusiveState(); | ||
| 101 | } | 48 | } |
| 102 | core_timing.Advance(); | 49 | core_timing.Advance(); |
| 103 | 50 | ||
| @@ -109,7 +56,7 @@ void Cpu::SingleStep() { | |||
| 109 | } | 56 | } |
| 110 | 57 | ||
| 111 | void Cpu::PrepareReschedule() { | 58 | void Cpu::PrepareReschedule() { |
| 112 | arm_interface->PrepareReschedule(); | 59 | physical_core.Stop(); |
| 113 | } | 60 | } |
| 114 | 61 | ||
| 115 | void Cpu::Reschedule() { | 62 | void Cpu::Reschedule() { |
| @@ -117,11 +64,8 @@ void Cpu::Reschedule() { | |||
| 117 | std::lock_guard lock(HLE::g_hle_lock); | 64 | std::lock_guard lock(HLE::g_hle_lock); |
| 118 | 65 | ||
| 119 | global_scheduler.SelectThread(core_index); | 66 | global_scheduler.SelectThread(core_index); |
| 120 | scheduler->TryDoContextSwitch(); | ||
| 121 | } | ||
| 122 | 67 | ||
| 123 | void Cpu::Shutdown() { | 68 | physical_core.Scheduler().TryDoContextSwitch(); |
| 124 | scheduler->Shutdown(); | ||
| 125 | } | 69 | } |
| 126 | 70 | ||
| 127 | } // namespace Core | 71 | } // namespace Core |