Browse Source

[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 <lizzie@eden-emu.dev>
lock-term-1
lizzie 2 months ago
parent
commit
d34400226b
No known key found for this signature in database GPG Key ID: 287378CADCAB13
  1. 22
      src/core/hle/kernel/k_thread.cpp

22
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<std::size_t>(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();

Loading…
Cancel
Save