diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 17 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.cpp | 13 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.h | 2 | 
4 files changed, 48 insertions, 5 deletions
| diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 312c64c17..5f917686f 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 diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 5846c3f39..e3169f5a7 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -42,6 +42,7 @@ class Process;  class ResourceLimit;  class KScheduler;  class SharedMemory; +class ServiceThread;  class Synchronization;  class Thread;  class TimeManager; @@ -227,6 +228,22 @@ public:      void ExitSVCProfile(); +    /** +     * Creates an HLE service thread, which are used to execute service routines asynchronously. +     * While these are allocated per ServerSession, these need to be owned and managed outside of +     * ServerSession to avoid a circular dependency. +     * @param name String name for the ServerSession creating this thread, used for debug purposes. +     * @returns The a weak pointer newly created service thread. +     */ +    std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name); + +    /** +     * Releases a HLE service thread, instructing KernelCore to free it. This should be called when +     * the ServerSession associated with the thread is destroyed. +     * @param service_thread Service thread to release. +     */ +    void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread); +  private:      friend class Object;      friend class Process; diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 947f4a133..b40fe3916 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -25,7 +25,10 @@  namespace Kernel {  ServerSession::ServerSession(KernelCore& kernel) : SynchronizationObject{kernel} {} -ServerSession::~ServerSession() = default; + +ServerSession::~ServerSession() { +    kernel.ReleaseServiceThread(service_thread); +}  ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kernel,                                                                  std::shared_ptr<Session> parent, @@ -34,7 +37,7 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern      session->name = std::move(name);      session->parent = std::move(parent); -    session->service_thread = std::make_unique<ServiceThread>(kernel, 1, session->name); +    session->service_thread = kernel.CreateServiceThread(session->name);      return MakeResult(std::move(session));  } @@ -139,7 +142,11 @@ ResultCode ServerSession::QueueSyncRequest(std::shared_ptr<Thread> thread,          std::make_shared<HLERequestContext>(kernel, memory, SharedFrom(this), std::move(thread));      context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); -    service_thread->QueueSyncRequest(*this, std::move(context)); + +    if (auto strong_ptr = service_thread.lock()) { +        strong_ptr->QueueSyncRequest(*this, std::move(context)); +        return RESULT_SUCCESS; +    }      return RESULT_SUCCESS;  } diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 8466b03e6..e8d1d99ea 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -167,7 +167,7 @@ private:      std::string name;      /// Thread to dispatch service requests -    std::unique_ptr<ServiceThread> service_thread; +    std::weak_ptr<ServiceThread> service_thread;  };  } // namespace Kernel | 
