core: hle: kernel: k_thread: Rework dummy thread waiting.

This commit is contained in:
bunnei 2022-04-11 20:57:32 -07:00
parent 965c05b43d
commit 3f0b93925f
2 changed files with 21 additions and 28 deletions

View file

@ -723,10 +723,10 @@ void KThread::UpdateState() {
ASSERT(kernel.GlobalSchedulerContext().IsLocked()); ASSERT(kernel.GlobalSchedulerContext().IsLocked());
// Set our suspend flags in state. // Set our suspend flags in state.
const ThreadState old_state = thread_state; const ThreadState old_state = thread_state.load(std::memory_order_relaxed);
const auto new_state = const auto new_state =
static_cast<ThreadState>(this->GetSuspendFlags()) | (old_state & ThreadState::Mask); static_cast<ThreadState>(this->GetSuspendFlags()) | (old_state & ThreadState::Mask);
thread_state = new_state; thread_state.store(new_state, std::memory_order_relaxed);
// Note the state change in scheduler. // Note the state change in scheduler.
if (new_state != old_state) { if (new_state != old_state) {
@ -738,8 +738,8 @@ void KThread::Continue() {
ASSERT(kernel.GlobalSchedulerContext().IsLocked()); ASSERT(kernel.GlobalSchedulerContext().IsLocked());
// Clear our suspend flags in state. // Clear our suspend flags in state.
const ThreadState old_state = thread_state; const ThreadState old_state = thread_state.load(std::memory_order_relaxed);
thread_state = old_state & ThreadState::Mask; thread_state.store(old_state & ThreadState::Mask, std::memory_order_relaxed);
// Note the state change in scheduler. // Note the state change in scheduler.
KScheduler::OnThreadStateChanged(kernel, this, old_state); KScheduler::OnThreadStateChanged(kernel, this, old_state);
@ -1079,17 +1079,10 @@ void KThread::IfDummyThreadTryWait() {
return; return;
} }
// Block until we can grab the lock. // Block until we are no longer waiting.
KScopedSpinLock lk{dummy_wait_lock}; std::unique_lock lk(dummy_wait_lock);
} dummy_wait_cv.wait(
lk, [&] { return GetState() != ThreadState::Waiting || kernel.IsShuttingDown(); });
void KThread::IfDummyThreadBeginWait() {
if (!IsDummyThread()) {
return;
}
// Ensure the thread will block when IfDummyThreadTryWait is called.
dummy_wait_lock.Lock();
} }
void KThread::IfDummyThreadEndWait() { void KThread::IfDummyThreadEndWait() {
@ -1097,8 +1090,8 @@ void KThread::IfDummyThreadEndWait() {
return; return;
} }
// Ensure the thread will no longer block. // Wake up the waiting thread.
dummy_wait_lock.Unlock(); dummy_wait_cv.notify_one();
} }
void KThread::BeginWait(KThreadQueue* queue) { void KThread::BeginWait(KThreadQueue* queue) {
@ -1107,9 +1100,6 @@ void KThread::BeginWait(KThreadQueue* queue) {
// Set our wait queue. // Set our wait queue.
wait_queue = queue; wait_queue = queue;
// Special case for dummy threads to ensure they block.
IfDummyThreadBeginWait();
} }
void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) { void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) {
@ -1158,10 +1148,11 @@ void KThread::SetState(ThreadState state) {
SetMutexWaitAddressForDebugging({}); SetMutexWaitAddressForDebugging({});
SetWaitReasonForDebugging({}); SetWaitReasonForDebugging({});
const ThreadState old_state = thread_state; const ThreadState old_state = thread_state.load(std::memory_order_relaxed);
thread_state = thread_state.store(
static_cast<ThreadState>((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)); static_cast<ThreadState>((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)),
if (thread_state != old_state) { std::memory_order_relaxed);
if (thread_state.load(std::memory_order_relaxed) != old_state) {
KScheduler::OnThreadStateChanged(kernel, this, old_state); KScheduler::OnThreadStateChanged(kernel, this, old_state);
} }
} }

View file

@ -6,6 +6,8 @@
#include <array> #include <array>
#include <atomic> #include <atomic>
#include <condition_variable>
#include <mutex>
#include <span> #include <span>
#include <string> #include <string>
#include <utility> #include <utility>
@ -257,11 +259,11 @@ public:
[[nodiscard]] std::shared_ptr<Common::Fiber>& GetHostContext(); [[nodiscard]] std::shared_ptr<Common::Fiber>& GetHostContext();
[[nodiscard]] ThreadState GetState() const { [[nodiscard]] ThreadState GetState() const {
return thread_state & ThreadState::Mask; return thread_state.load(std::memory_order_relaxed) & ThreadState::Mask;
} }
[[nodiscard]] ThreadState GetRawState() const { [[nodiscard]] ThreadState GetRawState() const {
return thread_state; return thread_state.load(std::memory_order_relaxed);
} }
void SetState(ThreadState state); void SetState(ThreadState state);
@ -643,7 +645,6 @@ public:
// blocking as needed. // blocking as needed.
void IfDummyThreadTryWait(); void IfDummyThreadTryWait();
void IfDummyThreadBeginWait();
void IfDummyThreadEndWait(); void IfDummyThreadEndWait();
private: private:
@ -764,12 +765,13 @@ private:
bool resource_limit_release_hint{}; bool resource_limit_release_hint{};
StackParameters stack_parameters{}; StackParameters stack_parameters{};
Common::SpinLock context_guard{}; Common::SpinLock context_guard{};
KSpinLock dummy_wait_lock{};
// For emulation // For emulation
std::shared_ptr<Common::Fiber> host_context{}; std::shared_ptr<Common::Fiber> host_context{};
bool is_single_core{}; bool is_single_core{};
ThreadType thread_type{}; ThreadType thread_type{};
std::mutex dummy_wait_lock;
std::condition_variable dummy_wait_cv;
// For debugging // For debugging
std::vector<KSynchronizationObject*> wait_objects_for_debugging; std::vector<KSynchronizationObject*> wait_objects_for_debugging;