diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 6ddbae52c..5423b187e 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -376,11 +376,21 @@ void KScheduler::ClearSchedulerUpdateNeeded(KernelCore& kernel) {
 }
 
 void KScheduler::DisableScheduling(KernelCore& kernel) {
+    // If we are shutting down the kernel, none of this is relevant anymore.
+    if (kernel.IsShuttingDown()) {
+        return;
+    }
+
     ASSERT(GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() >= 0);
     GetCurrentThreadPointer(kernel)->DisableDispatch();
 }
 
 void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduling) {
+    // If we are shutting down the kernel, none of this is relevant anymore.
+    if (kernel.IsShuttingDown()) {
+        return;
+    }
+
     ASSERT(GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() >= 1);
 
     if (GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() > 1) {
diff --git a/src/core/hle/kernel/k_scheduler_lock.h b/src/core/hle/kernel/k_scheduler_lock.h
index c571f2992..93c47f1b1 100644
--- a/src/core/hle/kernel/k_scheduler_lock.h
+++ b/src/core/hle/kernel/k_scheduler_lock.h
@@ -23,6 +23,11 @@ public:
     }
 
     void Lock() {
+        // If we are shutting down the kernel, none of this is relevant anymore.
+        if (kernel.IsShuttingDown()) {
+            return;
+        }
+
         if (IsLockedByCurrentThread()) {
             // If we already own the lock, we can just increment the count.
             ASSERT(lock_count > 0);
@@ -43,6 +48,11 @@ public:
     }
 
     void Unlock() {
+        // If we are shutting down the kernel, none of this is relevant anymore.
+        if (kernel.IsShuttingDown()) {
+            return;
+        }
+
         ASSERT(IsLockedByCurrentThread());
         ASSERT(lock_count > 0);
 
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 813b92ea4..f69978caf 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -1089,6 +1089,11 @@ s32 GetCurrentCoreId(KernelCore& kernel) {
 }
 
 KScopedDisableDispatch::~KScopedDisableDispatch() {
+    // If we are shutting down the kernel, none of this is relevant anymore.
+    if (kernel.IsShuttingDown()) {
+        return;
+    }
+
     if (GetCurrentThread(kernel).GetDisableDispatchCount() <= 1) {
         auto scheduler = kernel.CurrentScheduler();
 
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 1cde71e89..be1bc59ae 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -794,6 +794,10 @@ public:
 class KScopedDisableDispatch {
 public:
     [[nodiscard]] explicit KScopedDisableDispatch(KernelCore& kernel_) : kernel{kernel_} {
+        // If we are shutting down the kernel, none of this is relevant anymore.
+        if (kernel.IsShuttingDown()) {
+            return;
+        }
         GetCurrentThread(kernel).DisableDispatch();
     }
 
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index cf155ff66..1a47d4716 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -14,6 +14,7 @@
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "common/microprofile.h"
+#include "common/scope_exit.h"
 #include "common/thread.h"
 #include "common/thread_worker.h"
 #include "core/arm/arm_interface.h"
@@ -90,6 +91,9 @@ struct KernelCore::Impl {
     }
 
     void Shutdown() {
+        is_shutting_down.store(true, std::memory_order_relaxed);
+        SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); });
+
         process_list.clear();
 
         // Close all open server ports.
@@ -338,7 +342,16 @@ struct KernelCore::Impl {
         is_phantom_mode_for_singlecore = value;
     }
 
+    bool IsShuttingDown() const {
+        return is_shutting_down.load(std::memory_order_relaxed);
+    }
+
     KThread* GetCurrentEmuThread() {
+        // If we are shutting down the kernel, none of this is relevant anymore.
+        if (IsShuttingDown()) {
+            return {};
+        }
+
         const auto thread_id = GetCurrentHostThreadID();
         if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
             return GetHostDummyThread();
@@ -754,6 +767,7 @@ struct KernelCore::Impl {
     std::vector<std::unique_ptr<KThread>> dummy_threads;
 
     bool is_multicore{};
+    std::atomic_bool is_shutting_down{};
     bool is_phantom_mode_for_singlecore{};
     u32 single_core_thread_id{};
 
@@ -1066,6 +1080,10 @@ bool KernelCore::IsMulticore() const {
     return impl->is_multicore;
 }
 
+bool KernelCore::IsShuttingDown() const {
+    return impl->IsShuttingDown();
+}
+
 void KernelCore::ExceptionalExit() {
     exception_exited = true;
     Suspend(true);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 3499f8b90..eacf9dc61 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -274,6 +274,8 @@ public:
 
     bool IsMulticore() const;
 
+    bool IsShuttingDown() const;
+
     void EnterSVCProfile();
 
     void ExitSVCProfile();