diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp
index 930f789744..72565af05e 100644
--- a/src/core/hle/kernel/k_condition_variable.cpp
+++ b/src/core/hle/kernel/k_condition_variable.cpp
@@ -185,11 +185,11 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) {
             thread->Wakeup();
         } else {
             // Get the previous owner.
-            KThread* owner_thread =
-                kernel.CurrentProcess()->GetHandleTable()
-                    .GetObjectWithoutPseudoHandle<KThread>(
-                        static_cast<Handle>(prev_tag & ~Svc::HandleWaitMask))
-                    .ReleasePointerUnsafe();
+            KThread* owner_thread = kernel.CurrentProcess()
+                                        ->GetHandleTable()
+                                        .GetObjectWithoutPseudoHandle<KThread>(
+                                            static_cast<Handle>(prev_tag & ~Svc::HandleWaitMask))
+                                        .ReleasePointerUnsafe();
 
             if (owner_thread) {
                 // Add the thread as a waiter on the owner.
@@ -214,7 +214,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
     // Prepare for signaling.
     constexpr int MaxThreads = 16;
 
-    KLinkedList<KThread> thread_list;
+    KLinkedList<KThread> thread_list{kernel};
     std::array<KThread*, MaxThreads> thread_array;
     s32 num_to_close{};
 
@@ -254,7 +254,8 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
     }
 
     // Close threads in the list.
-    for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) {
+    for (auto it = thread_list.begin(); it != thread_list.end();
+         it = thread_list.erase(kernel, it)) {
         (*it).Close();
     }
 }
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp
index bc4a79cc84..4020e5325f 100644
--- a/src/core/hle/kernel/k_event.cpp
+++ b/src/core/hle/kernel/k_event.cpp
@@ -21,6 +21,10 @@ void KEvent::Initialize(std::string&& name_) {
     // writable events are closed this object will be destroyed.
     Open();
 
+    //// Create our sub events.
+    //KAutoObject::Create(readable_event.get());
+    //KAutoObject::Create(writable_event.get());
+
     // Create our sub events.
     readable_event = std::make_shared<KReadableEvent>(kernel, name_ + ":Readable");
     writable_event = std::make_shared<KWritableEvent>(kernel, name_ + ":Writable");
diff --git a/src/core/hle/kernel/k_linked_list.h b/src/core/hle/kernel/k_linked_list.h
index 8362b6edaa..8218bac8d2 100644
--- a/src/core/hle/kernel/k_linked_list.h
+++ b/src/core/hle/kernel/k_linked_list.h
@@ -11,6 +11,8 @@
 
 namespace Kernel {
 
+class KernelCore;
+
 class KLinkedListNode : public boost::intrusive::list_base_hook<>,
                         public KSlabAllocated<KLinkedListNode> {
 private:
@@ -118,11 +120,11 @@ public:
     };
 
 public:
-    constexpr KLinkedList() : BaseList() {}
+    constexpr KLinkedList(KernelCore& kernel_) : BaseList(), kernel{kernel_} {}
 
     ~KLinkedList() {
         // Erase all elements.
-        for (auto it = this->begin(); it != this->end(); it = this->erase(it)) {
+        for (auto it = this->begin(); it != this->end(); it = this->erase(kernel, it)) {
         }
 
         // Ensure we succeeded.
@@ -199,7 +201,7 @@ public:
     }
 
     iterator insert(const_iterator pos, reference ref) {
-        KLinkedListNode* node = KLinkedListNode::Allocate();
+        KLinkedListNode* node = KLinkedListNode::Allocate(kernel);
         ASSERT(node != nullptr);
         node->Initialize(std::addressof(ref));
         return iterator(BaseList::insert(pos.m_base_it, *node));
@@ -221,13 +223,16 @@ public:
         this->erase(this->begin());
     }
 
-    iterator erase(const iterator pos) {
+    iterator erase(KernelCore& kernel, const iterator pos) {
         KLinkedListNode* freed_node = std::addressof(*pos.m_base_it);
         iterator ret = iterator(BaseList::erase(pos.m_base_it));
-        KLinkedListNode::Free(freed_node);
+        KLinkedListNode::Free(kernel, freed_node);
 
         return ret;
     }
+
+private:
+    KernelCore& kernel;
 };
 
 } // namespace Kernel
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 09382f7dd4..1feda93031 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -617,7 +617,9 @@ KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core
     state.highest_priority_thread = nullptr;
 }
 
-KScheduler::~KScheduler() = default;
+KScheduler::~KScheduler() {
+    idle_thread->Close();
+}
 
 KThread* KScheduler::GetCurrentThread() const {
     if (auto result = current_thread.load(); result) {
diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h
index a3948cd27f..5ce9a1d7c3 100644
--- a/src/core/hle/kernel/k_slab_heap.h
+++ b/src/core/hle/kernel/k_slab_heap.h
@@ -97,6 +97,7 @@ public:
     void FreeImpl(void* obj) {
         // Don't allow freeing an object that wasn't allocated from this heap
         ASSERT(Contains(reinterpret_cast<uintptr_t>(obj)));
+
         impl.Free(obj);
     }
 
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index b78602f460..855bb590a1 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -11,9 +11,10 @@
 #include <vector>
 #include "core/arm/cpu_interrupt_handler.h"
 #include "core/hardware_properties.h"
+#include "core/hle/kernel/k_auto_object.h"
+#include "core/hle/kernel/k_slab_heap.h"
 #include "core/hle/kernel/memory_types.h"
 #include "core/hle/kernel/object.h"
-#include "core/hle/kernel/k_auto_object.h"
 
 namespace Core {
 class CPUInterruptHandler;
@@ -32,6 +33,8 @@ class ClientPort;
 class GlobalSchedulerContext;
 class HandleTable;
 class KAutoObjectWithListContainer;
+class KEvent;
+class KLinkedListNode;
 class KMemoryManager;
 class KResourceLimit;
 class KScheduler;
@@ -231,9 +234,10 @@ public:
 
     /**
      * 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.
+     * 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);
@@ -252,6 +256,22 @@ public:
     Core::System& System();
     const Core::System& System() const;
 
+    /// Gets the slab heap for the specified kernel object type.
+    template <typename T>
+    KSlabHeap<T>& SlabHeap() {
+        if constexpr (std::is_same_v<T, Process>) {
+            return slab_heap_Process;
+        } else if constexpr (std::is_same_v<T, KThread>) {
+            return slab_heap_KThread;
+        } else if constexpr (std::is_same_v<T, KEvent>) {
+            return slab_heap_KEvent;
+        } else if constexpr (std::is_same_v<T, KSharedMemory>) {
+            return slab_heap_KSharedMemory;
+        } else if constexpr (std::is_same_v<T, KLinkedListNode>) {
+            return slab_heap_KLinkedListNode;
+        }
+    }
+
 private:
     friend class Object;
     friend class Process;
@@ -277,7 +297,15 @@ private:
 
     struct Impl;
     std::unique_ptr<Impl> impl;
+
     bool exception_exited{};
+
+private:
+    KSlabHeap<Process> slab_heap_Process;
+    KSlabHeap<KThread> slab_heap_KThread;
+    KSlabHeap<KEvent> slab_heap_KEvent;
+    KSlabHeap<KSharedMemory> slab_heap_KSharedMemory;
+    KSlabHeap<KLinkedListNode> slab_heap_KLinkedListNode;
 };
 
 } // namespace Kernel
diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h
index ae9d097dab..4f23ddabf2 100644
--- a/src/core/hle/kernel/slab_helpers.h
+++ b/src/core/hle/kernel/slab_helpers.h
@@ -20,44 +20,44 @@ namespace Kernel {
 
 template <class Derived>
 class KSlabAllocated {
-private:
-    static inline KSlabHeap<Derived> s_slab_heap;
-
 public:
     constexpr KSlabAllocated() = default;
 
-    size_t GetSlabIndex() const {
-        return s_slab_heap.GetIndex(static_cast<const Derived*>(this));
+    size_t GetSlabIndex(KernelCore& kernel) const {
+        return kernel.SlabHeap<Derived>().GetIndex(static_cast<const Derived*>(this));
     }
 
 public:
-    static void InitializeSlabHeap(void* memory, size_t memory_size) {
-        s_slab_heap.Initialize(memory, memory_size);
+    static void InitializeSlabHeap(KernelCore& kernel, void* memory, size_t memory_size) {
+        kernel.SlabHeap<Derived>().Initialize(memory, memory_size);
     }
 
-    static Derived* Allocate() {
-        return s_slab_heap.Allocate();
+    static Derived* Allocate(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().Allocate();
     }
 
-    static void Free(Derived* obj) {
-        s_slab_heap.Free(obj);
+    static void Free(KernelCore& kernel, Derived* obj) {
+        kernel.SlabHeap<Derived>().Free(obj);
     }
 
-    static size_t GetObjectSize() {
-        return s_slab_heap.GetObjectSize();
-    }
-    static size_t GetSlabHeapSize() {
-        return s_slab_heap.GetSlabHeapSize();
-    }
-    static size_t GetPeakIndex() {
-        return s_slab_heap.GetPeakIndex();
-    }
-    static uintptr_t GetSlabHeapAddress() {
-        return s_slab_heap.GetSlabHeapAddress();
+    static size_t GetObjectSize(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetObjectSize();
     }
 
-    static size_t GetNumRemaining() {
-        return s_slab_heap.GetNumRemaining();
+    static size_t GetSlabHeapSize(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetSlabHeapSize();
+    }
+
+    static size_t GetPeakIndex(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetPeakIndex();
+    }
+
+    static uintptr_t GetSlabHeapAddress(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetSlabHeapAddress();
+    }
+
+    static size_t GetNumRemaining(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetNumRemaining();
     }
 };
 
@@ -66,43 +66,38 @@ class KAutoObjectWithSlabHeapAndContainer : public Base {
     static_assert(std::is_base_of<KAutoObjectWithList, Base>::value);
 
 private:
-    static inline KSlabHeap<Derived> s_slab_heap;
-    KernelCore& m_kernel;
-
-private:
-    static Derived* Allocate() {
-        return s_slab_heap.Allocate();
+    static Derived* Allocate(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().Allocate();
     }
 
     static Derived* AllocateWithKernel(KernelCore& kernel) {
-        return s_slab_heap.AllocateWithKernel(kernel);
+        return kernel.SlabHeap<Derived>().AllocateWithKernel(kernel);
     }
 
-    static void Free(Derived* obj) {
-        s_slab_heap.Free(obj);
+    static void Free(KernelCore& kernel, Derived* obj) {
+        kernel.SlabHeap<Derived>().Free(obj);
     }
 
 public:
     class ListAccessor : public KAutoObjectWithListContainer::ListAccessor {
     public:
-        ListAccessor()
-            : KAutoObjectWithListContainer::ListAccessor(m_kernel.ObjectListContainer()) {}
+        ListAccessor() : KAutoObjectWithListContainer::ListAccessor(kernel.ObjectListContainer()) {}
         ~ListAccessor() = default;
     };
 
 public:
-    KAutoObjectWithSlabHeapAndContainer(KernelCore& kernel) : Base(kernel), m_kernel(kernel) {}
+    KAutoObjectWithSlabHeapAndContainer(KernelCore& kernel_) : Base(kernel_), kernel(kernel_) {}
     virtual ~KAutoObjectWithSlabHeapAndContainer() {}
 
     virtual void Destroy() override {
         const bool is_initialized = this->IsInitialized();
         uintptr_t arg = 0;
         if (is_initialized) {
-            m_kernel.ObjectListContainer().Unregister(this);
+            kernel.ObjectListContainer().Unregister(this);
             arg = this->GetPostDestroyArgument();
             this->Finalize();
         }
-        Free(static_cast<Derived*>(this));
+        Free(kernel, static_cast<Derived*>(this));
         if (is_initialized) {
             Derived::PostDestroy(arg);
         }
@@ -116,12 +111,12 @@ public:
     }
 
     size_t GetSlabIndex() const {
-        return s_slab_heap.GetObjectIndex(static_cast<const Derived*>(this));
+        return SlabHeap<Derived>(kernel).GetObjectIndex(static_cast<const Derived*>(this));
     }
 
 public:
     static void InitializeSlabHeap(KernelCore& kernel, void* memory, size_t memory_size) {
-        s_slab_heap.Initialize(memory, memory_size);
+        kernel.SlabHeap<Derived>().Initialize(memory, memory_size);
         kernel.ObjectListContainer().Initialize();
     }
 
@@ -145,22 +140,28 @@ public:
         return kernel.ObjectListContainer().Register(obj);
     }
 
-    static size_t GetObjectSize() {
-        return s_slab_heap.GetObjectSize();
-    }
-    static size_t GetSlabHeapSize() {
-        return s_slab_heap.GetSlabHeapSize();
-    }
-    static size_t GetPeakIndex() {
-        return s_slab_heap.GetPeakIndex();
-    }
-    static uintptr_t GetSlabHeapAddress() {
-        return s_slab_heap.GetSlabHeapAddress();
+    static size_t GetObjectSize(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetObjectSize();
     }
 
-    static size_t GetNumRemaining() {
-        return s_slab_heap.GetNumRemaining();
+    static size_t GetSlabHeapSize(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetSlabHeapSize();
     }
+
+    static size_t GetPeakIndex(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetPeakIndex();
+    }
+
+    static uintptr_t GetSlabHeapAddress(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetSlabHeapAddress();
+    }
+
+    static size_t GetNumRemaining(KernelCore& kernel) {
+        return kernel.SlabHeap<Derived>().GetNumRemaining();
+    }
+
+protected:
+    KernelCore& kernel;
 };
 
 } // namespace Kernel