summaryrefslogtreecommitdiff
path: root/src/core/cpu_manager.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2020-12-20 20:57:54 -0800
committerGravatar GitHub2020-12-20 20:57:54 -0800
commit1279c7ce7afd3d1bf2b4e33aa922158acf2cd060 (patch)
tree6db8088caed2bd957187e4730f51424325038fa5 /src/core/cpu_manager.cpp
parentMerge pull request #5201 from ameerj/bufferq-refactor (diff)
parenthle: kernel: Process: Various style fixes based on code review feedback. (diff)
downloadyuzu-1279c7ce7afd3d1bf2b4e33aa922158acf2cd060.tar.gz
yuzu-1279c7ce7afd3d1bf2b4e33aa922158acf2cd060.tar.xz
yuzu-1279c7ce7afd3d1bf2b4e33aa922158acf2cd060.zip
Merge pull request #5131 from bunnei/scheduler-rewrite
Rewrite Kernel scheduler based on Atmosphere
Diffstat (limited to 'src/core/cpu_manager.cpp')
-rw-r--r--src/core/cpu_manager.cpp98
1 files changed, 45 insertions, 53 deletions
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 0cff985e9..373395047 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -10,9 +10,9 @@
10#include "core/core.h" 10#include "core/core.h"
11#include "core/core_timing.h" 11#include "core/core_timing.h"
12#include "core/cpu_manager.h" 12#include "core/cpu_manager.h"
13#include "core/hle/kernel/k_scheduler.h"
13#include "core/hle/kernel/kernel.h" 14#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/physical_core.h" 15#include "core/hle/kernel/physical_core.h"
15#include "core/hle/kernel/scheduler.h"
16#include "core/hle/kernel/thread.h" 16#include "core/hle/kernel/thread.h"
17#include "video_core/gpu.h" 17#include "video_core/gpu.h"
18 18
@@ -109,11 +109,8 @@ void* CpuManager::GetStartFuncParamater() {
109 109
110void CpuManager::MultiCoreRunGuestThread() { 110void CpuManager::MultiCoreRunGuestThread() {
111 auto& kernel = system.Kernel(); 111 auto& kernel = system.Kernel();
112 { 112 kernel.CurrentScheduler()->OnThreadStart();
113 auto& sched = kernel.CurrentScheduler(); 113 auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
114 sched.OnThreadStart();
115 }
116 auto* thread = kernel.CurrentScheduler().GetCurrentThread();
117 auto& host_context = thread->GetHostContext(); 114 auto& host_context = thread->GetHostContext();
118 host_context->SetRewindPoint(GuestRewindFunction, this); 115 host_context->SetRewindPoint(GuestRewindFunction, this);
119 MultiCoreRunGuestLoop(); 116 MultiCoreRunGuestLoop();
@@ -130,8 +127,8 @@ void CpuManager::MultiCoreRunGuestLoop() {
130 physical_core = &kernel.CurrentPhysicalCore(); 127 physical_core = &kernel.CurrentPhysicalCore();
131 } 128 }
132 system.ExitDynarmicProfile(); 129 system.ExitDynarmicProfile();
133 auto& scheduler = kernel.CurrentScheduler(); 130 physical_core->ArmInterface().ClearExclusiveState();
134 scheduler.TryDoContextSwitch(); 131 kernel.CurrentScheduler()->RescheduleCurrentCore();
135 } 132 }
136} 133}
137 134
@@ -140,25 +137,21 @@ void CpuManager::MultiCoreRunIdleThread() {
140 while (true) { 137 while (true) {
141 auto& physical_core = kernel.CurrentPhysicalCore(); 138 auto& physical_core = kernel.CurrentPhysicalCore();
142 physical_core.Idle(); 139 physical_core.Idle();
143 auto& scheduler = kernel.CurrentScheduler(); 140 kernel.CurrentScheduler()->RescheduleCurrentCore();
144 scheduler.TryDoContextSwitch();
145 } 141 }
146} 142}
147 143
148void CpuManager::MultiCoreRunSuspendThread() { 144void CpuManager::MultiCoreRunSuspendThread() {
149 auto& kernel = system.Kernel(); 145 auto& kernel = system.Kernel();
150 { 146 kernel.CurrentScheduler()->OnThreadStart();
151 auto& sched = kernel.CurrentScheduler();
152 sched.OnThreadStart();
153 }
154 while (true) { 147 while (true) {
155 auto core = kernel.GetCurrentHostThreadID(); 148 auto core = kernel.GetCurrentHostThreadID();
156 auto& scheduler = kernel.CurrentScheduler(); 149 auto& scheduler = *kernel.CurrentScheduler();
157 Kernel::Thread* current_thread = scheduler.GetCurrentThread(); 150 Kernel::Thread* current_thread = scheduler.GetCurrentThread();
158 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[core].host_context); 151 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[core].host_context);
159 ASSERT(scheduler.ContextSwitchPending()); 152 ASSERT(scheduler.ContextSwitchPending());
160 ASSERT(core == kernel.GetCurrentHostThreadID()); 153 ASSERT(core == kernel.GetCurrentHostThreadID());
161 scheduler.TryDoContextSwitch(); 154 scheduler.RescheduleCurrentCore();
162 } 155 }
163} 156}
164 157
@@ -206,11 +199,8 @@ void CpuManager::MultiCorePause(bool paused) {
206 199
207void CpuManager::SingleCoreRunGuestThread() { 200void CpuManager::SingleCoreRunGuestThread() {
208 auto& kernel = system.Kernel(); 201 auto& kernel = system.Kernel();
209 { 202 kernel.CurrentScheduler()->OnThreadStart();
210 auto& sched = kernel.CurrentScheduler(); 203 auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
211 sched.OnThreadStart();
212 }
213 auto* thread = kernel.CurrentScheduler().GetCurrentThread();
214 auto& host_context = thread->GetHostContext(); 204 auto& host_context = thread->GetHostContext();
215 host_context->SetRewindPoint(GuestRewindFunction, this); 205 host_context->SetRewindPoint(GuestRewindFunction, this);
216 SingleCoreRunGuestLoop(); 206 SingleCoreRunGuestLoop();
@@ -218,7 +208,7 @@ void CpuManager::SingleCoreRunGuestThread() {
218 208
219void CpuManager::SingleCoreRunGuestLoop() { 209void CpuManager::SingleCoreRunGuestLoop() {
220 auto& kernel = system.Kernel(); 210 auto& kernel = system.Kernel();
221 auto* thread = kernel.CurrentScheduler().GetCurrentThread(); 211 auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
222 while (true) { 212 while (true) {
223 auto* physical_core = &kernel.CurrentPhysicalCore(); 213 auto* physical_core = &kernel.CurrentPhysicalCore();
224 system.EnterDynarmicProfile(); 214 system.EnterDynarmicProfile();
@@ -230,9 +220,10 @@ void CpuManager::SingleCoreRunGuestLoop() {
230 thread->SetPhantomMode(true); 220 thread->SetPhantomMode(true);
231 system.CoreTiming().Advance(); 221 system.CoreTiming().Advance();
232 thread->SetPhantomMode(false); 222 thread->SetPhantomMode(false);
223 physical_core->ArmInterface().ClearExclusiveState();
233 PreemptSingleCore(); 224 PreemptSingleCore();
234 auto& scheduler = kernel.Scheduler(current_core); 225 auto& scheduler = kernel.Scheduler(current_core);
235 scheduler.TryDoContextSwitch(); 226 scheduler.RescheduleCurrentCore();
236 } 227 }
237} 228}
238 229
@@ -244,51 +235,53 @@ void CpuManager::SingleCoreRunIdleThread() {
244 system.CoreTiming().AddTicks(1000U); 235 system.CoreTiming().AddTicks(1000U);
245 idle_count++; 236 idle_count++;
246 auto& scheduler = physical_core.Scheduler(); 237 auto& scheduler = physical_core.Scheduler();
247 scheduler.TryDoContextSwitch(); 238 scheduler.RescheduleCurrentCore();
248 } 239 }
249} 240}
250 241
251void CpuManager::SingleCoreRunSuspendThread() { 242void CpuManager::SingleCoreRunSuspendThread() {
252 auto& kernel = system.Kernel(); 243 auto& kernel = system.Kernel();
253 { 244 kernel.CurrentScheduler()->OnThreadStart();
254 auto& sched = kernel.CurrentScheduler();
255 sched.OnThreadStart();
256 }
257 while (true) { 245 while (true) {
258 auto core = kernel.GetCurrentHostThreadID(); 246 auto core = kernel.GetCurrentHostThreadID();
259 auto& scheduler = kernel.CurrentScheduler(); 247 auto& scheduler = *kernel.CurrentScheduler();
260 Kernel::Thread* current_thread = scheduler.GetCurrentThread(); 248 Kernel::Thread* current_thread = scheduler.GetCurrentThread();
261 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[0].host_context); 249 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[0].host_context);
262 ASSERT(scheduler.ContextSwitchPending()); 250 ASSERT(scheduler.ContextSwitchPending());
263 ASSERT(core == kernel.GetCurrentHostThreadID()); 251 ASSERT(core == kernel.GetCurrentHostThreadID());
264 scheduler.TryDoContextSwitch(); 252 scheduler.RescheduleCurrentCore();
265 } 253 }
266} 254}
267 255
268void CpuManager::PreemptSingleCore(bool from_running_enviroment) { 256void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
269 std::size_t old_core = current_core; 257 {
270 auto& scheduler = system.Kernel().Scheduler(old_core); 258 auto& scheduler = system.Kernel().Scheduler(current_core);
271 Kernel::Thread* current_thread = scheduler.GetCurrentThread(); 259 Kernel::Thread* current_thread = scheduler.GetCurrentThread();
272 if (idle_count >= 4 || from_running_enviroment) { 260 if (idle_count >= 4 || from_running_enviroment) {
273 if (!from_running_enviroment) { 261 if (!from_running_enviroment) {
274 system.CoreTiming().Idle(); 262 system.CoreTiming().Idle();
275 idle_count = 0; 263 idle_count = 0;
264 }
265 current_thread->SetPhantomMode(true);
266 system.CoreTiming().Advance();
267 current_thread->SetPhantomMode(false);
276 } 268 }
277 current_thread->SetPhantomMode(true); 269 current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES);
278 system.CoreTiming().Advance(); 270 system.CoreTiming().ResetTicks();
279 current_thread->SetPhantomMode(false); 271 scheduler.Unload(scheduler.GetCurrentThread());
272
273 auto& next_scheduler = system.Kernel().Scheduler(current_core);
274 Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext());
280 } 275 }
281 current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); 276
282 system.CoreTiming().ResetTicks(); 277 // May have changed scheduler
283 scheduler.Unload(); 278 {
284 auto& next_scheduler = system.Kernel().Scheduler(current_core); 279 auto& scheduler = system.Kernel().Scheduler(current_core);
285 Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext()); 280 scheduler.Reload(scheduler.GetCurrentThread());
286 /// May have changed scheduler 281 auto* currrent_thread2 = scheduler.GetCurrentThread();
287 auto& current_scheduler = system.Kernel().Scheduler(current_core); 282 if (!currrent_thread2->IsIdleThread()) {
288 current_scheduler.Reload(); 283 idle_count = 0;
289 auto* currrent_thread2 = current_scheduler.GetCurrentThread(); 284 }
290 if (!currrent_thread2->IsIdleThread()) {
291 idle_count = 0;
292 } 285 }
293} 286}
294 287
@@ -369,8 +362,7 @@ void CpuManager::RunThread(std::size_t core) {
369 return; 362 return;
370 } 363 }
371 364
372 auto& scheduler = system.Kernel().CurrentScheduler(); 365 auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
373 Kernel::Thread* current_thread = scheduler.GetCurrentThread();
374 data.is_running = true; 366 data.is_running = true;
375 Common::Fiber::YieldTo(data.host_context, current_thread->GetHostContext()); 367 Common::Fiber::YieldTo(data.host_context, current_thread->GetHostContext());
376 data.is_running = false; 368 data.is_running = false;