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.
This commit is contained in:
ReinUsesLisp 2020-08-26 01:55:44 +00:00
parent 4efaecf125
commit ccdd84a778

View File

@ -756,7 +756,11 @@ void Scheduler::SwitchToCurrent() {
current_thread = selected_thread; current_thread = selected_thread;
is_context_switch_pending = false; 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()) { if (current_thread != nullptr && !current_thread->IsHLEThread()) {
current_thread->context_guard.lock(); current_thread->context_guard.lock();
if (!current_thread->IsRunnable()) { if (!current_thread->IsRunnable()) {
@ -775,7 +779,7 @@ void Scheduler::SwitchToCurrent() {
next_context = &idle_thread->GetHostContext(); next_context = &idle_thread->GetHostContext();
} }
Common::Fiber::YieldTo(switch_fiber, *next_context); Common::Fiber::YieldTo(switch_fiber, *next_context);
} } while (!is_switch_pending());
} }
} }