diff options
| author | 2022-04-11 20:57:32 -0700 | |
|---|---|---|
| committer | 2022-04-11 21:15:38 -0700 | |
| commit | 3f0b93925f082b6defe9454f16f1260539994217 (patch) | |
| tree | 2bfa8f2638bc70174ea8c921b20017996b51a253 | |
| parent | core: hle: service: Allocate a service thread. (diff) | |
| download | yuzu-3f0b93925f082b6defe9454f16f1260539994217.tar.gz yuzu-3f0b93925f082b6defe9454f16f1260539994217.tar.xz yuzu-3f0b93925f082b6defe9454f16f1260539994217.zip | |
core: hle: kernel: k_thread: Rework dummy thread waiting.
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 39 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.h | 10 |
2 files changed, 21 insertions, 28 deletions
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index d3bb1c871..af71987e8 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -723,10 +723,10 @@ void KThread::UpdateState() { | |||
| 723 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 723 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 724 | 724 | ||
| 725 | // Set our suspend flags in state. | 725 | // Set our suspend flags in state. |
| 726 | const ThreadState old_state = thread_state; | 726 | const ThreadState old_state = thread_state.load(std::memory_order_relaxed); |
| 727 | const auto new_state = | 727 | const auto new_state = |
| 728 | static_cast<ThreadState>(this->GetSuspendFlags()) | (old_state & ThreadState::Mask); | 728 | static_cast<ThreadState>(this->GetSuspendFlags()) | (old_state & ThreadState::Mask); |
| 729 | thread_state = new_state; | 729 | thread_state.store(new_state, std::memory_order_relaxed); |
| 730 | 730 | ||
| 731 | // Note the state change in scheduler. | 731 | // Note the state change in scheduler. |
| 732 | if (new_state != old_state) { | 732 | if (new_state != old_state) { |
| @@ -738,8 +738,8 @@ void KThread::Continue() { | |||
| 738 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 738 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 739 | 739 | ||
| 740 | // Clear our suspend flags in state. | 740 | // Clear our suspend flags in state. |
| 741 | const ThreadState old_state = thread_state; | 741 | const ThreadState old_state = thread_state.load(std::memory_order_relaxed); |
| 742 | thread_state = old_state & ThreadState::Mask; | 742 | thread_state.store(old_state & ThreadState::Mask, std::memory_order_relaxed); |
| 743 | 743 | ||
| 744 | // Note the state change in scheduler. | 744 | // Note the state change in scheduler. |
| 745 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | 745 | KScheduler::OnThreadStateChanged(kernel, this, old_state); |
| @@ -1079,17 +1079,10 @@ void KThread::IfDummyThreadTryWait() { | |||
| 1079 | return; | 1079 | return; |
| 1080 | } | 1080 | } |
| 1081 | 1081 | ||
| 1082 | // Block until we can grab the lock. | 1082 | // Block until we are no longer waiting. |
| 1083 | KScopedSpinLock lk{dummy_wait_lock}; | 1083 | std::unique_lock lk(dummy_wait_lock); |
| 1084 | } | 1084 | dummy_wait_cv.wait( |
| 1085 | 1085 | lk, [&] { return GetState() != ThreadState::Waiting || kernel.IsShuttingDown(); }); | |
| 1086 | void KThread::IfDummyThreadBeginWait() { | ||
| 1087 | if (!IsDummyThread()) { | ||
| 1088 | return; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | // Ensure the thread will block when IfDummyThreadTryWait is called. | ||
| 1092 | dummy_wait_lock.Lock(); | ||
| 1093 | } | 1086 | } |
| 1094 | 1087 | ||
| 1095 | void KThread::IfDummyThreadEndWait() { | 1088 | void KThread::IfDummyThreadEndWait() { |
| @@ -1097,8 +1090,8 @@ void KThread::IfDummyThreadEndWait() { | |||
| 1097 | return; | 1090 | return; |
| 1098 | } | 1091 | } |
| 1099 | 1092 | ||
| 1100 | // Ensure the thread will no longer block. | 1093 | // Wake up the waiting thread. |
| 1101 | dummy_wait_lock.Unlock(); | 1094 | dummy_wait_cv.notify_one(); |
| 1102 | } | 1095 | } |
| 1103 | 1096 | ||
| 1104 | void KThread::BeginWait(KThreadQueue* queue) { | 1097 | void KThread::BeginWait(KThreadQueue* queue) { |
| @@ -1107,9 +1100,6 @@ void KThread::BeginWait(KThreadQueue* queue) { | |||
| 1107 | 1100 | ||
| 1108 | // Set our wait queue. | 1101 | // Set our wait queue. |
| 1109 | wait_queue = queue; | 1102 | wait_queue = queue; |
| 1110 | |||
| 1111 | // Special case for dummy threads to ensure they block. | ||
| 1112 | IfDummyThreadBeginWait(); | ||
| 1113 | } | 1103 | } |
| 1114 | 1104 | ||
| 1115 | void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) { | 1105 | void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) { |
| @@ -1158,10 +1148,11 @@ void KThread::SetState(ThreadState state) { | |||
| 1158 | SetMutexWaitAddressForDebugging({}); | 1148 | SetMutexWaitAddressForDebugging({}); |
| 1159 | SetWaitReasonForDebugging({}); | 1149 | SetWaitReasonForDebugging({}); |
| 1160 | 1150 | ||
| 1161 | const ThreadState old_state = thread_state; | 1151 | const ThreadState old_state = thread_state.load(std::memory_order_relaxed); |
| 1162 | thread_state = | 1152 | thread_state.store( |
| 1163 | static_cast<ThreadState>((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)); | 1153 | static_cast<ThreadState>((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)), |
| 1164 | if (thread_state != old_state) { | 1154 | std::memory_order_relaxed); |
| 1155 | if (thread_state.load(std::memory_order_relaxed) != old_state) { | ||
| 1165 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | 1156 | KScheduler::OnThreadStateChanged(kernel, this, old_state); |
| 1166 | } | 1157 | } |
| 1167 | } | 1158 | } |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index c141fc11b..4892fdf76 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <atomic> | 8 | #include <atomic> |
| 9 | #include <condition_variable> | ||
| 10 | #include <mutex> | ||
| 9 | #include <span> | 11 | #include <span> |
| 10 | #include <string> | 12 | #include <string> |
| 11 | #include <utility> | 13 | #include <utility> |
| @@ -257,11 +259,11 @@ public: | |||
| 257 | [[nodiscard]] std::shared_ptr<Common::Fiber>& GetHostContext(); | 259 | [[nodiscard]] std::shared_ptr<Common::Fiber>& GetHostContext(); |
| 258 | 260 | ||
| 259 | [[nodiscard]] ThreadState GetState() const { | 261 | [[nodiscard]] ThreadState GetState() const { |
| 260 | return thread_state & ThreadState::Mask; | 262 | return thread_state.load(std::memory_order_relaxed) & ThreadState::Mask; |
| 261 | } | 263 | } |
| 262 | 264 | ||
| 263 | [[nodiscard]] ThreadState GetRawState() const { | 265 | [[nodiscard]] ThreadState GetRawState() const { |
| 264 | return thread_state; | 266 | return thread_state.load(std::memory_order_relaxed); |
| 265 | } | 267 | } |
| 266 | 268 | ||
| 267 | void SetState(ThreadState state); | 269 | void SetState(ThreadState state); |
| @@ -643,7 +645,6 @@ public: | |||
| 643 | // blocking as needed. | 645 | // blocking as needed. |
| 644 | 646 | ||
| 645 | void IfDummyThreadTryWait(); | 647 | void IfDummyThreadTryWait(); |
| 646 | void IfDummyThreadBeginWait(); | ||
| 647 | void IfDummyThreadEndWait(); | 648 | void IfDummyThreadEndWait(); |
| 648 | 649 | ||
| 649 | private: | 650 | private: |
| @@ -764,12 +765,13 @@ private: | |||
| 764 | bool resource_limit_release_hint{}; | 765 | bool resource_limit_release_hint{}; |
| 765 | StackParameters stack_parameters{}; | 766 | StackParameters stack_parameters{}; |
| 766 | Common::SpinLock context_guard{}; | 767 | Common::SpinLock context_guard{}; |
| 767 | KSpinLock dummy_wait_lock{}; | ||
| 768 | 768 | ||
| 769 | // For emulation | 769 | // For emulation |
| 770 | std::shared_ptr<Common::Fiber> host_context{}; | 770 | std::shared_ptr<Common::Fiber> host_context{}; |
| 771 | bool is_single_core{}; | 771 | bool is_single_core{}; |
| 772 | ThreadType thread_type{}; | 772 | ThreadType thread_type{}; |
| 773 | std::mutex dummy_wait_lock; | ||
| 774 | std::condition_variable dummy_wait_cv; | ||
| 773 | 775 | ||
| 774 | // For debugging | 776 | // For debugging |
| 775 | std::vector<KSynchronizationObject*> wait_objects_for_debugging; | 777 | std::vector<KSynchronizationObject*> wait_objects_for_debugging; |