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/scheduler.cpp | |
| 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/scheduler.cpp')
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 42 |
1 files changed, 42 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(); |