From d34400226b1146203e2e9d897f5af6af08c39579 Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 30 Oct 2025 20:02:21 +0000 Subject: [PATCH] [core/hle/kernel] fix potential datarace where thread may be told to be non-running but inbetween the acquisition of the lock there may be another holder whom puts it on Signed-off-by: lizzie --- src/core/hle/kernel/k_thread.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 6b68a56ab4..9916a4fde6 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -429,19 +429,23 @@ void KThread::StartTermination() { } void KThread::FinishTermination() { + // Acquire the scheduler lock. + KScopedSchedulerLock lk{m_kernel}; + // Ensure that the thread is not executing on any core. if (m_parent != nullptr) { - for (std::size_t i = 0; i < static_cast(Core::Hardware::NUM_CPU_CORES); ++i) { - KThread* core_thread{}; - do { - core_thread = m_kernel.Scheduler(i).GetSchedulerCurrentThread(); - } while (core_thread == this); + bool wait_thread = true; + lk.unlock(); + while (wait_thread) { + // now "pin" the scheduler so it wont change stuff mid-way + lk.lock(); + for (std::size_t i = 0; i < std::size_t(Core::Hardware::NUM_CPU_CORES); ++i) + is_on_schedule |= m_kernel.Scheduler(i).GetSchedulerCurrentThread() == this; + // let scheduler try again + if (wait_thread) + lk.unlock(); } } - - // Acquire the scheduler lock. - KScopedSchedulerLock sl{m_kernel}; - // Signal. m_signaled = true; KSynchronizationObject::NotifyAvailable();