summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp29
1 files changed, 20 insertions, 9 deletions
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 @@
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "common/microprofile.h" 16#include "common/microprofile.h"
17#include "common/thread.h" 17#include "common/thread.h"
18#include "common/thread_worker.h"
18#include "core/arm/arm_interface.h" 19#include "core/arm/arm_interface.h"
19#include "core/arm/cpu_interrupt_handler.h" 20#include "core/arm/cpu_interrupt_handler.h"
20#include "core/arm/exclusive_monitor.h" 21#include "core/arm/exclusive_monitor.h"
@@ -58,11 +59,11 @@ struct KernelCore::Impl {
58 } 59 }
59 60
60 void Initialize(KernelCore& kernel) { 61 void Initialize(KernelCore& kernel) {
61 process_list.clear();
62
63 RegisterHostThread(); 62 RegisterHostThread();
64 63
65 global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); 64 global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
65 service_thread_manager =
66 std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager");
66 67
67 InitializePhysicalCores(); 68 InitializePhysicalCores();
68 InitializeSystemResourceLimit(kernel); 69 InitializeSystemResourceLimit(kernel);
@@ -79,6 +80,12 @@ struct KernelCore::Impl {
79 } 80 }
80 81
81 void Shutdown() { 82 void Shutdown() {
83 process_list.clear();
84
85 // Ensures all service threads gracefully shutdown
86 service_thread_manager.reset();
87 service_threads.clear();
88
82 next_object_id = 0; 89 next_object_id = 0;
83 next_kernel_process_id = Process::InitialKIPIDMin; 90 next_kernel_process_id = Process::InitialKIPIDMin;
84 next_user_process_id = Process::ProcessIDMin; 91 next_user_process_id = Process::ProcessIDMin;
@@ -106,9 +113,6 @@ struct KernelCore::Impl {
106 113
107 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others 114 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
108 next_host_thread_id = Core::Hardware::NUM_CPU_CORES; 115 next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
109
110 // Ensures all service threads gracefully shutdown
111 service_threads.clear();
112 } 116 }
113 117
114 void InitializePhysicalCores() { 118 void InitializePhysicalCores() {
@@ -337,6 +341,10 @@ struct KernelCore::Impl {
337 // Threads used for services 341 // Threads used for services
338 std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads; 342 std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
339 343
344 // Service threads are managed by a worker thread, so that a calling service thread can queue up
345 // the release of itself
346 std::unique_ptr<Common::ThreadWorker> service_thread_manager;
347
340 std::array<std::shared_ptr<Thread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{}; 348 std::array<std::shared_ptr<Thread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{};
341 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; 349 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
342 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; 350 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
@@ -633,14 +641,17 @@ void KernelCore::ExitSVCProfile() {
633 641
634std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) { 642std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
635 auto service_thread = std::make_shared<Kernel::ServiceThread>(*this, 1, name); 643 auto service_thread = std::make_shared<Kernel::ServiceThread>(*this, 1, name);
636 impl->service_threads.emplace(service_thread); 644 impl->service_thread_manager->QueueWork(
645 [this, service_thread] { impl->service_threads.emplace(service_thread); });
637 return service_thread; 646 return service_thread;
638} 647}
639 648
640void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { 649void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
641 if (auto strong_ptr = service_thread.lock()) { 650 impl->service_thread_manager->QueueWork([this, service_thread] {
642 impl->service_threads.erase(strong_ptr); 651 if (auto strong_ptr = service_thread.lock()) {
643 } 652 impl->service_threads.erase(strong_ptr);
653 }
654 });
644} 655}
645 656
646} // namespace Kernel 657} // namespace Kernel