summaryrefslogtreecommitdiff
path: root/src/core/cpu_manager.cpp
diff options
context:
space:
mode:
authorGravatar Levi2021-01-10 22:09:56 -0700
committerGravatar Levi2021-01-10 22:09:56 -0700
commit7a3c884e39fccfbb498b855080bffabc9ce2e7f1 (patch)
tree5056f9406dec188439cb0deb87603498243a9412 /src/core/cpu_manager.cpp
parentMore forgetting... duh (diff)
parentMerge pull request #5229 from Morph1984/fullscreen-opt (diff)
downloadyuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.gz
yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.xz
yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.zip
Merge remote-tracking branch 'upstream/master' into int-flags
Diffstat (limited to 'src/core/cpu_manager.cpp')
-rw-r--r--src/core/cpu_manager.cpp133
1 files changed, 69 insertions, 64 deletions
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 688b99eba..373395047 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -4,15 +4,15 @@
4 4
5#include "common/fiber.h" 5#include "common/fiber.h"
6#include "common/microprofile.h" 6#include "common/microprofile.h"
7#include "common/scope_exit.h"
7#include "common/thread.h" 8#include "common/thread.h"
8#include "core/arm/exclusive_monitor.h" 9#include "core/arm/exclusive_monitor.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/core_timing.h" 11#include "core/core_timing.h"
11#include "core/cpu_manager.h" 12#include "core/cpu_manager.h"
12#include "core/gdbstub/gdbstub.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,28 +109,26 @@ 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(); 114 auto& host_context = thread->GetHostContext();
115 } 115 host_context->SetRewindPoint(GuestRewindFunction, this);
116 MultiCoreRunGuestLoop(); 116 MultiCoreRunGuestLoop();
117} 117}
118 118
119void CpuManager::MultiCoreRunGuestLoop() { 119void CpuManager::MultiCoreRunGuestLoop() {
120 auto& kernel = system.Kernel(); 120 auto& kernel = system.Kernel();
121 auto* thread = kernel.CurrentScheduler().GetCurrentThread(); 121
122 while (true) { 122 while (true) {
123 auto* physical_core = &kernel.CurrentPhysicalCore(); 123 auto* physical_core = &kernel.CurrentPhysicalCore();
124 auto& arm_interface = thread->ArmInterface();
125 system.EnterDynarmicProfile(); 124 system.EnterDynarmicProfile();
126 while (!physical_core->IsInterrupted()) { 125 while (!physical_core->IsInterrupted()) {
127 arm_interface.Run(); 126 physical_core->Run();
128 physical_core = &kernel.CurrentPhysicalCore(); 127 physical_core = &kernel.CurrentPhysicalCore();
129 } 128 }
130 system.ExitDynarmicProfile(); 129 system.ExitDynarmicProfile();
131 arm_interface.ClearExclusiveState(); 130 physical_core->ArmInterface().ClearExclusiveState();
132 auto& scheduler = kernel.CurrentScheduler(); 131 kernel.CurrentScheduler()->RescheduleCurrentCore();
133 scheduler.TryDoContextSwitch();
134 } 132 }
135} 133}
136 134
@@ -139,25 +137,21 @@ void CpuManager::MultiCoreRunIdleThread() {
139 while (true) { 137 while (true) {
140 auto& physical_core = kernel.CurrentPhysicalCore(); 138 auto& physical_core = kernel.CurrentPhysicalCore();
141 physical_core.Idle(); 139 physical_core.Idle();
142 auto& scheduler = kernel.CurrentScheduler(); 140 kernel.CurrentScheduler()->RescheduleCurrentCore();
143 scheduler.TryDoContextSwitch();
144 } 141 }
145} 142}
146 143
147void CpuManager::MultiCoreRunSuspendThread() { 144void CpuManager::MultiCoreRunSuspendThread() {
148 auto& kernel = system.Kernel(); 145 auto& kernel = system.Kernel();
149 { 146 kernel.CurrentScheduler()->OnThreadStart();
150 auto& sched = kernel.CurrentScheduler();
151 sched.OnThreadStart();
152 }
153 while (true) { 147 while (true) {
154 auto core = kernel.GetCurrentHostThreadID(); 148 auto core = kernel.GetCurrentHostThreadID();
155 auto& scheduler = kernel.CurrentScheduler(); 149 auto& scheduler = *kernel.CurrentScheduler();
156 Kernel::Thread* current_thread = scheduler.GetCurrentThread(); 150 Kernel::Thread* current_thread = scheduler.GetCurrentThread();
157 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[core].host_context); 151 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[core].host_context);
158 ASSERT(scheduler.ContextSwitchPending()); 152 ASSERT(scheduler.ContextSwitchPending());
159 ASSERT(core == kernel.GetCurrentHostThreadID()); 153 ASSERT(core == kernel.GetCurrentHostThreadID());
160 scheduler.TryDoContextSwitch(); 154 scheduler.RescheduleCurrentCore();
161 } 155 }
162} 156}
163 157
@@ -205,32 +199,31 @@ void CpuManager::MultiCorePause(bool paused) {
205 199
206void CpuManager::SingleCoreRunGuestThread() { 200void CpuManager::SingleCoreRunGuestThread() {
207 auto& kernel = system.Kernel(); 201 auto& kernel = system.Kernel();
208 { 202 kernel.CurrentScheduler()->OnThreadStart();
209 auto& sched = kernel.CurrentScheduler(); 203 auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
210 sched.OnThreadStart(); 204 auto& host_context = thread->GetHostContext();
211 } 205 host_context->SetRewindPoint(GuestRewindFunction, this);
212 SingleCoreRunGuestLoop(); 206 SingleCoreRunGuestLoop();
213} 207}
214 208
215void CpuManager::SingleCoreRunGuestLoop() { 209void CpuManager::SingleCoreRunGuestLoop() {
216 auto& kernel = system.Kernel(); 210 auto& kernel = system.Kernel();
217 auto* thread = kernel.CurrentScheduler().GetCurrentThread(); 211 auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
218 while (true) { 212 while (true) {
219 auto* physical_core = &kernel.CurrentPhysicalCore(); 213 auto* physical_core = &kernel.CurrentPhysicalCore();
220 auto& arm_interface = thread->ArmInterface();
221 system.EnterDynarmicProfile(); 214 system.EnterDynarmicProfile();
222 if (!physical_core->IsInterrupted()) { 215 if (!physical_core->IsInterrupted()) {
223 arm_interface.Run(); 216 physical_core->Run();
224 physical_core = &kernel.CurrentPhysicalCore(); 217 physical_core = &kernel.CurrentPhysicalCore();
225 } 218 }
226 system.ExitDynarmicProfile(); 219 system.ExitDynarmicProfile();
227 thread->SetPhantomMode(true); 220 thread->SetPhantomMode(true);
228 system.CoreTiming().Advance(); 221 system.CoreTiming().Advance();
229 thread->SetPhantomMode(false); 222 thread->SetPhantomMode(false);
230 arm_interface.ClearExclusiveState(); 223 physical_core->ArmInterface().ClearExclusiveState();
231 PreemptSingleCore(); 224 PreemptSingleCore();
232 auto& scheduler = kernel.Scheduler(current_core); 225 auto& scheduler = kernel.Scheduler(current_core);
233 scheduler.TryDoContextSwitch(); 226 scheduler.RescheduleCurrentCore();
234 } 227 }
235} 228}
236 229
@@ -242,51 +235,53 @@ void CpuManager::SingleCoreRunIdleThread() {
242 system.CoreTiming().AddTicks(1000U); 235 system.CoreTiming().AddTicks(1000U);
243 idle_count++; 236 idle_count++;
244 auto& scheduler = physical_core.Scheduler(); 237 auto& scheduler = physical_core.Scheduler();
245 scheduler.TryDoContextSwitch(); 238 scheduler.RescheduleCurrentCore();
246 } 239 }
247} 240}
248 241
249void CpuManager::SingleCoreRunSuspendThread() { 242void CpuManager::SingleCoreRunSuspendThread() {
250 auto& kernel = system.Kernel(); 243 auto& kernel = system.Kernel();
251 { 244 kernel.CurrentScheduler()->OnThreadStart();
252 auto& sched = kernel.CurrentScheduler();
253 sched.OnThreadStart();
254 }
255 while (true) { 245 while (true) {
256 auto core = kernel.GetCurrentHostThreadID(); 246 auto core = kernel.GetCurrentHostThreadID();
257 auto& scheduler = kernel.CurrentScheduler(); 247 auto& scheduler = *kernel.CurrentScheduler();
258 Kernel::Thread* current_thread = scheduler.GetCurrentThread(); 248 Kernel::Thread* current_thread = scheduler.GetCurrentThread();
259 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[0].host_context); 249 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[0].host_context);
260 ASSERT(scheduler.ContextSwitchPending()); 250 ASSERT(scheduler.ContextSwitchPending());
261 ASSERT(core == kernel.GetCurrentHostThreadID()); 251 ASSERT(core == kernel.GetCurrentHostThreadID());
262 scheduler.TryDoContextSwitch(); 252 scheduler.RescheduleCurrentCore();
263 } 253 }
264} 254}
265 255
266void CpuManager::PreemptSingleCore(bool from_running_enviroment) { 256void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
267 std::size_t old_core = current_core; 257 {
268 auto& scheduler = system.Kernel().Scheduler(old_core); 258 auto& scheduler = system.Kernel().Scheduler(current_core);
269 Kernel::Thread* current_thread = scheduler.GetCurrentThread(); 259 Kernel::Thread* current_thread = scheduler.GetCurrentThread();
270 if (idle_count >= 4 || from_running_enviroment) { 260 if (idle_count >= 4 || from_running_enviroment) {
271 if (!from_running_enviroment) { 261 if (!from_running_enviroment) {
272 system.CoreTiming().Idle(); 262 system.CoreTiming().Idle();
273 idle_count = 0; 263 idle_count = 0;
264 }
265 current_thread->SetPhantomMode(true);
266 system.CoreTiming().Advance();
267 current_thread->SetPhantomMode(false);
274 } 268 }
275 current_thread->SetPhantomMode(true); 269 current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES);
276 system.CoreTiming().Advance(); 270 system.CoreTiming().ResetTicks();
277 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());
278 } 275 }
279 current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); 276
280 system.CoreTiming().ResetTicks(); 277 // May have changed scheduler
281 scheduler.Unload(); 278 {
282 auto& next_scheduler = system.Kernel().Scheduler(current_core); 279 auto& scheduler = system.Kernel().Scheduler(current_core);
283 Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext()); 280 scheduler.Reload(scheduler.GetCurrentThread());
284 /// May have changed scheduler 281 auto* currrent_thread2 = scheduler.GetCurrentThread();
285 auto& current_scheduler = system.Kernel().Scheduler(current_core); 282 if (!currrent_thread2->IsIdleThread()) {
286 current_scheduler.Reload(); 283 idle_count = 0;
287 auto* currrent_thread2 = current_scheduler.GetCurrentThread(); 284 }
288 if (!currrent_thread2->IsIdleThread()) {
289 idle_count = 0;
290 } 285 }
291} 286}
292 287
@@ -343,6 +338,16 @@ void CpuManager::RunThread(std::size_t core) {
343 data.initialized = true; 338 data.initialized = true;
344 const bool sc_sync = !is_async_gpu && !is_multicore; 339 const bool sc_sync = !is_async_gpu && !is_multicore;
345 bool sc_sync_first_use = sc_sync; 340 bool sc_sync_first_use = sc_sync;
341
342 // Cleanup
343 SCOPE_EXIT({
344 data.host_context->Exit();
345 data.enter_barrier.reset();
346 data.exit_barrier.reset();
347 data.initialized = false;
348 MicroProfileOnThreadExit();
349 });
350
346 /// Running 351 /// Running
347 while (running_mode) { 352 while (running_mode) {
348 data.is_running = false; 353 data.is_running = false;
@@ -351,8 +356,13 @@ void CpuManager::RunThread(std::size_t core) {
351 system.GPU().ObtainContext(); 356 system.GPU().ObtainContext();
352 sc_sync_first_use = false; 357 sc_sync_first_use = false;
353 } 358 }
354 auto& scheduler = system.Kernel().CurrentScheduler(); 359
355 Kernel::Thread* current_thread = scheduler.GetCurrentThread(); 360 // Abort if emulation was killed before the session really starts
361 if (!system.IsPoweredOn()) {
362 return;
363 }
364
365 auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
356 data.is_running = true; 366 data.is_running = true;
357 Common::Fiber::YieldTo(data.host_context, current_thread->GetHostContext()); 367 Common::Fiber::YieldTo(data.host_context, current_thread->GetHostContext());
358 data.is_running = false; 368 data.is_running = false;
@@ -360,11 +370,6 @@ void CpuManager::RunThread(std::size_t core) {
360 data.exit_barrier->Wait(); 370 data.exit_barrier->Wait();
361 data.is_paused = false; 371 data.is_paused = false;
362 } 372 }
363 /// Time to cleanup
364 data.host_context->Exit();
365 data.enter_barrier.reset();
366 data.exit_barrier.reset();
367 data.initialized = false;
368} 373}
369 374
370} // namespace Core 375} // namespace Core