diff options
| author | 2020-12-20 20:57:54 -0800 | |
|---|---|---|
| committer | 2020-12-20 20:57:54 -0800 | |
| commit | 1279c7ce7afd3d1bf2b4e33aa922158acf2cd060 (patch) | |
| tree | 6db8088caed2bd957187e4730f51424325038fa5 /src/core/cpu_manager.cpp | |
| parent | Merge pull request #5201 from ameerj/bufferq-refactor (diff) | |
| parent | hle: kernel: Process: Various style fixes based on code review feedback. (diff) | |
| download | yuzu-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.cpp | 98 |
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 | ||
| 110 | void CpuManager::MultiCoreRunGuestThread() { | 110 | void 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 | ||
| 148 | void CpuManager::MultiCoreRunSuspendThread() { | 144 | void 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 | ||
| 207 | void CpuManager::SingleCoreRunGuestThread() { | 200 | void 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 | ||
| 219 | void CpuManager::SingleCoreRunGuestLoop() { | 209 | void 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 | ||
| 251 | void CpuManager::SingleCoreRunSuspendThread() { | 242 | void 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 | ||
| 268 | void CpuManager::PreemptSingleCore(bool from_running_enviroment) { | 256 | void 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; |