diff options
| author | 2020-03-10 11:50:33 -0400 | |
|---|---|---|
| committer | 2020-06-27 11:35:43 -0400 | |
| commit | a439cdf22ea50f0e39cb51f6dff15fee3b495d16 (patch) | |
| tree | 2c88310d7cca08ef451107d9ae6bd5191e7d72e5 /src/core/hle/kernel | |
| parent | Synchronization: Correct wide Assertion. (diff) | |
| download | yuzu-a439cdf22ea50f0e39cb51f6dff15fee3b495d16.tar.gz yuzu-a439cdf22ea50f0e39cb51f6dff15fee3b495d16.tar.xz yuzu-a439cdf22ea50f0e39cb51f6dff15fee3b495d16.zip | |
CPU_Manager: Unload/Reload threads on preemption on SingleCore
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 42 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.h | 10 |
2 files changed, 52 insertions, 0 deletions
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index d68d86cdf..00322d997 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -602,6 +602,48 @@ void Scheduler::OnThreadStart() { | |||
| 602 | SwitchContextStep2(); | 602 | SwitchContextStep2(); |
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | void Scheduler::Unload() { | ||
| 606 | Thread* thread = current_thread.get(); | ||
| 607 | if (thread) { | ||
| 608 | thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); | ||
| 609 | thread->SetIsRunning(false); | ||
| 610 | if (!thread->IsHLEThread()) { | ||
| 611 | auto& cpu_core = system.ArmInterface(core_id); | ||
| 612 | cpu_core.SaveContext(thread->GetContext32()); | ||
| 613 | cpu_core.SaveContext(thread->GetContext64()); | ||
| 614 | // Save the TPIDR_EL0 system register in case it was modified. | ||
| 615 | thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); | ||
| 616 | cpu_core.ClearExclusiveState(); | ||
| 617 | } | ||
| 618 | thread->context_guard.unlock(); | ||
| 619 | } | ||
| 620 | } | ||
| 621 | |||
| 622 | void Scheduler::Reload() { | ||
| 623 | Thread* thread = current_thread.get(); | ||
| 624 | if (thread) { | ||
| 625 | ASSERT_MSG(thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable, | ||
| 626 | "Thread must be runnable."); | ||
| 627 | |||
| 628 | // Cancel any outstanding wakeup events for this thread | ||
| 629 | thread->SetIsRunning(true); | ||
| 630 | thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); | ||
| 631 | |||
| 632 | auto* const thread_owner_process = thread->GetOwnerProcess(); | ||
| 633 | if (thread_owner_process != nullptr) { | ||
| 634 | system.Kernel().MakeCurrentProcess(thread_owner_process); | ||
| 635 | } | ||
| 636 | if (!thread->IsHLEThread()) { | ||
| 637 | auto& cpu_core = system.ArmInterface(core_id); | ||
| 638 | cpu_core.LoadContext(thread->GetContext32()); | ||
| 639 | cpu_core.LoadContext(thread->GetContext64()); | ||
| 640 | cpu_core.SetTlsAddress(thread->GetTLSAddress()); | ||
| 641 | cpu_core.SetTPIDR_EL0(thread->GetTPIDR_EL0()); | ||
| 642 | cpu_core.ClearExclusiveState(); | ||
| 643 | } | ||
| 644 | } | ||
| 645 | } | ||
| 646 | |||
| 605 | void Scheduler::SwitchContextStep2() { | 647 | void Scheduler::SwitchContextStep2() { |
| 606 | Thread* previous_thread = current_thread_prev.get(); | 648 | Thread* previous_thread = current_thread_prev.get(); |
| 607 | Thread* new_thread = selected_thread.get(); | 649 | Thread* new_thread = selected_thread.get(); |
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 5e062bf59..f63cc5085 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h | |||
| @@ -210,6 +210,12 @@ public: | |||
| 210 | /// Reschedules to the next available thread (call after current thread is suspended) | 210 | /// Reschedules to the next available thread (call after current thread is suspended) |
| 211 | void TryDoContextSwitch(); | 211 | void TryDoContextSwitch(); |
| 212 | 212 | ||
| 213 | /// The next two are for SingleCore Only. | ||
| 214 | /// Unload current thread before preempting core. | ||
| 215 | void Unload(); | ||
| 216 | /// Reload current thread after core preemption. | ||
| 217 | void Reload(); | ||
| 218 | |||
| 213 | /// Gets the current running thread | 219 | /// Gets the current running thread |
| 214 | Thread* GetCurrentThread() const; | 220 | Thread* GetCurrentThread() const; |
| 215 | 221 | ||
| @@ -230,6 +236,10 @@ public: | |||
| 230 | 236 | ||
| 231 | void OnThreadStart(); | 237 | void OnThreadStart(); |
| 232 | 238 | ||
| 239 | std::shared_ptr<Common::Fiber> ControlContext() { | ||
| 240 | return switch_fiber; | ||
| 241 | } | ||
| 242 | |||
| 233 | private: | 243 | private: |
| 234 | friend class GlobalScheduler; | 244 | friend class GlobalScheduler; |
| 235 | 245 | ||