summaryrefslogtreecommitdiff
path: root/src/core/core_cpu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/core_cpu.cpp')
-rw-r--r--src/core/core_cpu.cpp127
1 files changed, 0 insertions, 127 deletions
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
deleted file mode 100644
index 630cd4feb..000000000
--- a/src/core/core_cpu.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <condition_variable>
6#include <mutex>
7
8#include "common/logging/log.h"
9#ifdef ARCHITECTURE_x86_64
10#include "core/arm/dynarmic/arm_dynarmic.h"
11#endif
12#include "core/arm/exclusive_monitor.h"
13#include "core/arm/unicorn/arm_unicorn.h"
14#include "core/core.h"
15#include "core/core_cpu.h"
16#include "core/core_timing.h"
17#include "core/hle/kernel/scheduler.h"
18#include "core/hle/kernel/thread.h"
19#include "core/hle/lock.h"
20#include "core/settings.h"
21
22namespace Core {
23
24void CpuBarrier::NotifyEnd() {
25 std::unique_lock lock{mutex};
26 end = true;
27 condition.notify_all();
28}
29
30bool 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
53Cpu::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}
66
67Cpu::~Cpu() = default;
68
69std::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
79void 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();
87
88 // If we don't have a currently active thread then don't execute instructions,
89 // instead advance to the next event and try to yield to the next thread
90 if (Kernel::GetCurrentThread() == nullptr) {
91 LOG_TRACE(Core, "Core-{} idling", core_index);
92 core_timing.Idle();
93 } else {
94 if (tight_loop) {
95 arm_interface->Run();
96 } else {
97 arm_interface->Step();
98 }
99 // We are stopping a run, exclusive state must be cleared
100 arm_interface->ClearExclusiveState();
101 }
102 core_timing.Advance();
103
104 Reschedule();
105}
106
107void Cpu::SingleStep() {
108 return RunLoop(false);
109}
110
111void Cpu::PrepareReschedule() {
112 arm_interface->PrepareReschedule();
113}
114
115void Cpu::Reschedule() {
116 // Lock the global kernel mutex when we manipulate the HLE state
117 std::lock_guard lock(HLE::g_hle_lock);
118
119 global_scheduler.SelectThread(core_index);
120 scheduler->TryDoContextSwitch();
121}
122
123void Cpu::Shutdown() {
124 scheduler->Shutdown();
125}
126
127} // namespace Core