diff options
| author | bunnei <bunneidev@gmail.com> | 2021-01-10 14:29:02 -0800 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2021-01-11 14:23:17 -0800 | 
| commit | 03dfc8d8e74910d447b755e00848a623ec65cd93 (patch) | |
| tree | 56a80760bd0ba8ecd85dc8d9f09fb9e2068c91d4 | |
| parent | 81c1bfafeac88d0651d146056e9008c22bea87d2 (diff) | |
hle: kernel: thread: Preserve thread wait reason for debugging only.
- This is decoupled from core functionality and used for debugging only.
| -rw-r--r-- | src/core/hle/kernel/k_address_arbiter.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_condition_variable.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_synchronization_object.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 21 | ||||
| -rw-r--r-- | src/yuzu/debugger/wait_tree.cpp | 43 | 
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()));      } | 
