summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2021-01-10 14:29:02 -0800
committerGravatar bunnei2021-01-11 14:23:17 -0800
commit03dfc8d8e74910d447b755e00848a623ec65cd93 (patch)
tree56a80760bd0ba8ecd85dc8d9f09fb9e2068c91d4 /src
parentyuzu: debugger: wait_tree: Handle unknown ThreadState. (diff)
downloadyuzu-03dfc8d8e74910d447b755e00848a623ec65cd93.tar.gz
yuzu-03dfc8d8e74910d447b755e00848a623ec65cd93.tar.xz
yuzu-03dfc8d8e74910d447b755e00848a623ec65cd93.zip
hle: kernel: thread: Preserve thread wait reason for debugging only.
- This is decoupled from core functionality and used for debugging only.
Diffstat (limited to 'src')
-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
276 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 276 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr);
277 thread_tree.insert(*cur_thread); 277 thread_tree.insert(*cur_thread);
278 cur_thread->SetState(ThreadState::Waiting); 278 cur_thread->SetState(ThreadState::Waiting);
279 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
279 } 280 }
280 281
281 // Cancel the timer wait. 282 // Cancel the timer wait.
@@ -339,6 +340,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
339 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 340 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr);
340 thread_tree.insert(*cur_thread); 341 thread_tree.insert(*cur_thread);
341 cur_thread->SetState(ThreadState::Waiting); 342 cur_thread->SetState(ThreadState::Waiting);
343 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
342 } 344 }
343 345
344 // Cancel the timer wait. 346 // 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
133 cur_thread->SetAddressKey(addr, value); 133 cur_thread->SetAddressKey(addr, value);
134 owner_thread->AddWaiter(cur_thread); 134 owner_thread->AddWaiter(cur_thread);
135 cur_thread->SetState(ThreadState::Waiting); 135 cur_thread->SetState(ThreadState::Waiting);
136 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar);
136 cur_thread->SetMutexWaitAddressForDebugging(addr); 137 cur_thread->SetMutexWaitAddressForDebugging(addr);
137 } 138 }
138 } 139 }
@@ -315,6 +316,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout)
315 // If the timeout is non-zero, set the thread as waiting. 316 // If the timeout is non-zero, set the thread as waiting.
316 if (timeout != 0) { 317 if (timeout != 0) {
317 cur_thread->SetState(ThreadState::Waiting); 318 cur_thread->SetState(ThreadState::Waiting);
319 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar);
318 cur_thread->SetMutexWaitAddressForDebugging(addr); 320 cur_thread->SetMutexWaitAddressForDebugging(addr);
319 } 321 }
320 } 322 }
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,
78 thread->SetCancellable(); 78 thread->SetCancellable();
79 thread->SetSyncedObject(nullptr, Svc::ResultTimedOut); 79 thread->SetSyncedObject(nullptr, Svc::ResultTimedOut);
80 thread->SetState(ThreadState::Waiting); 80 thread->SetState(ThreadState::Waiting);
81 thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization);
81 } 82 }
82 83
83 // The lock/sleep is done, so we should be able to get our result. 84 // 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) {
605 const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting; 605 const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting;
606 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { 606 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
607 impl->suspend_threads[i]->SetState(state); 607 impl->suspend_threads[i]->SetState(state);
608 impl->suspend_threads[i]->SetWaitReasonForDebugging(
609 ThreadWaitReasonForDebugging::Suspended);
608 } 610 }
609 } 611 }
610} 612}
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) {
347 { 347 {
348 KScopedSchedulerLock lock(kernel); 348 KScopedSchedulerLock lock(kernel);
349 thread->SetState(ThreadState::Waiting); 349 thread->SetState(ThreadState::Waiting);
350 thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
350 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); 351 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming());
351 } 352 }
352 353
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 {
215void Thread::SetState(ThreadState state) { 215void Thread::SetState(ThreadState state) {
216 KScopedSchedulerLock sl(kernel); 216 KScopedSchedulerLock sl(kernel);
217 217
218 SetMutexWaitAddressForDebugging(0); 218 // Clear debugging state
219 SetMutexWaitAddressForDebugging({});
220 SetWaitReasonForDebugging({});
221
219 const ThreadState old_state = thread_state; 222 const ThreadState old_state = thread_state;
220 thread_state = 223 thread_state =
221 static_cast<ThreadState>((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)); 224 static_cast<ThreadState>((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask));
@@ -386,6 +389,7 @@ ResultCode Thread::Sleep(s64 nanoseconds) {
386 { 389 {
387 KScopedSchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds); 390 KScopedSchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds);
388 SetState(ThreadState::Waiting); 391 SetState(ThreadState::Waiting);
392 SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep);
389 } 393 }
390 394
391 if (event_handle != InvalidHandle) { 395 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 {
114 KernelInitPauseFlag = 1 << 8, 114 KernelInitPauseFlag = 1 << 8,
115}; 115};
116 116
117enum class ThreadWaitReasonForDebugging : u32 {
118 None, ///< Thread is not waiting
119 Sleep, ///< Thread is waiting due to a SleepThread SVC
120 IPC, ///< Thread is waiting for the reply from an IPC request
121 Synchronization, ///< Thread is waiting due to a WaitSynchronization SVC
122 ConditionVar, ///< Thread is waiting due to a WaitProcessWideKey SVC
123 Arbitration, ///< Thread is waiting due to a SignalToAddress/WaitForAddress SVC
124 Suspended, ///< Thread is waiting due to process suspension
125};
126
117class Thread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> { 127class Thread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> {
118 friend class KScheduler; 128 friend class KScheduler;
119 friend class Process; 129 friend class Process;
@@ -515,6 +525,14 @@ public:
515 disable_count--; 525 disable_count--;
516 } 526 }
517 527
528 void SetWaitReasonForDebugging(ThreadWaitReasonForDebugging reason) {
529 wait_reason_for_debugging = reason;
530 }
531
532 [[nodiscard]] ThreadWaitReasonForDebugging GetWaitReasonForDebugging() const {
533 return wait_reason_for_debugging;
534 }
535
518 void SetWaitObjectsForDebugging(const std::span<KSynchronizationObject*>& objects) { 536 void SetWaitObjectsForDebugging(const std::span<KSynchronizationObject*>& objects) {
519 wait_objects_for_debugging.clear(); 537 wait_objects_for_debugging.clear();
520 wait_objects_for_debugging.reserve(objects.size()); 538 wait_objects_for_debugging.reserve(objects.size());
@@ -708,6 +726,9 @@ private:
708 /// The current mutex wait address. This is used for debugging only. 726 /// The current mutex wait address. This is used for debugging only.
709 VAddr mutex_wait_address_for_debugging{}; 727 VAddr mutex_wait_address_for_debugging{};
710 728
729 /// The reason the thread is waiting. This is used for debugging only.
730 ThreadWaitReasonForDebugging wait_reason_for_debugging{};
731
711 KSynchronizationObject* signaling_object; 732 KSynchronizationObject* signaling_object;
712 ResultCode signaling_result{RESULT_SUCCESS}; 733 ResultCode signaling_result{RESULT_SUCCESS};
713 734
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 {
251 } 251 }
252 break; 252 break;
253 case Kernel::ThreadState::Waiting: 253 case Kernel::ThreadState::Waiting:
254 status = tr("waiting"); 254 switch (thread.GetWaitReasonForDebugging()) {
255 case Kernel::ThreadWaitReasonForDebugging::Sleep:
256 status = tr("sleeping");
257 break;
258 case Kernel::ThreadWaitReasonForDebugging::IPC:
259 status = tr("waiting for IPC reply");
260 break;
261 case Kernel::ThreadWaitReasonForDebugging::Synchronization:
262 status = tr("waiting for objects");
263 break;
264 case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
265 status = tr("waiting for condition variable");
266 break;
267 case Kernel::ThreadWaitReasonForDebugging::Arbitration:
268 status = tr("waiting for address arbiter");
269 break;
270 case Kernel::ThreadWaitReasonForDebugging::Suspended:
271 status = tr("waiting for suspend resume");
272 break;
273 default:
274 status = tr("waiting");
275 break;
276 }
255 break; 277 break;
256 case Kernel::ThreadState::Initialized: 278 case Kernel::ThreadState::Initialized:
257 status = tr("initialized"); 279 status = tr("initialized");
@@ -288,7 +310,20 @@ QColor WaitTreeThread::GetColor() const {
288 return QColor(WaitTreeColors[2][color_index]); 310 return QColor(WaitTreeColors[2][color_index]);
289 } 311 }
290 case Kernel::ThreadState::Waiting: 312 case Kernel::ThreadState::Waiting:
291 return QColor(WaitTreeColors[3][color_index]); 313 switch (thread.GetWaitReasonForDebugging()) {
314 case Kernel::ThreadWaitReasonForDebugging::IPC:
315 return QColor(WaitTreeColors[4][color_index]);
316 case Kernel::ThreadWaitReasonForDebugging::Sleep:
317 return QColor(WaitTreeColors[5][color_index]);
318 case Kernel::ThreadWaitReasonForDebugging::Synchronization:
319 case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
320 case Kernel::ThreadWaitReasonForDebugging::Arbitration:
321 case Kernel::ThreadWaitReasonForDebugging::Suspended:
322 return QColor(WaitTreeColors[6][color_index]);
323 break;
324 default:
325 return QColor(WaitTreeColors[3][color_index]);
326 }
292 case Kernel::ThreadState::Initialized: 327 case Kernel::ThreadState::Initialized:
293 return QColor(WaitTreeColors[7][color_index]); 328 return QColor(WaitTreeColors[7][color_index]);
294 case Kernel::ThreadState::Terminated: 329 case Kernel::ThreadState::Terminated:
@@ -339,7 +374,9 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
339 list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex"))); 374 list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex")));
340 } 375 }
341 376
342 if (thread.GetState() == Kernel::ThreadState::Waiting) { 377 if (thread.GetState() == Kernel::ThreadState::Waiting &&
378 thread.GetWaitReasonForDebugging() ==
379 Kernel::ThreadWaitReasonForDebugging::Synchronization) {
343 list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetWaitObjectsForDebugging(), 380 list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetWaitObjectsForDebugging(),
344 thread.IsCancellable())); 381 thread.IsCancellable()));
345 } 382 }