From f6cbb14dce48bc4ae112a7d5ae2bbca476d3457e Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 17 Jan 2022 16:41:06 -0800 Subject: hle: kernel: KThread: Rename thread_type_for_debugging -> thread_type. - This will be used to ensure that we do not schedule dummy threads. --- src/core/hle/kernel/k_thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel/k_thread.cpp') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 7a5e6fc08..5eb64a381 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -140,7 +140,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s UNREACHABLE_MSG("KThread::Initialize: Unknown ThreadType {}", static_cast(type)); break; } - thread_type_for_debugging = type; + thread_type = type; // Set the ideal core ID and affinity mask. virtual_ideal_core_id = virt_core; -- cgit v1.2.3 From 5ffec69dc79f489631916b71d89090e837997f01 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 17 Jan 2022 16:46:29 -0800 Subject: hle: kernel: KThread: Ensure dummy threads never call EndWait. - These are only used by host threads for locking and will never have a wait_queue. --- src/core/hle/kernel/k_thread.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core/hle/kernel/k_thread.cpp') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 5eb64a381..35c4a7581 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -1097,6 +1097,11 @@ void KThread::EndWait(ResultCode wait_result_) { // Lock the scheduler. KScopedSchedulerLock sl(kernel); + // Dummy threads are just used by host threads for locking, and will never have a wait_queue. + if (thread_type == ThreadType::Dummy) { + return; + } + // If we're waiting, notify our queue that we're available. if (GetState() == ThreadState::Waiting) { wait_queue->EndWait(this, wait_result_); -- cgit v1.2.3 From 46a620f9d7c0fa2a4f1143ebf28bba4fee12d1a1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 17 Jan 2022 18:48:14 -0800 Subject: hle: kernel: KThread: Decrease DummyThread priority to ensure it is never scheduled. --- src/core/hle/kernel/k_thread.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/k_thread.cpp') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 35c4a7581..a599723e6 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -106,7 +106,7 @@ KThread::~KThread() = default; ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, s32 virt_core, KProcess* owner, ThreadType type) { // Assert parameters are valid. - ASSERT((type == ThreadType::Main) || + ASSERT((type == ThreadType::Main) || (type == ThreadType::Dummy) || (Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority)); ASSERT((owner != nullptr) || (type != ThreadType::User)); ASSERT(0 <= virt_core && virt_core < static_cast(Common::BitSize())); @@ -262,7 +262,7 @@ ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uint } ResultCode KThread::InitializeDummyThread(KThread* thread) { - return thread->Initialize({}, {}, {}, DefaultThreadPriority, 3, {}, ThreadType::Dummy); + return thread->Initialize({}, {}, {}, DummyThreadPriority, 3, {}, ThreadType::Dummy); } ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { @@ -1099,6 +1099,7 @@ void KThread::EndWait(ResultCode wait_result_) { // Dummy threads are just used by host threads for locking, and will never have a wait_queue. if (thread_type == ThreadType::Dummy) { + ASSERT_MSG(false, "Dummy threads should never call EndWait!"); return; } -- cgit v1.2.3 From 91ff6d4cb3aa4010e5856993c9291627c5c38f99 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 18 Jan 2022 17:56:08 -0800 Subject: hle: kernel: KThread: DummyThread can be waited, ensure wait_queue is not nullptr. --- src/core/hle/kernel/k_thread.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/core/hle/kernel/k_thread.cpp') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index a599723e6..4cbf12c11 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -1097,14 +1097,14 @@ void KThread::EndWait(ResultCode wait_result_) { // Lock the scheduler. KScopedSchedulerLock sl(kernel); - // Dummy threads are just used by host threads for locking, and will never have a wait_queue. - if (thread_type == ThreadType::Dummy) { - ASSERT_MSG(false, "Dummy threads should never call EndWait!"); - return; - } - // If we're waiting, notify our queue that we're available. if (GetState() == ThreadState::Waiting) { + if (wait_queue == nullptr) { + // This should never happen, but avoid a hard crash below to get this logged. + ASSERT_MSG(false, "wait_queue is nullptr!"); + return; + } + wait_queue->EndWait(this, wait_result_); } } -- cgit v1.2.3 From 615fb40416b9ee10abf40a036b31d1540886a9b8 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 21 Jan 2022 17:10:11 -0800 Subject: hle: kernel: KThread: Ensure host (dummy) threads block on locking. - But do not enter the priority queue, as otherwise they will be scheduled. - Allows dummy threads to use guest synchronization primitives. --- src/core/hle/kernel/k_thread.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'src/core/hle/kernel/k_thread.cpp') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 4cbf12c11..f42abb8a1 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -1075,12 +1075,46 @@ ResultCode KThread::Sleep(s64 timeout) { return ResultSuccess; } +void KThread::IfDummyThreadTryWait() { + if (!IsDummyThread()) { + return; + } + + if (GetState() != ThreadState::Waiting) { + return; + } + + // Block until we can grab the lock. + KScopedSpinLock lk{dummy_wait_lock}; +} + +void KThread::IfDummyThreadBeginWait() { + if (!IsDummyThread()) { + return; + } + + // Ensure the thread will block when IfDummyThreadTryWait is called. + dummy_wait_lock.Lock(); +} + +void KThread::IfDummyThreadEndWait() { + if (!IsDummyThread()) { + return; + } + + // Ensure the thread will no longer block. + dummy_wait_lock.Unlock(); +} + void KThread::BeginWait(KThreadQueue* queue) { // Set our state as waiting. SetState(ThreadState::Waiting); // Set our wait queue. wait_queue = queue; + + // Special case for dummy threads to ensure they block. + IfDummyThreadBeginWait(); } void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) { @@ -1106,6 +1140,9 @@ void KThread::EndWait(ResultCode wait_result_) { } wait_queue->EndWait(this, wait_result_); + + // Special case for dummy threads to wakeup if necessary. + IfDummyThreadEndWait(); } } -- cgit v1.2.3