From 03dfc8d8e74910d447b755e00848a623ec65cd93 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 10 Jan 2021 14:29:02 -0800 Subject: hle: kernel: thread: Preserve thread wait reason for debugging only. - This is decoupled from core functionality and used for debugging only. --- src/core/hle/kernel/k_address_arbiter.cpp | 2 ++ src/core/hle/kernel/k_condition_variable.cpp | 2 ++ src/core/hle/kernel/k_synchronization_object.cpp | 1 + src/core/hle/kernel/kernel.cpp | 2 ++ src/core/hle/kernel/svc.cpp | 1 + src/core/hle/kernel/thread.cpp | 6 +++++- src/core/hle/kernel/thread.h | 21 +++++++++++++++++++++ 7 files changed, 34 insertions(+), 1 deletion(-) (limited to 'src/core/hle') diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 7b712d31a..d9e702f13 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -276,6 +276,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); thread_tree.insert(*cur_thread); cur_thread->SetState(ThreadState::Waiting); + cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } // Cancel the timer wait. @@ -339,6 +340,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); thread_tree.insert(*cur_thread); cur_thread->SetState(ThreadState::Waiting); + cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } // Cancel the timer wait. diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index ef5c17409..49a068310 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -133,6 +133,7 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val cur_thread->SetAddressKey(addr, value); owner_thread->AddWaiter(cur_thread); cur_thread->SetState(ThreadState::Waiting); + cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); cur_thread->SetMutexWaitAddressForDebugging(addr); } } @@ -315,6 +316,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) // If the timeout is non-zero, set the thread as waiting. if (timeout != 0) { cur_thread->SetState(ThreadState::Waiting); + cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); cur_thread->SetMutexWaitAddressForDebugging(addr); } } diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index 11b989ecd..1c508cb55 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -78,6 +78,7 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, thread->SetCancellable(); thread->SetSyncedObject(nullptr, Svc::ResultTimedOut); thread->SetState(ThreadState::Waiting); + thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); } // The lock/sleep is done, so we should be able to get our result. diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 8d03f16fb..c0ff287a6 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -605,6 +605,8 @@ void KernelCore::Suspend(bool in_suspention) { const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting; for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { impl->suspend_threads[i]->SetState(state); + impl->suspend_threads[i]->SetWaitReasonForDebugging( + ThreadWaitReasonForDebugging::Suspended); } } } diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 99bb4ea20..cc8b661af 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -347,6 +347,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { { KScopedSchedulerLock lock(kernel); thread->SetState(ThreadState::Waiting); + thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index eda56c31c..d97323255 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -215,7 +215,10 @@ VAddr Thread::GetCommandBufferAddress() const { void Thread::SetState(ThreadState state) { KScopedSchedulerLock sl(kernel); - SetMutexWaitAddressForDebugging(0); + // Clear debugging state + SetMutexWaitAddressForDebugging({}); + SetWaitReasonForDebugging({}); + const ThreadState old_state = thread_state; thread_state = static_cast((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)); @@ -386,6 +389,7 @@ ResultCode Thread::Sleep(s64 nanoseconds) { { KScopedSchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds); SetState(ThreadState::Waiting); + SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); } if (event_handle != InvalidHandle) { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 820ea524f..6b66c9a0e 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -114,6 +114,16 @@ enum class ThreadSchedFlags : u32 { KernelInitPauseFlag = 1 << 8, }; +enum class ThreadWaitReasonForDebugging : u32 { + None, ///< Thread is not waiting + Sleep, ///< Thread is waiting due to a SleepThread SVC + IPC, ///< Thread is waiting for the reply from an IPC request + Synchronization, ///< Thread is waiting due to a WaitSynchronization SVC + ConditionVar, ///< Thread is waiting due to a WaitProcessWideKey SVC + Arbitration, ///< Thread is waiting due to a SignalToAddress/WaitForAddress SVC + Suspended, ///< Thread is waiting due to process suspension +}; + class Thread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> { friend class KScheduler; friend class Process; @@ -515,6 +525,14 @@ public: disable_count--; } + void SetWaitReasonForDebugging(ThreadWaitReasonForDebugging reason) { + wait_reason_for_debugging = reason; + } + + [[nodiscard]] ThreadWaitReasonForDebugging GetWaitReasonForDebugging() const { + return wait_reason_for_debugging; + } + void SetWaitObjectsForDebugging(const std::span& objects) { wait_objects_for_debugging.clear(); wait_objects_for_debugging.reserve(objects.size()); @@ -708,6 +726,9 @@ private: /// The current mutex wait address. This is used for debugging only. VAddr mutex_wait_address_for_debugging{}; + /// The reason the thread is waiting. This is used for debugging only. + ThreadWaitReasonForDebugging wait_reason_for_debugging{}; + KSynchronizationObject* signaling_object; ResultCode signaling_result{RESULT_SUCCESS}; -- cgit v1.2.3