Просмотр исходного кода

hle: kernel: thread: Preserve thread wait reason for debugging only.

- This is decoupled from core functionality and used for debugging only.
bunnei 5 лет назад
Родитель
Сommit
03dfc8d8e7

+ 2 - 0
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.

+ 2 - 0
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);
         }
     }

+ 1 - 0
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.

+ 2 - 0
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);
         }
     }
 }

+ 1 - 0
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());
     }
 

+ 5 - 1
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) {

+ 21 - 0
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};
 

+ 40 - 3
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()));
     }