core: hle: kernel: k_thread: Rework dummy thread waiting.
This commit is contained in:
parent
965c05b43d
commit
3f0b93925f
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue