summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp2
-rw-r--r--src/core/hle/kernel/k_condition_variable.cpp2
-rw-r--r--src/core/hle/kernel/k_synchronization_object.cpp1
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/svc.cpp1
-rw-r--r--src/core/hle/kernel/thread.cpp6
-rw-r--r--src/core/hle/kernel/thread.h21
-rw-r--r--src/yuzu/debugger/wait_tree.cpp43
8 files changed, 74 insertions, 4 deletions
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<ThreadState>((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<KSynchronizationObject*>& 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};
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index deefb0ba0..a93b5d3c2 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -251,7 +251,29 @@ QString WaitTreeThread::GetText() const {
}
break;
case Kernel::ThreadState::Waiting:
- status = tr("waiting");
+ switch (thread.GetWaitReasonForDebugging()) {
+ case Kernel::ThreadWaitReasonForDebugging::Sleep:
+ status = tr("sleeping");
+ break;
+ case Kernel::ThreadWaitReasonForDebugging::IPC:
+ status = tr("waiting for IPC reply");
+ break;
+ case Kernel::ThreadWaitReasonForDebugging::Synchronization:
+ status = tr("waiting for objects");
+ break;
+ case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
+ status = tr("waiting for condition variable");
+ break;
+ case Kernel::ThreadWaitReasonForDebugging::Arbitration:
+ status = tr("waiting for address arbiter");
+ break;
+ case Kernel::ThreadWaitReasonForDebugging::Suspended:
+ status = tr("waiting for suspend resume");
+ break;
+ default:
+ status = tr("waiting");
+ break;
+ }
break;
case Kernel::ThreadState::Initialized:
status = tr("initialized");
@@ -288,7 +310,20 @@ QColor WaitTreeThread::GetColor() const {
return QColor(WaitTreeColors[2][color_index]);
}
case Kernel::ThreadState::Waiting:
- return QColor(WaitTreeColors[3][color_index]);
+ switch (thread.GetWaitReasonForDebugging()) {
+ case Kernel::ThreadWaitReasonForDebugging::IPC:
+ return QColor(WaitTreeColors[4][color_index]);
+ case Kernel::ThreadWaitReasonForDebugging::Sleep:
+ return QColor(WaitTreeColors[5][color_index]);
+ case Kernel::ThreadWaitReasonForDebugging::Synchronization:
+ case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
+ case Kernel::ThreadWaitReasonForDebugging::Arbitration:
+ case Kernel::ThreadWaitReasonForDebugging::Suspended:
+ return QColor(WaitTreeColors[6][color_index]);
+ break;
+ default:
+ return QColor(WaitTreeColors[3][color_index]);
+ }
case Kernel::ThreadState::Initialized:
return QColor(WaitTreeColors[7][color_index]);
case Kernel::ThreadState::Terminated:
@@ -339,7 +374,9 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex")));
}
- if (thread.GetState() == Kernel::ThreadState::Waiting) {
+ if (thread.GetState() == Kernel::ThreadState::Waiting &&
+ thread.GetWaitReasonForDebugging() ==
+ Kernel::ThreadWaitReasonForDebugging::Synchronization) {
list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetWaitObjectsForDebugging(),
thread.IsCancellable()));
}