summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2017-01-04 10:44:38 -0500
committerGravatar Subv2017-01-04 15:58:50 -0500
commitcef5f45de2fd64f0728d4504d0ad7434cb8ac519 (patch)
treea8297434a72bc21d1cec17e3414766ece0ec0054 /src
parentKernel/Mutex: Propagate thread priority changes to other threads inheriting t... (diff)
downloadyuzu-cef5f45de2fd64f0728d4504d0ad7434cb8ac519.tar.gz
yuzu-cef5f45de2fd64f0728d4504d0ad7434cb8ac519.tar.xz
yuzu-cef5f45de2fd64f0728d4504d0ad7434cb8ac519.zip
Kernel: Use different thread statuses when a thread calls WaitSynchronization1 and WaitSynchronizationN with wait_all = true.
This commit removes the overly general THREADSTATUS_WAIT_SYNCH and replaces it with two more granular statuses: THREADSTATUS_WAIT_SYNCH_ANY when a thread waits on objects via WaitSynchronization1 or WaitSynchronizationN with wait_all = false. THREADSTATUS_WAIT_SYNCH_ALL when a thread waits on objects via WaitSynchronizationN with wait_all = true.
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/debugger/wait_tree.cpp9
-rw-r--r--src/core/hle/kernel/thread.cpp11
-rw-r--r--src/core/hle/kernel/thread.h19
-rw-r--r--src/core/hle/svc.cpp6
4 files changed, 26 insertions, 19 deletions
diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp
index 1d2de5185..b6ecf3819 100644
--- a/src/citra_qt/debugger/wait_tree.cpp
+++ b/src/citra_qt/debugger/wait_tree.cpp
@@ -153,7 +153,8 @@ QString WaitTreeThread::GetText() const {
153 case THREADSTATUS_WAIT_SLEEP: 153 case THREADSTATUS_WAIT_SLEEP:
154 status = tr("sleeping"); 154 status = tr("sleeping");
155 break; 155 break;
156 case THREADSTATUS_WAIT_SYNCH: 156 case THREADSTATUS_WAIT_SYNCH_ALL:
157 case THREADSTATUS_WAIT_SYNCH_ANY:
157 status = tr("waiting for objects"); 158 status = tr("waiting for objects");
158 break; 159 break;
159 case THREADSTATUS_DORMANT: 160 case THREADSTATUS_DORMANT:
@@ -180,7 +181,8 @@ QColor WaitTreeThread::GetColor() const {
180 return QColor(Qt::GlobalColor::darkRed); 181 return QColor(Qt::GlobalColor::darkRed);
181 case THREADSTATUS_WAIT_SLEEP: 182 case THREADSTATUS_WAIT_SLEEP:
182 return QColor(Qt::GlobalColor::darkYellow); 183 return QColor(Qt::GlobalColor::darkYellow);
183 case THREADSTATUS_WAIT_SYNCH: 184 case THREADSTATUS_WAIT_SYNCH_ALL:
185 case THREADSTATUS_WAIT_SYNCH_ANY:
184 return QColor(Qt::GlobalColor::red); 186 return QColor(Qt::GlobalColor::red);
185 case THREADSTATUS_DORMANT: 187 case THREADSTATUS_DORMANT:
186 return QColor(Qt::GlobalColor::darkCyan); 188 return QColor(Qt::GlobalColor::darkCyan);
@@ -228,7 +230,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
228 } else { 230 } else {
229 list.push_back(std::make_unique<WaitTreeMutexList>(thread.held_mutexes)); 231 list.push_back(std::make_unique<WaitTreeMutexList>(thread.held_mutexes));
230 } 232 }
231 if (thread.status == THREADSTATUS_WAIT_SYNCH) { 233 if (thread.status == THREADSTATUS_WAIT_SYNCH_ANY ||
234 thread.status == THREADSTATUS_WAIT_SYNCH_ALL) {
232 list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects, 235 list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects,
233 thread.IsSleepingOnWaitAll())); 236 thread.IsSleepingOnWaitAll()));
234 } 237 }
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 3a5a67450..aa99d18c7 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -72,7 +72,8 @@ Thread* GetCurrentThread() {
72 * @return True if the thread is waiting, false otherwise 72 * @return True if the thread is waiting, false otherwise
73 */ 73 */
74static bool CheckWait_WaitObject(const Thread* thread, WaitObject* wait_object) { 74static bool CheckWait_WaitObject(const Thread* thread, WaitObject* wait_object) {
75 if (thread->status != THREADSTATUS_WAIT_SYNCH) 75 if (thread->status != THREADSTATUS_WAIT_SYNCH_ALL &&
76 thread->status != THREADSTATUS_WAIT_SYNCH_ANY)
76 return false; 77 return false;
77 78
78 auto itr = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object); 79 auto itr = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object);
@@ -253,7 +254,7 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa
253 Thread* thread = GetCurrentThread(); 254 Thread* thread = GetCurrentThread();
254 thread->wait_set_output = wait_set_output; 255 thread->wait_set_output = wait_set_output;
255 thread->wait_objects = std::move(wait_objects); 256 thread->wait_objects = std::move(wait_objects);
256 thread->status = THREADSTATUS_WAIT_SYNCH; 257 thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
257} 258}
258 259
259void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { 260void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) {
@@ -281,7 +282,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
281 return; 282 return;
282 } 283 }
283 284
284 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) { 285 if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
286 thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB) {
285 thread->wait_set_output = false; 287 thread->wait_set_output = false;
286 // Remove the thread from each of its waiting objects' waitlists 288 // Remove the thread from each of its waiting objects' waitlists
287 for (auto& object : thread->wait_objects) 289 for (auto& object : thread->wait_objects)
@@ -306,7 +308,8 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
306 308
307void Thread::ResumeFromWait() { 309void Thread::ResumeFromWait() {
308 switch (status) { 310 switch (status) {
309 case THREADSTATUS_WAIT_SYNCH: 311 case THREADSTATUS_WAIT_SYNCH_ALL:
312 case THREADSTATUS_WAIT_SYNCH_ANY:
310 case THREADSTATUS_WAIT_ARB: 313 case THREADSTATUS_WAIT_ARB:
311 case THREADSTATUS_WAIT_SLEEP: 314 case THREADSTATUS_WAIT_SLEEP:
312 break; 315 break;
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index e2f0cc831..6cd8c20e2 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -31,13 +31,14 @@ enum ThreadProcessorId : s32 {
31}; 31};
32 32
33enum ThreadStatus { 33enum ThreadStatus {
34 THREADSTATUS_RUNNING, ///< Currently running 34 THREADSTATUS_RUNNING, ///< Currently running
35 THREADSTATUS_READY, ///< Ready to run 35 THREADSTATUS_READY, ///< Ready to run
36 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter 36 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter
37 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC 37 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC
38 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC 38 THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
39 THREADSTATUS_DORMANT, ///< Created but not yet made ready 39 THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true
40 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated 40 THREADSTATUS_DORMANT, ///< Created but not yet made ready
41 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
41}; 42};
42 43
43namespace Kernel { 44namespace Kernel {
@@ -158,10 +159,10 @@ public:
158 /** 159 /**
159 * Returns whether this thread is waiting for all the objects in 160 * Returns whether this thread is waiting for all the objects in
160 * its wait list to become ready, as a result of a WaitSynchronizationN call 161 * its wait list to become ready, as a result of a WaitSynchronizationN call
161 * with wait_all = true, or a ReplyAndReceive call. 162 * with wait_all = true.
162 */ 163 */
163 bool IsSleepingOnWaitAll() const { 164 bool IsSleepingOnWaitAll() const {
164 return !wait_objects.empty(); 165 return status == THREADSTATUS_WAIT_SYNCH_ALL;
165 } 166 }
166 167
167 ARM_Interface::ThreadContext context; 168 ARM_Interface::ThreadContext context;
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 160f27c98..1e1ca5180 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -278,7 +278,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
278 return ERR_SYNC_TIMEOUT; 278 return ERR_SYNC_TIMEOUT;
279 279
280 object->AddWaitingThread(thread); 280 object->AddWaitingThread(thread);
281 thread->status = THREADSTATUS_WAIT_SYNCH; 281 thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
282 282
283 // Create an event to wake the thread up after the specified nanosecond delay has passed 283 // Create an event to wake the thread up after the specified nanosecond delay has passed
284 thread->WakeAfterDelay(nano_seconds); 284 thread->WakeAfterDelay(nano_seconds);
@@ -351,7 +351,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
351 return ERR_SYNC_TIMEOUT; 351 return ERR_SYNC_TIMEOUT;
352 352
353 // Put the thread to sleep 353 // Put the thread to sleep
354 thread->status = THREADSTATUS_WAIT_SYNCH; 354 thread->status = THREADSTATUS_WAIT_SYNCH_ALL;
355 355
356 // Add the thread to each of the objects' waiting threads. 356 // Add the thread to each of the objects' waiting threads.
357 for (auto& object : objects) { 357 for (auto& object : objects) {
@@ -393,7 +393,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
393 return ERR_SYNC_TIMEOUT; 393 return ERR_SYNC_TIMEOUT;
394 394
395 // Put the thread to sleep 395 // Put the thread to sleep
396 thread->status = THREADSTATUS_WAIT_SYNCH; 396 thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
397 397
398 // Clear the thread's waitlist, we won't use it for wait_all = false 398 // Clear the thread's waitlist, we won't use it for wait_all = false
399 thread->wait_objects.clear(); 399 thread->wait_objects.clear();