diff options
author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2020-08-26 01:55:44 +0000 |
---|---|---|
committer | ReinUsesLisp <reinuseslisp@airmail.cc> | 2020-08-26 02:56:05 +0000 |
commit | ccdd84a778244eb1ebbf7ea6e39d5fca79f16e2a (patch) | |
tree | aab98e92a63c4ed5a3fcabef34dce8f8445278cf | |
parent | 4efaecf1251b152536cbf84af2616f3181d64960 (diff) |
hle/scheduler: Fix data race in is_context_switch_pending
As reported by tsan, SelectThreads could write to
is_context_switch_pending holding a mutex while SwitchToCurrent reads it
without holding any.
It is assumed that the author didn't want an atomic here, so the code is
reordered so that whenever is_context_switch_pending is read inside
SwitchToContext, the mutex is locked.
-rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index a4b2344243..5cbd3b912c 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -756,7 +756,11 @@ void Scheduler::SwitchToCurrent() { current_thread = selected_thread; is_context_switch_pending = false; } - while (!is_context_switch_pending) { + const auto is_switch_pending = [this] { + std::scoped_lock lock{guard}; + return is_context_switch_pending; + }; + do { if (current_thread != nullptr && !current_thread->IsHLEThread()) { current_thread->context_guard.lock(); if (!current_thread->IsRunnable()) { @@ -775,7 +779,7 @@ void Scheduler::SwitchToCurrent() { next_context = &idle_thread->GetHostContext(); } Common::Fiber::YieldTo(switch_fiber, *next_context); - } + } while (!is_switch_pending()); } } |