summaryrefslogtreecommitdiff
path: root/src/core/cpu_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/cpu_manager.cpp')
-rw-r--r--src/core/cpu_manager.cpp161
1 files changed, 61 insertions, 100 deletions
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 37d3d83b9..428194129 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -8,6 +8,7 @@
8#include "core/core.h" 8#include "core/core.h"
9#include "core/core_timing.h" 9#include "core/core_timing.h"
10#include "core/cpu_manager.h" 10#include "core/cpu_manager.h"
11#include "core/hle/kernel/k_interrupt_manager.h"
11#include "core/hle/kernel/k_scheduler.h" 12#include "core/hle/kernel/k_scheduler.h"
12#include "core/hle/kernel/k_thread.h" 13#include "core/hle/kernel/k_thread.h"
13#include "core/hle/kernel/kernel.h" 14#include "core/hle/kernel/kernel.h"
@@ -41,44 +42,65 @@ void CpuManager::Shutdown() {
41 } 42 }
42} 43}
43 44
44void CpuManager::GuestThreadFunction() { 45void CpuManager::GuestActivateFunction() {
45 if (is_multicore) { 46 if (is_multicore) {
46 MultiCoreRunGuestThread(); 47 MultiCoreGuestActivate();
47 } else { 48 } else {
48 SingleCoreRunGuestThread(); 49 SingleCoreGuestActivate();
49 } 50 }
50} 51}
51 52
52void CpuManager::GuestRewindFunction() { 53void CpuManager::GuestThreadFunction() {
53 if (is_multicore) { 54 if (is_multicore) {
54 MultiCoreRunGuestLoop(); 55 MultiCoreRunGuestThread();
55 } else { 56 } else {
56 SingleCoreRunGuestLoop(); 57 SingleCoreRunGuestThread();
57 } 58 }
58} 59}
59 60
60void CpuManager::IdleThreadFunction() { 61void CpuManager::ShutdownThreadFunction() {
61 if (is_multicore) { 62 ShutdownThread();
62 MultiCoreRunIdleThread(); 63}
63 } else { 64
64 SingleCoreRunIdleThread(); 65void CpuManager::WaitForAndHandleInterrupt() {
66 auto& kernel = system.Kernel();
67 auto& physical_core = kernel.CurrentPhysicalCore();
68
69 ASSERT(Kernel::GetCurrentThread(kernel).GetDisableDispatchCount() == 1);
70
71 if (!physical_core.IsInterrupted()) {
72 physical_core.Idle();
65 } 73 }
74
75 HandleInterrupt();
66} 76}
67 77
68void CpuManager::ShutdownThreadFunction() { 78void CpuManager::HandleInterrupt() {
69 ShutdownThread(); 79 auto& kernel = system.Kernel();
80 auto core_index = kernel.CurrentPhysicalCoreIndex();
81
82 Kernel::KInterruptManager::HandleInterrupt(kernel, static_cast<s32>(core_index));
70} 83}
71 84
72/////////////////////////////////////////////////////////////////////////////// 85///////////////////////////////////////////////////////////////////////////////
73/// MultiCore /// 86/// MultiCore ///
74/////////////////////////////////////////////////////////////////////////////// 87///////////////////////////////////////////////////////////////////////////////
75 88
89void CpuManager::MultiCoreGuestActivate() {
90 // Similar to the HorizonKernelMain callback in HOS
91 auto& kernel = system.Kernel();
92 auto* scheduler = kernel.CurrentScheduler();
93
94 scheduler->Activate();
95 UNREACHABLE();
96}
97
76void CpuManager::MultiCoreRunGuestThread() { 98void CpuManager::MultiCoreRunGuestThread() {
99 // Similar to UserModeThreadStarter in HOS
77 auto& kernel = system.Kernel(); 100 auto& kernel = system.Kernel();
78 kernel.CurrentScheduler()->OnThreadStart(); 101 auto* thread = kernel.GetCurrentEmuThread();
79 auto* thread = kernel.CurrentScheduler()->GetSchedulerCurrentThread(); 102 thread->EnableDispatch();
80 auto& host_context = thread->GetHostContext(); 103
81 host_context->SetRewindPoint([this] { GuestRewindFunction(); });
82 MultiCoreRunGuestLoop(); 104 MultiCoreRunGuestLoop();
83} 105}
84 106
@@ -91,18 +113,8 @@ void CpuManager::MultiCoreRunGuestLoop() {
91 physical_core->Run(); 113 physical_core->Run();
92 physical_core = &kernel.CurrentPhysicalCore(); 114 physical_core = &kernel.CurrentPhysicalCore();
93 } 115 }
94 {
95 Kernel::KScopedDisableDispatch dd(kernel);
96 physical_core->ArmInterface().ClearExclusiveState();
97 }
98 }
99}
100 116
101void CpuManager::MultiCoreRunIdleThread() { 117 HandleInterrupt();
102 auto& kernel = system.Kernel();
103 while (true) {
104 Kernel::KScopedDisableDispatch dd(kernel);
105 kernel.CurrentPhysicalCore().Idle();
106 } 118 }
107} 119}
108 120
@@ -110,83 +122,20 @@ void CpuManager::MultiCoreRunIdleThread() {
110/// SingleCore /// 122/// SingleCore ///
111/////////////////////////////////////////////////////////////////////////////// 123///////////////////////////////////////////////////////////////////////////////
112 124
113void CpuManager::SingleCoreRunGuestThread() { 125void CpuManager::SingleCoreGuestActivate() {}
114 auto& kernel = system.Kernel();
115 kernel.CurrentScheduler()->OnThreadStart();
116 auto* thread = kernel.CurrentScheduler()->GetSchedulerCurrentThread();
117 auto& host_context = thread->GetHostContext();
118 host_context->SetRewindPoint([this] { GuestRewindFunction(); });
119 SingleCoreRunGuestLoop();
120}
121
122void CpuManager::SingleCoreRunGuestLoop() {
123 auto& kernel = system.Kernel();
124 while (true) {
125 auto* physical_core = &kernel.CurrentPhysicalCore();
126 if (!physical_core->IsInterrupted()) {
127 physical_core->Run();
128 physical_core = &kernel.CurrentPhysicalCore();
129 }
130 kernel.SetIsPhantomModeForSingleCore(true);
131 system.CoreTiming().Advance();
132 kernel.SetIsPhantomModeForSingleCore(false);
133 physical_core->ArmInterface().ClearExclusiveState();
134 PreemptSingleCore();
135 auto& scheduler = kernel.Scheduler(current_core);
136 scheduler.RescheduleCurrentCore();
137 }
138}
139
140void CpuManager::SingleCoreRunIdleThread() {
141 auto& kernel = system.Kernel();
142 while (true) {
143 auto& physical_core = kernel.CurrentPhysicalCore();
144 PreemptSingleCore(false);
145 system.CoreTiming().AddTicks(1000U);
146 idle_count++;
147 auto& scheduler = physical_core.Scheduler();
148 scheduler.RescheduleCurrentCore();
149 }
150}
151 126
152void CpuManager::PreemptSingleCore(bool from_running_enviroment) { 127void CpuManager::SingleCoreRunGuestThread() {}
153 {
154 auto& kernel = system.Kernel();
155 auto& scheduler = kernel.Scheduler(current_core);
156 Kernel::KThread* current_thread = scheduler.GetSchedulerCurrentThread();
157 if (idle_count >= 4 || from_running_enviroment) {
158 if (!from_running_enviroment) {
159 system.CoreTiming().Idle();
160 idle_count = 0;
161 }
162 kernel.SetIsPhantomModeForSingleCore(true);
163 system.CoreTiming().Advance();
164 kernel.SetIsPhantomModeForSingleCore(false);
165 }
166 current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES);
167 system.CoreTiming().ResetTicks();
168 scheduler.Unload(scheduler.GetSchedulerCurrentThread());
169 128
170 auto& next_scheduler = kernel.Scheduler(current_core); 129void CpuManager::SingleCoreRunGuestLoop() {}
171 Common::Fiber::YieldTo(current_thread->GetHostContext(), *next_scheduler.ControlContext());
172 }
173 130
174 // May have changed scheduler 131void CpuManager::PreemptSingleCore(bool from_running_enviroment) {}
175 {
176 auto& scheduler = system.Kernel().Scheduler(current_core);
177 scheduler.Reload(scheduler.GetSchedulerCurrentThread());
178 if (!scheduler.IsIdle()) {
179 idle_count = 0;
180 }
181 }
182}
183 132
184void CpuManager::ShutdownThread() { 133void CpuManager::ShutdownThread() {
185 auto& kernel = system.Kernel(); 134 auto& kernel = system.Kernel();
135 auto* thread = kernel.GetCurrentEmuThread();
186 auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0; 136 auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0;
187 auto* current_thread = kernel.GetCurrentEmuThread();
188 137
189 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context); 138 Common::Fiber::YieldTo(thread->GetHostContext(), *core_data[core].host_context);
190 UNREACHABLE(); 139 UNREACHABLE();
191} 140}
192 141
@@ -218,9 +167,21 @@ void CpuManager::RunThread(std::size_t core) {
218 system.GPU().ObtainContext(); 167 system.GPU().ObtainContext();
219 } 168 }
220 169
221 auto* current_thread = system.Kernel().CurrentScheduler()->GetIdleThread(); 170 auto& kernel = system.Kernel();
222 Kernel::SetCurrentThread(system.Kernel(), current_thread); 171
223 Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext()); 172 auto* main_thread = Kernel::KThread::Create(kernel);
173 main_thread->SetName(fmt::format("MainThread:{}", core));
174 ASSERT(Kernel::KThread::InitializeMainThread(system, main_thread, static_cast<s32>(core))
175 .IsSuccess());
176
177 auto* idle_thread = Kernel::KThread::Create(kernel);
178 ASSERT(Kernel::KThread::InitializeIdleThread(system, idle_thread, static_cast<s32>(core))
179 .IsSuccess());
180
181 kernel.SetCurrentEmuThread(main_thread);
182 kernel.CurrentScheduler()->Initialize(idle_thread);
183
184 Common::Fiber::YieldTo(data.host_context, *main_thread->GetHostContext());
224} 185}
225 186
226} // namespace Core 187} // namespace Core