From dfdac7d38af170683812f3b474ef9d686dfa9ef8 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Tue, 15 Dec 2020 00:41:48 -0800
Subject: hle: kernel: Move ServiceThread ownership to KernelCore.

- Fixes a circular dependency which prevented threads from being released on shutdown.
---
 src/core/hle/kernel/kernel.cpp | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

(limited to 'src/core/hle/kernel/kernel.cpp')

diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 312c64c179..5f917686fe 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -8,7 +8,7 @@
 #include <functional>
 #include <memory>
 #include <thread>
-#include <unordered_map>
+#include <unordered_set>
 #include <utility>
 
 #include "common/assert.h"
@@ -35,6 +35,7 @@
 #include "core/hle/kernel/physical_core.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/resource_limit.h"
+#include "core/hle/kernel/service_thread.h"
 #include "core/hle/kernel/shared_memory.h"
 #include "core/hle/kernel/synchronization.h"
 #include "core/hle/kernel/thread.h"
@@ -107,6 +108,9 @@ struct KernelCore::Impl {
         std::fill(register_host_thread_keys.begin(), register_host_thread_keys.end(),
                   std::thread::id{});
         std::fill(register_host_thread_values.begin(), register_host_thread_values.end(), 0);
+
+        // Ensures all service threads gracefully shutdown
+        service_threads.clear();
     }
 
     void InitializePhysicalCores() {
@@ -345,6 +349,9 @@ struct KernelCore::Impl {
     std::shared_ptr<Kernel::SharedMemory> irs_shared_mem;
     std::shared_ptr<Kernel::SharedMemory> time_shared_mem;
 
+    // Threads used for services
+    std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
+
     std::array<std::shared_ptr<Thread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{};
     std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
     std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
@@ -639,4 +646,16 @@ void KernelCore::ExitSVCProfile() {
     MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[core]);
 }
 
+std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
+    auto service_thread = std::make_shared<Kernel::ServiceThread>(*this, 1, name);
+    impl->service_threads.emplace(service_thread);
+    return service_thread;
+}
+
+void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
+    if (auto strong_ptr = service_thread.lock()) {
+        impl->service_threads.erase(strong_ptr);
+    }
+}
+
 } // namespace Kernel
-- 
cgit v1.2.3-70-g09d2