From a2a0f5318dba2c87578703a5bb69b9fbf7ec526d Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 29 Dec 2020 16:39:04 -0800 Subject: hle: kernel: Manage service threads on another thread. - This is to allow service threads to defer destruction of themselves. --- src/core/hle/kernel/kernel.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 022cd413d..e8ece8164 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -15,6 +15,7 @@ #include "common/logging/log.h" #include "common/microprofile.h" #include "common/thread.h" +#include "common/thread_worker.h" #include "core/arm/arm_interface.h" #include "core/arm/cpu_interrupt_handler.h" #include "core/arm/exclusive_monitor.h" @@ -58,11 +59,11 @@ struct KernelCore::Impl { } void Initialize(KernelCore& kernel) { - process_list.clear(); - RegisterHostThread(); global_scheduler_context = std::make_unique(kernel); + service_thread_manager = + std::make_unique(1, "yuzu:ServiceThreadManager"); InitializePhysicalCores(); InitializeSystemResourceLimit(kernel); @@ -79,6 +80,12 @@ struct KernelCore::Impl { } void Shutdown() { + process_list.clear(); + + // Ensures all service threads gracefully shutdown + service_thread_manager.reset(); + service_threads.clear(); + next_object_id = 0; next_kernel_process_id = Process::InitialKIPIDMin; next_user_process_id = Process::ProcessIDMin; @@ -106,9 +113,6 @@ struct KernelCore::Impl { // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others next_host_thread_id = Core::Hardware::NUM_CPU_CORES; - - // Ensures all service threads gracefully shutdown - service_threads.clear(); } void InitializePhysicalCores() { @@ -337,6 +341,10 @@ struct KernelCore::Impl { // Threads used for services std::unordered_set> service_threads; + // Service threads are managed by a worker thread, so that a calling service thread can queue up + // the release of itself + std::unique_ptr service_thread_manager; + std::array, Core::Hardware::NUM_CPU_CORES> suspend_threads{}; std::array interrupts{}; std::array, Core::Hardware::NUM_CPU_CORES> schedulers{}; @@ -633,14 +641,17 @@ void KernelCore::ExitSVCProfile() { std::weak_ptr KernelCore::CreateServiceThread(const std::string& name) { auto service_thread = std::make_shared(*this, 1, name); - impl->service_threads.emplace(service_thread); + impl->service_thread_manager->QueueWork( + [this, service_thread] { impl->service_threads.emplace(service_thread); }); return service_thread; } void KernelCore::ReleaseServiceThread(std::weak_ptr service_thread) { - if (auto strong_ptr = service_thread.lock()) { - impl->service_threads.erase(strong_ptr); - } + impl->service_thread_manager->QueueWork([this, service_thread] { + if (auto strong_ptr = service_thread.lock()) { + impl->service_threads.erase(strong_ptr); + } + }); } } // namespace Kernel -- cgit v1.2.3