summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/hle_ipc.h5
-rw-r--r--src/core/hle/kernel/k_priority_queue.h36
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp9
-rw-r--r--src/core/hle/kernel/k_server_session.cpp20
-rw-r--r--src/core/hle/kernel/k_thread.cpp49
-rw-r--r--src/core/hle/kernel/k_thread.h20
-rw-r--r--src/core/hle/kernel/kernel.cpp12
-rw-r--r--src/core/hle/kernel/service_thread.cpp5
-rw-r--r--src/yuzu/debugger/wait_tree.cpp4
9 files changed, 120 insertions, 40 deletions
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 55e6fb9f7..754b41ff6 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -341,10 +341,6 @@ public:
341 return *thread; 341 return *thread;
342 } 342 }
343 343
344 bool IsThreadWaiting() const {
345 return is_thread_waiting;
346 }
347
348private: 344private:
349 friend class IPC::ResponseBuilder; 345 friend class IPC::ResponseBuilder;
350 346
@@ -379,7 +375,6 @@ private:
379 u32 domain_offset{}; 375 u32 domain_offset{};
380 376
381 std::shared_ptr<SessionRequestManager> manager; 377 std::shared_ptr<SessionRequestManager> manager;
382 bool is_thread_waiting{};
383 378
384 KernelCore& kernel; 379 KernelCore& kernel;
385 Core::Memory::Memory& memory; 380 Core::Memory::Memory& memory;
diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h
index f4d71ad7e..0b894c8cf 100644
--- a/src/core/hle/kernel/k_priority_queue.h
+++ b/src/core/hle/kernel/k_priority_queue.h
@@ -45,6 +45,7 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) {
45 45
46 { t.GetActiveCore() } -> Common::ConvertibleTo<s32>; 46 { t.GetActiveCore() } -> Common::ConvertibleTo<s32>;
47 { t.GetPriority() } -> Common::ConvertibleTo<s32>; 47 { t.GetPriority() } -> Common::ConvertibleTo<s32>;
48 { t.IsDummyThread() } -> Common::ConvertibleTo<bool>;
48}; 49};
49 50
50template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority> 51template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>
@@ -349,24 +350,49 @@ public:
349 350
350 // Mutators. 351 // Mutators.
351 constexpr void PushBack(Member* member) { 352 constexpr void PushBack(Member* member) {
353 // This is for host (dummy) threads that we do not want to enter the priority queue.
354 if (member->IsDummyThread()) {
355 return;
356 }
357
352 this->PushBack(member->GetPriority(), member); 358 this->PushBack(member->GetPriority(), member);
353 } 359 }
354 360
355 constexpr void Remove(Member* member) { 361 constexpr void Remove(Member* member) {
362 // This is for host (dummy) threads that we do not want to enter the priority queue.
363 if (member->IsDummyThread()) {
364 return;
365 }
366
356 this->Remove(member->GetPriority(), member); 367 this->Remove(member->GetPriority(), member);
357 } 368 }
358 369
359 constexpr void MoveToScheduledFront(Member* member) { 370 constexpr void MoveToScheduledFront(Member* member) {
371 // This is for host (dummy) threads that we do not want to enter the priority queue.
372 if (member->IsDummyThread()) {
373 return;
374 }
375
360 this->scheduled_queue.MoveToFront(member->GetPriority(), member->GetActiveCore(), member); 376 this->scheduled_queue.MoveToFront(member->GetPriority(), member->GetActiveCore(), member);
361 } 377 }
362 378
363 constexpr KThread* MoveToScheduledBack(Member* member) { 379 constexpr KThread* MoveToScheduledBack(Member* member) {
380 // This is for host (dummy) threads that we do not want to enter the priority queue.
381 if (member->IsDummyThread()) {
382 return {};
383 }
384
364 return this->scheduled_queue.MoveToBack(member->GetPriority(), member->GetActiveCore(), 385 return this->scheduled_queue.MoveToBack(member->GetPriority(), member->GetActiveCore(),
365 member); 386 member);
366 } 387 }
367 388
368 // First class fancy operations. 389 // First class fancy operations.
369 constexpr void ChangePriority(s32 prev_priority, bool is_running, Member* member) { 390 constexpr void ChangePriority(s32 prev_priority, bool is_running, Member* member) {
391 // This is for host (dummy) threads that we do not want to enter the priority queue.
392 if (member->IsDummyThread()) {
393 return;
394 }
395
370 ASSERT(IsValidPriority(prev_priority)); 396 ASSERT(IsValidPriority(prev_priority));
371 397
372 // Remove the member from the queues. 398 // Remove the member from the queues.
@@ -383,6 +409,11 @@ public:
383 409
384 constexpr void ChangeAffinityMask(s32 prev_core, const AffinityMaskType& prev_affinity, 410 constexpr void ChangeAffinityMask(s32 prev_core, const AffinityMaskType& prev_affinity,
385 Member* member) { 411 Member* member) {
412 // This is for host (dummy) threads that we do not want to enter the priority queue.
413 if (member->IsDummyThread()) {
414 return;
415 }
416
386 // Get the new information. 417 // Get the new information.
387 const s32 priority = member->GetPriority(); 418 const s32 priority = member->GetPriority();
388 const AffinityMaskType& new_affinity = member->GetAffinityMask(); 419 const AffinityMaskType& new_affinity = member->GetAffinityMask();
@@ -412,6 +443,11 @@ public:
412 } 443 }
413 444
414 constexpr void ChangeCore(s32 prev_core, Member* member, bool to_front = false) { 445 constexpr void ChangeCore(s32 prev_core, Member* member, bool to_front = false) {
446 // This is for host (dummy) threads that we do not want to enter the priority queue.
447 if (member->IsDummyThread()) {
448 return;
449 }
450
415 // Get the new information. 451 // Get the new information.
416 const s32 new_core = member->GetActiveCore(); 452 const s32 new_core = member->GetActiveCore();
417 const s32 priority = member->GetPriority(); 453 const s32 priority = member->GetPriority();
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index f900b2e7a..b32d4f285 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -406,6 +406,9 @@ void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduli
406 } else { 406 } else {
407 RescheduleCores(kernel, cores_needing_scheduling); 407 RescheduleCores(kernel, cores_needing_scheduling);
408 } 408 }
409
410 // Special case to ensure dummy threads that are waiting block.
411 current_thread->IfDummyThreadTryWait();
409} 412}
410 413
411u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) { 414u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) {
@@ -739,6 +742,12 @@ void KScheduler::ScheduleImpl() {
739 next_thread = idle_thread; 742 next_thread = idle_thread;
740 } 743 }
741 744
745 // We never want to schedule a dummy thread, as these are only used by host threads for locking.
746 if (next_thread->GetThreadType() == ThreadType::Dummy) {
747 ASSERT_MSG(false, "Dummy threads should never be scheduled!");
748 next_thread = idle_thread;
749 }
750
742 // If we're not actually switching thread, there's nothing to do. 751 // If we're not actually switching thread, there's nothing to do.
743 if (next_thread == current_thread.load()) { 752 if (next_thread == current_thread.load()) {
744 previous_thread->EnableDispatch(); 753 previous_thread->EnableDispatch();
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index d4e4a6b06..4d94eb9cf 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -8,7 +8,6 @@
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/scope_exit.h"
12#include "core/core_timing.h" 11#include "core/core_timing.h"
13#include "core/hle/ipc_helpers.h" 12#include "core/hle/ipc_helpers.h"
14#include "core/hle/kernel/hle_ipc.h" 13#include "core/hle/kernel/hle_ipc.h"
@@ -123,20 +122,10 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor
123 122
124 context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); 123 context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
125 124
126 // In the event that something fails here, stub a result to prevent the game from crashing.
127 // This is a work-around in the event that somehow we process a service request after the
128 // session has been closed by the game. This has been observed to happen rarely in Pokemon
129 // Sword/Shield and is likely a result of us using host threads/scheduling for services.
130 // TODO(bunnei): Find a better solution here.
131 auto error_guard = SCOPE_GUARD({ CompleteSyncRequest(*context); });
132
133 // Ensure we have a session request handler 125 // Ensure we have a session request handler
134 if (manager->HasSessionRequestHandler(*context)) { 126 if (manager->HasSessionRequestHandler(*context)) {
135 if (auto strong_ptr = manager->GetServiceThread().lock()) { 127 if (auto strong_ptr = manager->GetServiceThread().lock()) {
136 strong_ptr->QueueSyncRequest(*parent, std::move(context)); 128 strong_ptr->QueueSyncRequest(*parent, std::move(context));
137
138 // We succeeded.
139 error_guard.Cancel();
140 } else { 129 } else {
141 ASSERT_MSG(false, "strong_ptr is nullptr!"); 130 ASSERT_MSG(false, "strong_ptr is nullptr!");
142 } 131 }
@@ -171,13 +160,8 @@ ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) {
171 convert_to_domain = false; 160 convert_to_domain = false;
172 } 161 }
173 162
174 // Some service requests require the thread to block 163 // The calling thread is waiting for this request to complete, so wake it up.
175 { 164 context.GetThread().EndWait(result);
176 KScopedSchedulerLock lock(kernel);
177 if (!context.IsThreadWaiting()) {
178 context.GetThread().EndWait(result);
179 }
180 }
181 165
182 return result; 166 return result;
183} 167}
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 7a5e6fc08..f42abb8a1 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -106,7 +106,7 @@ KThread::~KThread() = default;
106ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, 106ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio,
107 s32 virt_core, KProcess* owner, ThreadType type) { 107 s32 virt_core, KProcess* owner, ThreadType type) {
108 // Assert parameters are valid. 108 // Assert parameters are valid.
109 ASSERT((type == ThreadType::Main) || 109 ASSERT((type == ThreadType::Main) || (type == ThreadType::Dummy) ||
110 (Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority)); 110 (Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority));
111 ASSERT((owner != nullptr) || (type != ThreadType::User)); 111 ASSERT((owner != nullptr) || (type != ThreadType::User));
112 ASSERT(0 <= virt_core && virt_core < static_cast<s32>(Common::BitSize<u64>())); 112 ASSERT(0 <= virt_core && virt_core < static_cast<s32>(Common::BitSize<u64>()));
@@ -140,7 +140,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
140 UNREACHABLE_MSG("KThread::Initialize: Unknown ThreadType {}", static_cast<u32>(type)); 140 UNREACHABLE_MSG("KThread::Initialize: Unknown ThreadType {}", static_cast<u32>(type));
141 break; 141 break;
142 } 142 }
143 thread_type_for_debugging = type; 143 thread_type = type;
144 144
145 // Set the ideal core ID and affinity mask. 145 // Set the ideal core ID and affinity mask.
146 virtual_ideal_core_id = virt_core; 146 virtual_ideal_core_id = virt_core;
@@ -262,7 +262,7 @@ ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uint
262} 262}
263 263
264ResultCode KThread::InitializeDummyThread(KThread* thread) { 264ResultCode KThread::InitializeDummyThread(KThread* thread) {
265 return thread->Initialize({}, {}, {}, DefaultThreadPriority, 3, {}, ThreadType::Dummy); 265 return thread->Initialize({}, {}, {}, DummyThreadPriority, 3, {}, ThreadType::Dummy);
266} 266}
267 267
268ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { 268ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) {
@@ -1075,12 +1075,46 @@ ResultCode KThread::Sleep(s64 timeout) {
1075 return ResultSuccess; 1075 return ResultSuccess;
1076} 1076}
1077 1077
1078void KThread::IfDummyThreadTryWait() {
1079 if (!IsDummyThread()) {
1080 return;
1081 }
1082
1083 if (GetState() != ThreadState::Waiting) {
1084 return;
1085 }
1086
1087 // Block until we can grab the lock.
1088 KScopedSpinLock lk{dummy_wait_lock};
1089}
1090
1091void KThread::IfDummyThreadBeginWait() {
1092 if (!IsDummyThread()) {
1093 return;
1094 }
1095
1096 // Ensure the thread will block when IfDummyThreadTryWait is called.
1097 dummy_wait_lock.Lock();
1098}
1099
1100void KThread::IfDummyThreadEndWait() {
1101 if (!IsDummyThread()) {
1102 return;
1103 }
1104
1105 // Ensure the thread will no longer block.
1106 dummy_wait_lock.Unlock();
1107}
1108
1078void KThread::BeginWait(KThreadQueue* queue) { 1109void KThread::BeginWait(KThreadQueue* queue) {
1079 // Set our state as waiting. 1110 // Set our state as waiting.
1080 SetState(ThreadState::Waiting); 1111 SetState(ThreadState::Waiting);
1081 1112
1082 // Set our wait queue. 1113 // Set our wait queue.
1083 wait_queue = queue; 1114 wait_queue = queue;
1115
1116 // Special case for dummy threads to ensure they block.
1117 IfDummyThreadBeginWait();
1084} 1118}
1085 1119
1086void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) { 1120void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) {
@@ -1099,7 +1133,16 @@ void KThread::EndWait(ResultCode wait_result_) {
1099 1133
1100 // If we're waiting, notify our queue that we're available. 1134 // If we're waiting, notify our queue that we're available.
1101 if (GetState() == ThreadState::Waiting) { 1135 if (GetState() == ThreadState::Waiting) {
1136 if (wait_queue == nullptr) {
1137 // This should never happen, but avoid a hard crash below to get this logged.
1138 ASSERT_MSG(false, "wait_queue is nullptr!");
1139 return;
1140 }
1141
1102 wait_queue->EndWait(this, wait_result_); 1142 wait_queue->EndWait(this, wait_result_);
1143
1144 // Special case for dummy threads to wakeup if necessary.
1145 IfDummyThreadEndWait();
1103 } 1146 }
1104} 1147}
1105 1148
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index cc427f6cf..d058db62c 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -112,6 +112,7 @@ private:
112public: 112public:
113 static constexpr s32 DefaultThreadPriority = 44; 113 static constexpr s32 DefaultThreadPriority = 44;
114 static constexpr s32 IdleThreadPriority = Svc::LowestThreadPriority + 1; 114 static constexpr s32 IdleThreadPriority = Svc::LowestThreadPriority + 1;
115 static constexpr s32 DummyThreadPriority = Svc::LowestThreadPriority + 2;
115 116
116 explicit KThread(KernelCore& kernel_); 117 explicit KThread(KernelCore& kernel_);
117 ~KThread() override; 118 ~KThread() override;
@@ -553,8 +554,12 @@ public:
553 return wait_reason_for_debugging; 554 return wait_reason_for_debugging;
554 } 555 }
555 556
556 [[nodiscard]] ThreadType GetThreadTypeForDebugging() const { 557 [[nodiscard]] ThreadType GetThreadType() const {
557 return thread_type_for_debugging; 558 return thread_type;
559 }
560
561 [[nodiscard]] bool IsDummyThread() const {
562 return GetThreadType() == ThreadType::Dummy;
558 } 563 }
559 564
560 void SetWaitObjectsForDebugging(const std::span<KSynchronizationObject*>& objects) { 565 void SetWaitObjectsForDebugging(const std::span<KSynchronizationObject*>& objects) {
@@ -631,6 +636,14 @@ public:
631 return condvar_key; 636 return condvar_key;
632 } 637 }
633 638
639 // Dummy threads (used for HLE host threads) cannot wait based on the guest scheduler, and
640 // therefore will not block on guest kernel synchronization primitives. These methods handle
641 // blocking as needed.
642
643 void IfDummyThreadTryWait();
644 void IfDummyThreadBeginWait();
645 void IfDummyThreadEndWait();
646
634private: 647private:
635 static constexpr size_t PriorityInheritanceCountMax = 10; 648 static constexpr size_t PriorityInheritanceCountMax = 10;
636 union SyncObjectBuffer { 649 union SyncObjectBuffer {
@@ -749,16 +762,17 @@ private:
749 bool resource_limit_release_hint{}; 762 bool resource_limit_release_hint{};
750 StackParameters stack_parameters{}; 763 StackParameters stack_parameters{};
751 KSpinLock context_guard{}; 764 KSpinLock context_guard{};
765 KSpinLock dummy_wait_lock{};
752 766
753 // For emulation 767 // For emulation
754 std::shared_ptr<Common::Fiber> host_context{}; 768 std::shared_ptr<Common::Fiber> host_context{};
755 bool is_single_core{}; 769 bool is_single_core{};
770 ThreadType thread_type{};
756 771
757 // For debugging 772 // For debugging
758 std::vector<KSynchronizationObject*> wait_objects_for_debugging; 773 std::vector<KSynchronizationObject*> wait_objects_for_debugging;
759 VAddr mutex_wait_address_for_debugging{}; 774 VAddr mutex_wait_address_for_debugging{};
760 ThreadWaitReasonForDebugging wait_reason_for_debugging{}; 775 ThreadWaitReasonForDebugging wait_reason_for_debugging{};
761 ThreadType thread_type_for_debugging{};
762 776
763public: 777public:
764 using ConditionVariableThreadTreeType = ConditionVariableThreadTree; 778 using ConditionVariableThreadTreeType = ConditionVariableThreadTree;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 887c1fd27..49c0714ed 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -301,12 +301,10 @@ struct KernelCore::Impl {
301 // Gets the dummy KThread for the caller, allocating a new one if this is the first time 301 // Gets the dummy KThread for the caller, allocating a new one if this is the first time
302 KThread* GetHostDummyThread() { 302 KThread* GetHostDummyThread() {
303 auto make_thread = [this]() { 303 auto make_thread = [this]() {
304 std::lock_guard lk(dummy_thread_lock); 304 KThread* thread = KThread::Create(system.Kernel());
305 auto& thread = dummy_threads.emplace_back(std::make_unique<KThread>(system.Kernel())); 305 ASSERT(KThread::InitializeDummyThread(thread).IsSuccess());
306 KAutoObject::Create(thread.get());
307 ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess());
308 thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); 306 thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
309 return thread.get(); 307 return thread;
310 }; 308 };
311 309
312 thread_local KThread* saved_thread = make_thread(); 310 thread_local KThread* saved_thread = make_thread();
@@ -731,7 +729,6 @@ struct KernelCore::Impl {
731 std::mutex server_sessions_lock; 729 std::mutex server_sessions_lock;
732 std::mutex registered_objects_lock; 730 std::mutex registered_objects_lock;
733 std::mutex registered_in_use_objects_lock; 731 std::mutex registered_in_use_objects_lock;
734 std::mutex dummy_thread_lock;
735 732
736 std::atomic<u32> next_object_id{0}; 733 std::atomic<u32> next_object_id{0};
737 std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin}; 734 std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin};
@@ -788,9 +785,6 @@ struct KernelCore::Impl {
788 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; 785 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
789 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; 786 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
790 787
791 // Specifically tracked to be automatically destroyed with kernel
792 std::vector<std::unique_ptr<KThread>> dummy_threads;
793
794 bool is_multicore{}; 788 bool is_multicore{};
795 std::atomic_bool is_shutting_down{}; 789 std::atomic_bool is_shutting_down{};
796 bool is_phantom_mode_for_singlecore{}; 790 bool is_phantom_mode_for_singlecore{};
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp
index 03f3dec10..4eb3a5988 100644
--- a/src/core/hle/kernel/service_thread.cpp
+++ b/src/core/hle/kernel/service_thread.cpp
@@ -12,6 +12,7 @@
12#include "common/scope_exit.h" 12#include "common/scope_exit.h"
13#include "common/thread.h" 13#include "common/thread.h"
14#include "core/hle/kernel/k_session.h" 14#include "core/hle/kernel/k_session.h"
15#include "core/hle/kernel/k_thread.h"
15#include "core/hle/kernel/kernel.h" 16#include "core/hle/kernel/kernel.h"
16#include "core/hle/kernel/service_thread.h" 17#include "core/hle/kernel/service_thread.h"
17 18
@@ -50,6 +51,10 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std
50 51
51 kernel.RegisterHostThread(); 52 kernel.RegisterHostThread();
52 53
54 // Ensure the dummy thread allocated for this host thread is closed on exit.
55 auto* dummy_thread = kernel.GetCurrentEmuThread();
56 SCOPE_EXIT({ dummy_thread->Close(); });
57
53 while (true) { 58 while (true) {
54 std::function<void()> task; 59 std::function<void()> task;
55 60
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 1f41c46c4..2d1a2d9cb 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -95,7 +95,7 @@ std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList(
95 std::size_t row = 0; 95 std::size_t row = 0;
96 auto add_threads = [&](const std::vector<Kernel::KThread*>& threads) { 96 auto add_threads = [&](const std::vector<Kernel::KThread*>& threads) {
97 for (std::size_t i = 0; i < threads.size(); ++i) { 97 for (std::size_t i = 0; i < threads.size(); ++i) {
98 if (threads[i]->GetThreadTypeForDebugging() == Kernel::ThreadType::User) { 98 if (threads[i]->GetThreadType() == Kernel::ThreadType::User) {
99 item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i], system)); 99 item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i], system));
100 item_list.back()->row = row; 100 item_list.back()->row = row;
101 } 101 }
@@ -153,7 +153,7 @@ QString WaitTreeCallstack::GetText() const {
153std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const { 153std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const {
154 std::vector<std::unique_ptr<WaitTreeItem>> list; 154 std::vector<std::unique_ptr<WaitTreeItem>> list;
155 155
156 if (thread.GetThreadTypeForDebugging() != Kernel::ThreadType::User) { 156 if (thread.GetThreadType() != Kernel::ThreadType::User) {
157 return list; 157 return list;
158 } 158 }
159 159