diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index fd354d4840..06010b8d18 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -27,16 +27,12 @@ namespace Kernel {
 
 SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
                                              ServiceThreadType thread_type)
-    : kernel{kernel_} {
-    if (thread_type == ServiceThreadType::CreateNew) {
-        service_thread = kernel.CreateServiceThread(service_name_);
-    } else {
-        service_thread = kernel.GetDefaultServiceThread();
-    }
-}
+    : kernel{kernel_}, service_thread{thread_type == ServiceThreadType::CreateNew
+                                          ? kernel.CreateServiceThread(service_name_)
+                                          : kernel.GetDefaultServiceThread()} {}
 
 SessionRequestHandler::~SessionRequestHandler() {
-    kernel.ReleaseServiceThread(service_thread.lock());
+    kernel.ReleaseServiceThread(service_thread);
 }
 
 void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
@@ -49,7 +45,7 @@ void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
 void SessionRequestHandler::RegisterSession(KServerSession* server_session,
                                             std::shared_ptr<SessionRequestManager> manager) {
     manager->SetSessionHandler(shared_from_this());
-    service_thread.lock()->RegisterServerSession(server_session, manager);
+    service_thread.RegisterServerSession(server_session, manager);
     server_session->Close();
 }
 
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 67da8e7e10..d87be72d6a 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -82,13 +82,13 @@ public:
     void RegisterSession(KServerSession* server_session,
                          std::shared_ptr<SessionRequestManager> manager);
 
-    std::weak_ptr<ServiceThread> GetServiceThread() const {
+    ServiceThread& GetServiceThread() const {
         return service_thread;
     }
 
 protected:
     KernelCore& kernel;
-    std::weak_ptr<ServiceThread> service_thread;
+    ServiceThread& service_thread;
 };
 
 using SessionRequestHandlerWeakPtr = std::weak_ptr<SessionRequestHandler>;
@@ -154,7 +154,7 @@ public:
         session_handler = std::move(handler);
     }
 
-    std::weak_ptr<ServiceThread> GetServiceThread() const {
+    ServiceThread& GetServiceThread() const {
         return session_handler->GetServiceThread();
     }
 
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 47b760a9cb..abff140794 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -93,7 +93,7 @@ struct KernelCore::Impl {
 
         RegisterHostThread();
 
-        default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread");
+        default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
     }
 
     void InitializeCores() {
@@ -779,33 +779,31 @@ struct KernelCore::Impl {
         search->second(system.ServiceManager(), server_port);
     }
 
-    std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel,
-                                                             const std::string& name) {
-        auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, name);
+    Kernel::ServiceThread& CreateServiceThread(KernelCore& kernel, const std::string& name) {
+        auto* ptr = new ServiceThread(kernel, name);
 
         service_threads_manager.QueueWork(
-            [this, service_thread]() { service_threads.emplace(service_thread); });
+            [this, ptr]() { service_threads.emplace(ptr, std::unique_ptr<ServiceThread>(ptr)); });
 
-        return service_thread;
+        return *ptr;
     }
 
-    void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
-        if (auto strong_ptr = service_thread.lock()) {
-            if (strong_ptr == default_service_thread.lock()) {
-                // Nothing to do here, the service is using default_service_thread, which will be
-                // released on shutdown.
-                return;
-            }
+    void ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
+        auto* ptr = &service_thread;
 
-            service_threads_manager.QueueWork(
-                [this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); });
+        if (ptr == default_service_thread) {
+            // Nothing to do here, the service is using default_service_thread, which will be
+            // released on shutdown.
+            return;
         }
+
+        service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); });
     }
 
     void ClearServiceThreads() {
         service_threads_manager.QueueWork([this] {
             service_threads.clear();
-            default_service_thread.reset();
+            default_service_thread = nullptr;
             service_thread_barrier.Sync();
         });
         service_thread_barrier.Sync();
@@ -881,8 +879,8 @@ struct KernelCore::Impl {
     std::unique_ptr<KMemoryLayout> memory_layout;
 
     // Threads used for services
-    std::unordered_set<std::shared_ptr<ServiceThread>> service_threads;
-    std::weak_ptr<ServiceThread> default_service_thread;
+    std::unordered_map<ServiceThread*, std::unique_ptr<ServiceThread>> service_threads;
+    ServiceThread* default_service_thread{};
     Common::ThreadWorker service_threads_manager;
     Common::Barrier service_thread_barrier;
 
@@ -1239,15 +1237,15 @@ void KernelCore::ExitSVCProfile() {
     MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
 }
 
-std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
+Kernel::ServiceThread& KernelCore::CreateServiceThread(const std::string& name) {
     return impl->CreateServiceThread(*this, name);
 }
 
-std::weak_ptr<Kernel::ServiceThread> KernelCore::GetDefaultServiceThread() const {
-    return impl->default_service_thread;
+Kernel::ServiceThread& KernelCore::GetDefaultServiceThread() const {
+    return *impl->default_service_thread;
 }
 
-void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
+void KernelCore::ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
     impl->ReleaseServiceThread(service_thread);
 }
 
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index caca605864..29617d736d 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -309,24 +309,24 @@ public:
      * See GetDefaultServiceThread.
      * @param name String name for the ServerSession creating this thread, used for debug
      * purposes.
-     * @returns The a weak pointer newly created service thread.
+     * @returns A reference to the newly created service thread.
      */
-    std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name);
+    Kernel::ServiceThread& CreateServiceThread(const std::string& name);
 
     /**
      * Gets the default host service thread, which executes HLE service requests. Unless service
      * requests need to block on the host, the default service thread should be used in favor of
      * creating a new service thread.
-     * @returns The a weak pointer for the default service thread.
+     * @returns A reference to the default service thread.
      */
-    std::weak_ptr<Kernel::ServiceThread> GetDefaultServiceThread() const;
+    Kernel::ServiceThread& GetDefaultServiceThread() const;
 
     /**
      * 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);
+    void ReleaseServiceThread(Kernel::ServiceThread& service_thread);
 
     /// Workaround for single-core mode when preempting threads while idle.
     bool IsPhantomModeForSingleCore() const;