diff options
| author | 2020-12-29 16:39:04 -0800 | |
|---|---|---|
| committer | 2020-12-29 16:46:29 -0800 | |
| commit | a2a0f5318dba2c87578703a5bb69b9fbf7ec526d (patch) | |
| tree | 9d153419ffd306af3c13137223e8a85a5f33e9bc /src/core/hle/kernel/kernel.cpp | |
| parent | common: ThreadWorker: Add class to help do asynchronous work. (diff) | |
| download | yuzu-a2a0f5318dba2c87578703a5bb69b9fbf7ec526d.tar.gz yuzu-a2a0f5318dba2c87578703a5bb69b9fbf7ec526d.tar.xz yuzu-a2a0f5318dba2c87578703a5bb69b9fbf7ec526d.zip | |
hle: kernel: Manage service threads on another thread.
- This is to allow service threads to defer destruction of themselves.
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 29 |
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 | ||
| 634 | std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) { | 642 | std::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 | ||
| 640 | void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { | 649 | void 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 |