summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2018-04-20 15:52:06 -0500
committerGravatar Subv2018-04-20 21:04:34 -0500
commit013778aa21bad3769b739d14843b8ef2bb3185c9 (patch)
tree4d338fcd6a19a4d0c3d4f0d604c3dd82c3111557 /src
parentKernel: Remove unused ConditionVariable class. (diff)
downloadyuzu-013778aa21bad3769b739d14843b8ef2bb3185c9.tar.gz
yuzu-013778aa21bad3769b739d14843b8ef2bb3185c9.tar.xz
yuzu-013778aa21bad3769b739d14843b8ef2bb3185c9.zip
Qt: Update the WaitTree widget to show info about the current mutex of each thread.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp6
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h6
-rw-r--r--src/yuzu/debugger/wait_tree.cpp86
-rw-r--r--src/yuzu/debugger/wait_tree.h43
5 files changed, 55 insertions, 90 deletions
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 053bf4e17..402ae900f 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -18,12 +18,10 @@ using Handle = u32;
18enum class HandleType : u32 { 18enum class HandleType : u32 {
19 Unknown, 19 Unknown,
20 Event, 20 Event,
21 Mutex,
22 SharedMemory, 21 SharedMemory,
23 Thread, 22 Thread,
24 Process, 23 Process,
25 AddressArbiter, 24 AddressArbiter,
26 ConditionVariable,
27 Timer, 25 Timer,
28 ResourceLimit, 26 ResourceLimit,
29 CodeSet, 27 CodeSet,
@@ -63,9 +61,7 @@ public:
63 bool IsWaitable() const { 61 bool IsWaitable() const {
64 switch (GetHandleType()) { 62 switch (GetHandleType()) {
65 case HandleType::Event: 63 case HandleType::Event:
66 case HandleType::Mutex:
67 case HandleType::Thread: 64 case HandleType::Thread:
68 case HandleType::ConditionVariable:
69 case HandleType::Timer: 65 case HandleType::Timer:
70 case HandleType::ServerPort: 66 case HandleType::ServerPort:
71 case HandleType::ServerSession: 67 case HandleType::ServerSession:
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 03a4fed59..e4ff2e267 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -9,7 +9,8 @@
9#include "core/core_timing.h" 9#include "core/core_timing.h"
10#include "core/hle/service/nvflinger/buffer_queue.h" 10#include "core/hle/service/nvflinger/buffer_queue.h"
11 11
12namespace Service::NVFlinger { 12namespace Service {
13namespace NVFlinger {
13 14
14BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { 15BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
15 native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle"); 16 native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle");
@@ -110,4 +111,5 @@ void BufferQueue::SetBufferWaitEvent(Kernel::SharedPtr<Kernel::Event>&& wait_eve
110 buffer_wait_event = std::move(wait_event); 111 buffer_wait_event = std::move(wait_event);
111} 112}
112 113
113} // namespace Service::NVFlinger 114} // namespace NVFlinger
115} // namespace Service
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index 95adc4706..1de5767cb 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -13,7 +13,8 @@ namespace CoreTiming {
13struct EventType; 13struct EventType;
14} 14}
15 15
16namespace Service::NVFlinger { 16namespace Service {
17namespace NVFlinger {
17 18
18struct IGBPBuffer { 19struct IGBPBuffer {
19 u32_le magic; 20 u32_le magic;
@@ -97,4 +98,5 @@ private:
97 Kernel::SharedPtr<Kernel::Event> buffer_wait_event; 98 Kernel::SharedPtr<Kernel::Event> buffer_wait_event;
98}; 99};
99 100
100} // namespace Service::NVFlinger 101} // namespace NVFlinger
102} // namespace Service
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index cae2864e5..acc4c2e0b 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -6,8 +6,8 @@
6#include "yuzu/util/util.h" 6#include "yuzu/util/util.h"
7 7
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/kernel/condition_variable.h"
10#include "core/hle/kernel/event.h" 9#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/handle_table.h"
11#include "core/hle/kernel/mutex.h" 11#include "core/hle/kernel/mutex.h"
12#include "core/hle/kernel/thread.h" 12#include "core/hle/kernel/thread.h"
13#include "core/hle/kernel/timer.h" 13#include "core/hle/kernel/timer.h"
@@ -67,6 +67,29 @@ QString WaitTreeText::GetText() const {
67 return text; 67 return text;
68} 68}
69 69
70WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address) : mutex_address(mutex_address) {
71 mutex_value = Memory::Read32(mutex_address);
72 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Mutex::MutexOwnerMask);
73 owner = Kernel::g_handle_table.Get<Kernel::Thread>(owner_handle);
74}
75
76QString WaitTreeMutexInfo::GetText() const {
77 return tr("waiting for mutex 0x%1").arg(mutex_address, 16, 16, QLatin1Char('0'));
78}
79
80std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() const {
81 std::vector<std::unique_ptr<WaitTreeItem>> list;
82
83 bool has_waiters = (mutex_value & Kernel::Mutex::MutexHasWaitersFlag) != 0;
84
85 list.push_back(std::make_unique<WaitTreeText>(tr("has waiters: %1").arg(has_waiters)));
86 list.push_back(std::make_unique<WaitTreeText>(
87 tr("owner handle: 0x%1").arg(owner_handle, 8, 16, QLatin1Char('0'))));
88 if (owner != nullptr)
89 list.push_back(std::make_unique<WaitTreeThread>(*owner));
90 return list;
91}
92
70WaitTreeWaitObject::WaitTreeWaitObject(const Kernel::WaitObject& o) : object(o) {} 93WaitTreeWaitObject::WaitTreeWaitObject(const Kernel::WaitObject& o) : object(o) {}
71 94
72bool WaitTreeExpandableItem::IsExpandable() const { 95bool WaitTreeExpandableItem::IsExpandable() const {
@@ -84,11 +107,6 @@ std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitO
84 switch (object.GetHandleType()) { 107 switch (object.GetHandleType()) {
85 case Kernel::HandleType::Event: 108 case Kernel::HandleType::Event:
86 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::Event&>(object)); 109 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::Event&>(object));
87 case Kernel::HandleType::Mutex:
88 return std::make_unique<WaitTreeMutex>(static_cast<const Kernel::Mutex&>(object));
89 case Kernel::HandleType::ConditionVariable:
90 return std::make_unique<WaitTreeConditionVariable>(
91 static_cast<const Kernel::ConditionVariable&>(object));
92 case Kernel::HandleType::Timer: 110 case Kernel::HandleType::Timer:
93 return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object)); 111 return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object));
94 case Kernel::HandleType::Thread: 112 case Kernel::HandleType::Thread:
@@ -160,6 +178,9 @@ QString WaitTreeThread::GetText() const {
160 case THREADSTATUS_WAIT_SYNCH_ANY: 178 case THREADSTATUS_WAIT_SYNCH_ANY:
161 status = tr("waiting for objects"); 179 status = tr("waiting for objects");
162 break; 180 break;
181 case THREADSTATUS_WAIT_MUTEX:
182 status = tr("waiting for mutex");
183 break;
163 case THREADSTATUS_DORMANT: 184 case THREADSTATUS_DORMANT:
164 status = tr("dormant"); 185 status = tr("dormant");
165 break; 186 break;
@@ -186,6 +207,7 @@ QColor WaitTreeThread::GetColor() const {
186 return QColor(Qt::GlobalColor::darkYellow); 207 return QColor(Qt::GlobalColor::darkYellow);
187 case THREADSTATUS_WAIT_SYNCH_ALL: 208 case THREADSTATUS_WAIT_SYNCH_ALL:
188 case THREADSTATUS_WAIT_SYNCH_ANY: 209 case THREADSTATUS_WAIT_SYNCH_ANY:
210 case THREADSTATUS_WAIT_MUTEX:
189 return QColor(Qt::GlobalColor::red); 211 return QColor(Qt::GlobalColor::red);
190 case THREADSTATUS_DORMANT: 212 case THREADSTATUS_DORMANT:
191 return QColor(Qt::GlobalColor::darkCyan); 213 return QColor(Qt::GlobalColor::darkCyan);
@@ -225,11 +247,11 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
225 list.push_back(std::make_unique<WaitTreeText>( 247 list.push_back(std::make_unique<WaitTreeText>(
226 tr("last running ticks = %1").arg(thread.last_running_ticks))); 248 tr("last running ticks = %1").arg(thread.last_running_ticks)));
227 249
228 if (thread.held_mutexes.empty()) { 250 if (thread.mutex_wait_address != 0)
229 list.push_back(std::make_unique<WaitTreeText>(tr("not holding mutex"))); 251 list.push_back(std::make_unique<WaitTreeMutexInfo>(thread.mutex_wait_address));
230 } else { 252 else
231 list.push_back(std::make_unique<WaitTreeMutexList>(thread.held_mutexes)); 253 list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex")));
232 } 254
233 if (thread.status == THREADSTATUS_WAIT_SYNCH_ANY || 255 if (thread.status == THREADSTATUS_WAIT_SYNCH_ANY ||
234 thread.status == THREADSTATUS_WAIT_SYNCH_ALL) { 256 thread.status == THREADSTATUS_WAIT_SYNCH_ALL) {
235 list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects, 257 list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects,
@@ -250,33 +272,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const {
250 return list; 272 return list;
251} 273}
252 274
253WaitTreeMutex::WaitTreeMutex(const Kernel::Mutex& object) : WaitTreeWaitObject(object) {}
254
255std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutex::GetChildren() const {
256 std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren());
257
258 const auto& mutex = static_cast<const Kernel::Mutex&>(object);
259 if (mutex.GetHasWaiters()) {
260 list.push_back(std::make_unique<WaitTreeText>(tr("locked by thread:")));
261 list.push_back(std::make_unique<WaitTreeThread>(*mutex.GetHoldingThread()));
262 } else {
263 list.push_back(std::make_unique<WaitTreeText>(tr("free")));
264 }
265 return list;
266}
267
268WaitTreeConditionVariable::WaitTreeConditionVariable(const Kernel::ConditionVariable& object)
269 : WaitTreeWaitObject(object) {}
270
271std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeConditionVariable::GetChildren() const {
272 std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren());
273
274 const auto& condition_variable = static_cast<const Kernel::ConditionVariable&>(object);
275 list.push_back(std::make_unique<WaitTreeText>(
276 tr("available count = %1").arg(condition_variable.GetAvailableCount())));
277 return list;
278}
279
280WaitTreeTimer::WaitTreeTimer(const Kernel::Timer& object) : WaitTreeWaitObject(object) {} 275WaitTreeTimer::WaitTreeTimer(const Kernel::Timer& object) : WaitTreeWaitObject(object) {}
281 276
282std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const { 277std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const {
@@ -293,21 +288,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const {
293 return list; 288 return list;
294} 289}
295 290
296WaitTreeMutexList::WaitTreeMutexList(
297 const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list)
298 : mutex_list(list) {}
299
300QString WaitTreeMutexList::GetText() const {
301 return tr("holding mutexes");
302}
303
304std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexList::GetChildren() const {
305 std::vector<std::unique_ptr<WaitTreeItem>> list(mutex_list.size());
306 std::transform(mutex_list.begin(), mutex_list.end(), list.begin(),
307 [](const auto& t) { return std::make_unique<WaitTreeMutex>(*t); });
308 return list;
309}
310
311WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list) 291WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list)
312 : thread_list(list) {} 292 : thread_list(list) {}
313 293
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index e538174eb..300ba9ae4 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -16,8 +16,6 @@ class EmuThread;
16namespace Kernel { 16namespace Kernel {
17class WaitObject; 17class WaitObject;
18class Event; 18class Event;
19class Mutex;
20class ConditionVariable;
21class Thread; 19class Thread;
22class Timer; 20class Timer;
23} // namespace Kernel 21} // namespace Kernel
@@ -61,6 +59,20 @@ public:
61 bool IsExpandable() const override; 59 bool IsExpandable() const override;
62}; 60};
63 61
62class WaitTreeMutexInfo : public WaitTreeExpandableItem {
63 Q_OBJECT
64public:
65 explicit WaitTreeMutexInfo(VAddr mutex_address);
66 QString GetText() const override;
67 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
68
69private:
70 VAddr mutex_address;
71 u32 mutex_value;
72 Kernel::Handle owner_handle;
73 Kernel::SharedPtr<Kernel::Thread> owner;
74};
75
64class WaitTreeWaitObject : public WaitTreeExpandableItem { 76class WaitTreeWaitObject : public WaitTreeExpandableItem {
65 Q_OBJECT 77 Q_OBJECT
66public: 78public:
@@ -104,20 +116,6 @@ public:
104 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; 116 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
105}; 117};
106 118
107class WaitTreeMutex : public WaitTreeWaitObject {
108 Q_OBJECT
109public:
110 explicit WaitTreeMutex(const Kernel::Mutex& object);
111 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
112};
113
114class WaitTreeConditionVariable : public WaitTreeWaitObject {
115 Q_OBJECT
116public:
117 explicit WaitTreeConditionVariable(const Kernel::ConditionVariable& object);
118 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
119};
120
121class WaitTreeTimer : public WaitTreeWaitObject { 119class WaitTreeTimer : public WaitTreeWaitObject {
122 Q_OBJECT 120 Q_OBJECT
123public: 121public:
@@ -125,19 +123,6 @@ public:
125 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; 123 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
126}; 124};
127 125
128class WaitTreeMutexList : public WaitTreeExpandableItem {
129 Q_OBJECT
130public:
131 explicit WaitTreeMutexList(
132 const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list);
133
134 QString GetText() const override;
135 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
136
137private:
138 const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& mutex_list;
139};
140
141class WaitTreeThreadList : public WaitTreeExpandableItem { 126class WaitTreeThreadList : public WaitTreeExpandableItem {
142 Q_OBJECT 127 Q_OBJECT
143public: 128public: