diff --git a/src/core/core.cpp b/src/core/core.cpp
index 9cc23c75d..f5c640fe5 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -174,7 +174,8 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) {
 
     timing = std::make_unique<Timing>();
 
-    kernel = std::make_unique<Kernel::KernelSystem>(*memory, *timing, system_mode);
+    kernel = std::make_unique<Kernel::KernelSystem>(*memory, *timing,
+                                                    [this] { PrepareReschedule(); }, system_mode);
 
     if (Settings::values.use_cpu_jit) {
 #ifdef ARCHITECTURE_x86_64
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index b2a5a9d45..e5bb44f0a 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -16,8 +16,10 @@
 namespace Kernel {
 
 /// Initialize the kernel
-KernelSystem::KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, u32 system_mode)
-    : memory(memory), timing(timing) {
+KernelSystem::KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing,
+                           std::function<void()> prepare_reschedule_callback, u32 system_mode)
+    : memory(memory), timing(timing),
+      prepare_reschedule_callback(std::move(prepare_reschedule_callback)) {
     MemoryInit(system_mode);
 
     resource_limits = std::make_unique<ResourceLimitList>(*this);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index dfb87b906..0fe29af92 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -6,6 +6,7 @@
 
 #include <array>
 #include <atomic>
+#include <functional>
 #include <memory>
 #include <string>
 #include <unordered_map>
@@ -82,7 +83,8 @@ using SharedPtr = boost::intrusive_ptr<T>;
 
 class KernelSystem {
 public:
-    explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, u32 system_mode);
+    explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing,
+                          std::function<void()> prepare_reschedule_callback, u32 system_mode);
     ~KernelSystem();
 
     /**
@@ -228,6 +230,10 @@ public:
     /// Adds a port to the named port table
     void AddNamedPort(std::string name, SharedPtr<ClientPort> port);
 
+    void PrepareReschedule() {
+        prepare_reschedule_callback();
+    }
+
     /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort
     std::unordered_map<std::string, SharedPtr<ClientPort>> named_ports;
 
@@ -238,6 +244,8 @@ public:
 private:
     void MemoryInit(u32 mem_type);
 
+    std::function<void()> prepare_reschedule_callback;
+
     std::unique_ptr<ResourceLimitList> resource_limits;
     std::atomic<u32> next_object_id{0};
 
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 88d03d8f2..9bc0505f5 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -24,7 +24,7 @@ void ReleaseThreadMutexes(Thread* thread) {
     thread->held_mutexes.clear();
 }
 
-Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel) {}
+Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {}
 Mutex::~Mutex() {}
 
 SharedPtr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name) {
@@ -54,7 +54,7 @@ void Mutex::Acquire(Thread* thread) {
         thread->held_mutexes.insert(this);
         holding_thread = thread;
         thread->UpdatePriority();
-        Core::System::GetInstance().PrepareReschedule();
+        kernel.PrepareReschedule();
     }
 
     lock_count++;
@@ -87,7 +87,7 @@ ResultCode Mutex::Release(Thread* thread) {
         holding_thread->UpdatePriority();
         holding_thread = nullptr;
         WakeupAllWaitingThreads();
-        Core::System::GetInstance().PrepareReschedule();
+        kernel.PrepareReschedule();
     }
 
     return RESULT_SUCCESS;
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index ec0e3f794..aff2f3986 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -57,6 +57,7 @@ private:
     ~Mutex() override;
 
     friend class KernelSystem;
+    KernelSystem& kernel;
 };
 
 /**
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 403879248..c3ad3d054 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -224,7 +224,7 @@ void Thread::ResumeFromWait() {
 
     thread_manager.ready_queue.push_back(current_priority, this);
     status = ThreadStatus::Ready;
-    Core::System::GetInstance().PrepareReschedule();
+    thread_manager.kernel.PrepareReschedule();
 }
 
 void ThreadManager::DebugThreadQueue() {
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp
index 07da6b2b9..e1ef67a52 100644
--- a/src/tests/core/arm/arm_test_common.cpp
+++ b/src/tests/core/arm/arm_test_common.cpp
@@ -21,8 +21,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_)
     Core::System::GetInstance().timing = std::make_unique<Core::Timing>();
     Core::System::GetInstance().memory = std::make_unique<Memory::MemorySystem>();
     Memory::MemorySystem& memory = *Core::System::GetInstance().memory;
-    Core::System::GetInstance().kernel =
-        std::make_unique<Kernel::KernelSystem>(memory, *Core::System::GetInstance().timing, 0);
+    Core::System::GetInstance().kernel = std::make_unique<Kernel::KernelSystem>(
+        memory, *Core::System::GetInstance().timing, [] {}, 0);
     kernel = Core::System::GetInstance().kernel.get();
 
     kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0)));
diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp
index 062a8d8ee..3df0a4468 100644
--- a/src/tests/core/hle/kernel/hle_ipc.cpp
+++ b/src/tests/core/hle/kernel/hle_ipc.cpp
@@ -24,7 +24,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
     // HACK: see comments of member timing
     Core::System::GetInstance().timing = std::make_unique<Core::Timing>();
     auto memory = std::make_unique<Memory::MemorySystem>();
-    Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, 0);
+    Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, [] {}, 0);
     auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
     HLERequestContext context(std::move(session));
 
@@ -237,7 +237,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
     // HACK: see comments of member timing
     Core::System::GetInstance().timing = std::make_unique<Core::Timing>();
     auto memory = std::make_unique<Memory::MemorySystem>();
-    Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, 0);
+    Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, [] {}, 0);
     auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
     HLERequestContext context(std::move(session));
 
diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp
index a36571193..9ccfe4587 100644
--- a/src/tests/core/memory/memory.cpp
+++ b/src/tests/core/memory/memory.cpp
@@ -15,7 +15,7 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") {
     Core::System::GetInstance().timing = std::make_unique<Core::Timing>();
     Core::System::GetInstance().memory = std::make_unique<Memory::MemorySystem>();
     Kernel::KernelSystem kernel(*Core::System::GetInstance().memory,
-                                *Core::System::GetInstance().timing, 0);
+                                *Core::System::GetInstance().timing, [] {}, 0);
     SECTION("these regions should not be mapped on an empty process") {
         auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
         CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false);