summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/kernel.cpp21
-rw-r--r--src/core/hle/kernel/kernel.h17
-rw-r--r--src/core/hle/kernel/server_session.cpp13
-rw-r--r--src/core/hle/kernel/server_session.h2
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