summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/k_thread.cpp39
-rw-r--r--src/core/hle/kernel/k_thread.h10
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(); });
1086void 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
1095void KThread::IfDummyThreadEndWait() { 1088void 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
1104void KThread::BeginWait(KThreadQueue* queue) { 1097void 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
1115void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) { 1105void 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
649private: 650private:
@@ -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;