CPU_Manager: Unload/Reload threads on preemption on SingleCore

This commit is contained in:
Fernando Sahmkow 2020-03-10 11:50:33 -04:00
parent 8a78fc2580
commit a439cdf22e
4 changed files with 64 additions and 7 deletions

View file

@ -602,6 +602,48 @@ void Scheduler::OnThreadStart() {
SwitchContextStep2();
}
void Scheduler::Unload() {
Thread* thread = current_thread.get();
if (thread) {
thread->last_running_ticks = system.CoreTiming().GetCPUTicks();
thread->SetIsRunning(false);
if (!thread->IsHLEThread()) {
auto& cpu_core = system.ArmInterface(core_id);
cpu_core.SaveContext(thread->GetContext32());
cpu_core.SaveContext(thread->GetContext64());
// Save the TPIDR_EL0 system register in case it was modified.
thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0());
cpu_core.ClearExclusiveState();
}
thread->context_guard.unlock();
}
}
void Scheduler::Reload() {
Thread* thread = current_thread.get();
if (thread) {
ASSERT_MSG(thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable,
"Thread must be runnable.");
// Cancel any outstanding wakeup events for this thread
thread->SetIsRunning(true);
thread->last_running_ticks = system.CoreTiming().GetCPUTicks();
auto* const thread_owner_process = thread->GetOwnerProcess();
if (thread_owner_process != nullptr) {
system.Kernel().MakeCurrentProcess(thread_owner_process);
}
if (!thread->IsHLEThread()) {
auto& cpu_core = system.ArmInterface(core_id);
cpu_core.LoadContext(thread->GetContext32());
cpu_core.LoadContext(thread->GetContext64());
cpu_core.SetTlsAddress(thread->GetTLSAddress());
cpu_core.SetTPIDR_EL0(thread->GetTPIDR_EL0());
cpu_core.ClearExclusiveState();
}
}
}
void Scheduler::SwitchContextStep2() {
Thread* previous_thread = current_thread_prev.get();
Thread* new_thread = selected_thread.get();

View file

@ -210,6 +210,12 @@ public:
/// Reschedules to the next available thread (call after current thread is suspended)
void TryDoContextSwitch();
/// The next two are for SingleCore Only.
/// Unload current thread before preempting core.
void Unload();
/// Reload current thread after core preemption.
void Reload();
/// Gets the current running thread
Thread* GetCurrentThread() const;
@ -230,6 +236,10 @@ public:
void OnThreadStart();
std::shared_ptr<Common::Fiber> ControlContext() {
return switch_fiber;
}
private:
friend class GlobalScheduler;