diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index cd4b0aa60..ea5fe5b29 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -187,7 +187,6 @@ void Process::RemoveConditionVariableThread(std::shared_ptr<Thread> thread) {
         }
         ++it;
     }
-    UNREACHABLE();
 }
 
 std::vector<std::shared_ptr<Thread>> Process::GetConditionVariableThreads(
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index 0e85ee69e..758fa8188 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -632,7 +632,7 @@ void Scheduler::SwitchContext() {
             cpu_core.SaveContext(previous_thread->GetContext64());
             // Save the TPIDR_EL0 system register in case it was modified.
             previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0());
-
+            cpu_core.ClearExclusiveState();
         }
         if (previous_thread->GetStatus() == ThreadStatus::Running) {
             previous_thread->SetStatus(ThreadStatus::Ready);
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 8634d3feb..a5193063b 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1541,33 +1541,50 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
         return ERR_INVALID_ADDRESS;
     }
 
-    UNIMPLEMENTED();
-
     ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4));
-
+    auto& kernel = system.Kernel();
+    Handle event_handle;
+    Thread* current_thread = system.CurrentScheduler().GetCurrentThread();
     auto* const current_process = system.Kernel().CurrentProcess();
-    const auto& handle_table = current_process->GetHandleTable();
-    std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle);
-    ASSERT(thread);
+    {
+        SchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds);
+        const auto& handle_table = current_process->GetHandleTable();
+        std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle);
+        ASSERT(thread);
 
-    const auto release_result = current_process->GetMutex().Release(mutex_addr);
-    if (release_result.IsError()) {
-        return release_result;
+        current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
+
+        const auto release_result = current_process->GetMutex().Release(mutex_addr);
+        if (release_result.IsError()) {
+            lock.CancelSleep();
+            return release_result;
+        }
+
+        if (nano_seconds == 0) {
+            lock.CancelSleep();
+            return RESULT_TIMEOUT;
+        }
+
+        current_thread->SetCondVarWaitAddress(condition_variable_addr);
+        current_thread->SetMutexWaitAddress(mutex_addr);
+        current_thread->SetWaitHandle(thread_handle);
+        current_thread->SetStatus(ThreadStatus::WaitCondVar);
+        current_process->InsertConditionVariableThread(SharedFrom(current_thread));
     }
 
-    Thread* current_thread = system.CurrentScheduler().GetCurrentThread();
-    current_thread->SetCondVarWaitAddress(condition_variable_addr);
-    current_thread->SetMutexWaitAddress(mutex_addr);
-    current_thread->SetWaitHandle(thread_handle);
-    current_thread->SetStatus(ThreadStatus::WaitCondVar);
-    current_thread->InvalidateWakeupCallback();
-    current_process->InsertConditionVariableThread(SharedFrom(current_thread));
+    if (event_handle != InvalidHandle) {
+        auto& time_manager = kernel.TimeManager();
+        time_manager.UnscheduleTimeEvent(event_handle);
+    }
 
-    current_thread->WakeAfterDelay(nano_seconds);
+    {
+        SchedulerLock lock(kernel);
 
+        current_process->RemoveConditionVariableThread(SharedFrom(current_thread));
+    }
     // Note: Deliberately don't attempt to inherit the lock owner's priority.
 
-    return RESULT_SUCCESS;
+    return current_thread->GetSignalingResult();
 }
 
 /// Signal process wide key
@@ -1577,10 +1594,10 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
 
     ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4));
 
-    UNIMPLEMENTED();
-
     // Retrieve a list of all threads that are waiting for this condition variable.
-    auto* const current_process = system.Kernel().CurrentProcess();
+    auto& kernel = system.Kernel();
+    SchedulerLock lock(kernel);
+    auto* const current_process = kernel.CurrentProcess();
     std::vector<std::shared_ptr<Thread>> waiting_threads =
         current_process->GetConditionVariableThreads(condition_variable_addr);
 
@@ -1589,10 +1606,18 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
     std::size_t last = waiting_threads.size();
     if (target > 0)
         last = std::min(waiting_threads.size(), static_cast<std::size_t>(target));
-
+    auto& time_manager = kernel.TimeManager();
     for (std::size_t index = 0; index < last; ++index) {
         auto& thread = waiting_threads[index];
 
+        if (thread->GetStatus() != ThreadStatus::WaitCondVar) {
+            last++;
+            last = std::min(waiting_threads.size(), last);
+            continue;
+        }
+
+        time_manager.CancelTimeEvent(thread.get());
+
         ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr);
 
         // liberate Cond Var Thread.
@@ -1630,17 +1655,13 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
             }
 
             thread->SetLockOwner(nullptr);
-            thread->SetMutexWaitAddress(0);
-            thread->SetWaitHandle(0);
-            thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
+            thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS);
         } else {
             // The mutex is already owned by some other thread, make this thread wait on it.
             const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
             const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
             auto owner = handle_table.Get<Thread>(owner_handle);
             ASSERT(owner);
-            ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar);
-            thread->InvalidateWakeupCallback();
             thread->SetStatus(ThreadStatus::WaitMutex);
 
             owner->AddMutexWaiter(thread);
diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp
index b36e550a0..c60c5bb42 100644
--- a/src/core/hle/kernel/synchronization.cpp
+++ b/src/core/hle/kernel/synchronization.cpp
@@ -17,12 +17,15 @@ namespace Kernel {
 Synchronization::Synchronization(Core::System& system) : system{system} {}
 
 void Synchronization::SignalObject(SynchronizationObject& obj) const {
-    SchedulerLock lock(system.Kernel());
+    auto& kernel = system.Kernel();
+    SchedulerLock lock(kernel);
+    auto& time_manager = kernel.TimeManager();
     if (obj.IsSignaled()) {
         for (auto thread : obj.GetWaitingThreads()) {
             if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) {
                 thread->SetSynchronizationResults(&obj, RESULT_SUCCESS);
                 thread->ResumeFromWait();
+                time_manager.CancelTimeEvent(thread.get());
             }
         }
     }
@@ -79,6 +82,9 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor(
         SchedulerLock lock(kernel);
         ResultCode signaling_result = thread->GetSignalingResult();
         SynchronizationObject* signaling_object = thread->GetSignalingObject();
+        for (auto& obj : sync_objects) {
+            obj->RemoveWaitingThread(SharedFrom(thread));
+        }
         if (signaling_result == RESULT_SUCCESS) {
             const auto itr = std::find_if(
                 sync_objects.begin(), sync_objects.end(),
diff --git a/src/core/hle/kernel/synchronization_object.cpp b/src/core/hle/kernel/synchronization_object.cpp
index 43f3eef18..be9e09106 100644
--- a/src/core/hle/kernel/synchronization_object.cpp
+++ b/src/core/hle/kernel/synchronization_object.cpp
@@ -102,6 +102,10 @@ void SynchronizationObject::WakeupAllWaitingThreads() {
     }
 }
 
+void SynchronizationObject::ClearWaitingThreads() {
+    waiting_threads.clear();
+}
+
 const std::vector<std::shared_ptr<Thread>>& SynchronizationObject::GetWaitingThreads() const {
     return waiting_threads;
 }
diff --git a/src/core/hle/kernel/synchronization_object.h b/src/core/hle/kernel/synchronization_object.h
index 0a0d069e0..a35544ac1 100644
--- a/src/core/hle/kernel/synchronization_object.h
+++ b/src/core/hle/kernel/synchronization_object.h
@@ -68,6 +68,8 @@ public:
     /// Get a const reference to the waiting threads list for debug use
     const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const;
 
+    void ClearWaitingThreads();
+
 protected:
     bool is_signaled{}; // Tells if this sync object is signalled;
 
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index fb97535a3..a645ee3a2 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -49,12 +49,12 @@ Thread::~Thread() = default;
 void Thread::Stop() {
     SchedulerLock lock(kernel);
     // Cancel any outstanding wakeup events for this thread
+    Signal();
     Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(),
                                                              global_handle);
     kernel.GlobalHandleTable().Close(global_handle);
     global_handle = 0;
     SetStatus(ThreadStatus::Dead);
-    Signal();
 
     owner_process->UnregisterThread(this);
 
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp
index 0b8f0d993..dab5fc4c6 100644
--- a/src/core/hle/kernel/time_manager.cpp
+++ b/src/core/hle/kernel/time_manager.cpp
@@ -8,15 +8,21 @@
 #include "core/core_timing_util.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/time_manager.h"
 
 namespace Kernel {
 
-TimeManager::TimeManager(Core::System& system) : system{system} {
+TimeManager::TimeManager(Core::System& system_) : system{system_} {
     time_manager_event_type = Core::Timing::CreateEvent(
         "Kernel::TimeManagerCallback", [this](u64 thread_handle, [[maybe_unused]] s64 cycles_late) {
+            SchedulerLock lock(system.Kernel());
             Handle proper_handle = static_cast<Handle>(thread_handle);
+            if (cancelled_events[proper_handle]) {
+                return;
+            }
+            event_fired[proper_handle] = true;
             std::shared_ptr<Thread> thread =
                 this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
             thread->OnWakeUp();
@@ -24,14 +30,16 @@ TimeManager::TimeManager(Core::System& system) : system{system} {
 }
 
 void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 nanoseconds) {
+    event_handle = timetask->GetGlobalHandle();
     if (nanoseconds > 0) {
         ASSERT(timetask);
-        event_handle = timetask->GetGlobalHandle();
         const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds});
         system.CoreTiming().ScheduleEvent(cycles, time_manager_event_type, event_handle);
     } else {
         event_handle = InvalidHandle;
     }
+    cancelled_events[event_handle] = false;
+    event_fired[event_handle] = false;
 }
 
 void TimeManager::UnscheduleTimeEvent(Handle event_handle) {
@@ -39,6 +47,12 @@ void TimeManager::UnscheduleTimeEvent(Handle event_handle) {
         return;
     }
     system.CoreTiming().UnscheduleEvent(time_manager_event_type, event_handle);
+    cancelled_events[event_handle] = true;
+}
+
+void TimeManager::CancelTimeEvent(Thread* time_task) {
+    Handle event_handle = time_task->GetGlobalHandle();
+    UnscheduleTimeEvent(event_handle);
 }
 
 } // namespace Kernel
diff --git a/src/core/hle/kernel/time_manager.h b/src/core/hle/kernel/time_manager.h
index eaec486d1..3080ac838 100644
--- a/src/core/hle/kernel/time_manager.h
+++ b/src/core/hle/kernel/time_manager.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <memory>
+#include <unordered_map>
 
 #include "core/hle/kernel/object.h"
 
@@ -35,9 +36,13 @@ public:
     /// Unschedule an existing time event
     void UnscheduleTimeEvent(Handle event_handle);
 
+    void CancelTimeEvent(Thread* time_task);
+
 private:
     Core::System& system;
     std::shared_ptr<Core::Timing::EventType> time_manager_event_type;
+    std::unordered_map<Handle, bool> cancelled_events;
+    std::unordered_map<Handle, bool> event_fired;
 };
 
 } // namespace Kernel