diff options
| author | 2020-08-26 01:55:44 +0000 | |
|---|---|---|
| committer | 2020-08-26 02:56:05 +0000 | |
| commit | ccdd84a778244eb1ebbf7ea6e39d5fca79f16e2a (patch) | |
| tree | aab98e92a63c4ed5a3fcabef34dce8f8445278cf | |
| parent | Merge pull request #4572 from lioncash/xbyak (diff) | |
| download | yuzu-ccdd84a778244eb1ebbf7ea6e39d5fca79f16e2a.tar.gz yuzu-ccdd84a778244eb1ebbf7ea6e39d5fca79f16e2a.tar.xz yuzu-ccdd84a778244eb1ebbf7ea6e39d5fca79f16e2a.zip | |
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 a4b234424..5cbd3b912 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -756,7 +756,11 @@ void Scheduler::SwitchToCurrent() { | |||
| 756 | current_thread = selected_thread; | 756 | current_thread = selected_thread; |
| 757 | is_context_switch_pending = false; | 757 | is_context_switch_pending = false; |
| 758 | } | 758 | } |
| 759 | while (!is_context_switch_pending) { | 759 | const auto is_switch_pending = [this] { |
| 760 | std::scoped_lock lock{guard}; | ||
| 761 | return is_context_switch_pending; | ||
| 762 | }; | ||
| 763 | do { | ||
| 760 | if (current_thread != nullptr && !current_thread->IsHLEThread()) { | 764 | if (current_thread != nullptr && !current_thread->IsHLEThread()) { |
| 761 | current_thread->context_guard.lock(); | 765 | current_thread->context_guard.lock(); |
| 762 | if (!current_thread->IsRunnable()) { | 766 | if (!current_thread->IsRunnable()) { |
| @@ -775,7 +779,7 @@ void Scheduler::SwitchToCurrent() { | |||
| 775 | next_context = &idle_thread->GetHostContext(); | 779 | next_context = &idle_thread->GetHostContext(); |
| 776 | } | 780 | } |
| 777 | Common::Fiber::YieldTo(switch_fiber, *next_context); | 781 | Common::Fiber::YieldTo(switch_fiber, *next_context); |
| 778 | } | 782 | } while (!is_switch_pending()); |
| 779 | } | 783 | } |
| 780 | } | 784 | } |
| 781 | 785 | ||