From 25f8606a6dab595eb7a92fce9be32e0489079964 Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Sat, 12 Oct 2019 08:21:51 -0400
Subject: [PATCH] Kernel Scheduler: Make sure the global scheduler shutdowns
 correctly.

---
 src/common/multi_level_queue.h    | 7 +++++++
 src/core/core_cpu.cpp             | 4 ++++
 src/core/core_cpu.h               | 2 ++
 src/core/cpu_core_manager.cpp     | 1 +
 src/core/hle/kernel/kernel.cpp    | 2 ++
 src/core/hle/kernel/scheduler.cpp | 8 ++++++++
 src/core/hle/kernel/scheduler.h   | 7 +++++++
 7 files changed, 31 insertions(+)

diff --git a/src/common/multi_level_queue.h b/src/common/multi_level_queue.h
index 9cb448f567..50acfdbf2f 100644
--- a/src/common/multi_level_queue.h
+++ b/src/common/multi_level_queue.h
@@ -304,6 +304,13 @@ public:
         return levels[priority == Depth ? 63 : priority].back();
     }
 
+    void clear() {
+        used_priorities = 0;
+        for (std::size_t i = 0; i < Depth; i++) {
+            levels[i].clear();
+        }
+    }
+
 private:
     using const_list_iterator = typename std::list<T>::const_iterator;
 
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
index a6f63e437a..233ea572ca 100644
--- a/src/core/core_cpu.cpp
+++ b/src/core/core_cpu.cpp
@@ -117,4 +117,8 @@ void Cpu::Reschedule() {
     scheduler->TryDoContextSwitch();
 }
 
+void Cpu::Shutdown() {
+    scheduler->Shutdown();
+}
+
 } // namespace Core
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h
index 80261daf75..cafca8df7f 100644
--- a/src/core/core_cpu.h
+++ b/src/core/core_cpu.h
@@ -84,6 +84,8 @@ public:
         return core_index;
     }
 
+    void Shutdown();
+
     static std::unique_ptr<ExclusiveMonitor> MakeExclusiveMonitor(std::size_t num_cores);
 
 private:
diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_core_manager.cpp
index 16b384076e..8efd410bba 100644
--- a/src/core/cpu_core_manager.cpp
+++ b/src/core/cpu_core_manager.cpp
@@ -58,6 +58,7 @@ void CpuCoreManager::Shutdown() {
 
     thread_to_cpu.clear();
     for (auto& cpu_core : cores) {
+        cpu_core->Shutdown();
         cpu_core.reset();
     }
 
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 002c5af2bb..0d6286f845 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -116,6 +116,8 @@ struct KernelCore::Impl {
         thread_wakeup_event_type = nullptr;
         preemption_event = nullptr;
 
+        global_scheduler.Shutdown();
+
         named_ports.clear();
     }
 
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index 226d15d888..122106267a 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -342,6 +342,14 @@ bool GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread, T
     }
 }
 
+void GlobalScheduler::Shutdown() {
+    for (std::size_t core = 0; core < NUM_CPU_CORES; core++) {
+        scheduled_queue[core].clear();
+        suggested_queue[core].clear();
+    }
+    thread_list.clear();
+}
+
 GlobalScheduler::~GlobalScheduler() = default;
 
 Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, u32 core_id)
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index 408e20c883..617553ae36 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -147,6 +147,8 @@ public:
         return reselection_pending.load();
     }
 
+    void Shutdown();
+
 private:
     bool AskForReselectionOrMarkRedundant(Thread* current_thread, Thread* winner);
 
@@ -189,6 +191,11 @@ public:
         return context_switch_pending;
     }
 
+    void Shutdown() {
+        current_thread = nullptr;
+        selected_thread = nullptr;
+    }
+
 private:
     friend class GlobalScheduler;
     /**