summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Lioncash2019-04-17 07:21:19 -0400
committerGravatar Lioncash2019-04-17 09:30:56 -0400
commitc268ffd831bc8771585934e7e24da0f7e150936e (patch)
treeee35a6da18561f3b3d7a43a37081f7f175e62314 /src
parentkernel/svc: Migrate svcCancelSynchronization behavior to a thread function (diff)
downloadyuzu-c268ffd831bc8771585934e7e24da0f7e150936e.tar.gz
yuzu-c268ffd831bc8771585934e7e24da0f7e150936e.tar.xz
yuzu-c268ffd831bc8771585934e7e24da0f7e150936e.zip
kernel/thread: Unify wait synchronization types
This is a holdover from Citra, where the 3DS has both WaitSynchronization1 and WaitSynchronizationN. The switch only has one form of wait synchronizing (literally WaitSynchonization). This allows us to throw out code that doesn't apply at all to the Switch kernel. Because of this unnecessary dichotomy within the wait synchronization utilities, we were also neglecting to properly handle waiting on multiple objects. While we're at it, we can also scrub out any lingering references to WaitSynchronization1/WaitSynchronizationN in comments, and change them to WaitSynchronization (or remove them if the mention no longer applies).
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/kernel.cpp3
-rw-r--r--src/core/hle/kernel/process.cpp3
-rw-r--r--src/core/hle/kernel/svc.cpp4
-rw-r--r--src/core/hle/kernel/thread.cpp5
-rw-r--r--src/core/hle/kernel/thread.h28
-rw-r--r--src/core/hle/kernel/wait_object.cpp29
-rw-r--r--src/yuzu/debugger/wait_tree.cpp11
7 files changed, 38 insertions, 45 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 4d58e7c69..a38ee117b 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -46,8 +46,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
46 46
47 bool resume = true; 47 bool resume = true;
48 48
49 if (thread->GetStatus() == ThreadStatus::WaitSynchAny || 49 if (thread->GetStatus() == ThreadStatus::WaitSynch ||
50 thread->GetStatus() == ThreadStatus::WaitSynchAll ||
51 thread->GetStatus() == ThreadStatus::WaitHLEEvent) { 50 thread->GetStatus() == ThreadStatus::WaitHLEEvent) {
52 // Remove the thread from each of its waiting objects' waitlists 51 // Remove the thread from each of its waiting objects' waitlists
53 for (const auto& object : thread->GetWaitObjects()) { 52 for (const auto& object : thread->GetWaitObjects()) {
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 4e94048da..0ace3d21c 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -150,8 +150,7 @@ void Process::PrepareForTermination() {
150 continue; 150 continue;
151 151
152 // TODO(Subv): When are the other running/ready threads terminated? 152 // TODO(Subv): When are the other running/ready threads terminated?
153 ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynchAny || 153 ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynch,
154 thread->GetStatus() == ThreadStatus::WaitSynchAll,
155 "Exiting processes with non-waiting threads is currently unimplemented"); 154 "Exiting processes with non-waiting threads is currently unimplemented");
156 155
157 thread->Stop(); 156 thread->Stop();
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index b25190882..ea3fdc315 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -424,7 +424,7 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han
424/// Default thread wakeup callback for WaitSynchronization 424/// Default thread wakeup callback for WaitSynchronization
425static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread, 425static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread,
426 SharedPtr<WaitObject> object, std::size_t index) { 426 SharedPtr<WaitObject> object, std::size_t index) {
427 ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny); 427 ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch);
428 428
429 if (reason == ThreadWakeupReason::Timeout) { 429 if (reason == ThreadWakeupReason::Timeout) {
430 thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); 430 thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
@@ -502,7 +502,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
502 } 502 }
503 503
504 thread->SetWaitObjects(std::move(objects)); 504 thread->SetWaitObjects(std::move(objects));
505 thread->SetStatus(ThreadStatus::WaitSynchAny); 505 thread->SetStatus(ThreadStatus::WaitSynch);
506 506
507 // Create an event to wake the thread up after the specified nanosecond delay has passed 507 // Create an event to wake the thread up after the specified nanosecond delay has passed
508 thread->WakeAfterDelay(nano_seconds); 508 thread->WakeAfterDelay(nano_seconds);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 7d4fe9608..2abf9efca 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -101,8 +101,7 @@ void Thread::ResumeFromWait() {
101 ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects"); 101 ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects");
102 102
103 switch (status) { 103 switch (status) {
104 case ThreadStatus::WaitSynchAll: 104 case ThreadStatus::WaitSynch:
105 case ThreadStatus::WaitSynchAny:
106 case ThreadStatus::WaitHLEEvent: 105 case ThreadStatus::WaitHLEEvent:
107 case ThreadStatus::WaitSleep: 106 case ThreadStatus::WaitSleep:
108 case ThreadStatus::WaitIPC: 107 case ThreadStatus::WaitIPC:
@@ -143,7 +142,7 @@ void Thread::ResumeFromWait() {
143} 142}
144 143
145void Thread::CancelWait() { 144void Thread::CancelWait() {
146 ASSERT(GetStatus() == ThreadStatus::WaitSynchAny); 145 ASSERT(GetStatus() == ThreadStatus::WaitSynch);
147 SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED); 146 SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
148 ResumeFromWait(); 147 ResumeFromWait();
149} 148}
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index e3c457408..62ce7bfda 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -49,8 +49,7 @@ enum class ThreadStatus {
49 WaitHLEEvent, ///< Waiting for hle event to finish 49 WaitHLEEvent, ///< Waiting for hle event to finish
50 WaitSleep, ///< Waiting due to a SleepThread SVC 50 WaitSleep, ///< Waiting due to a SleepThread SVC
51 WaitIPC, ///< Waiting for the reply from an IPC request 51 WaitIPC, ///< Waiting for the reply from an IPC request
52 WaitSynchAny, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false 52 WaitSynch, ///< Waiting due to WaitSynchronization
53 WaitSynchAll, ///< Waiting due to WaitSynchronizationN with wait_all = true
54 WaitMutex, ///< Waiting due to an ArbitrateLock svc 53 WaitMutex, ///< Waiting due to an ArbitrateLock svc
55 WaitCondVar, ///< Waiting due to an WaitProcessWideKey svc 54 WaitCondVar, ///< Waiting due to an WaitProcessWideKey svc
56 WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc 55 WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc
@@ -185,24 +184,27 @@ public:
185 void CancelWakeupTimer(); 184 void CancelWakeupTimer();
186 185
187 /** 186 /**
188 * Sets the result after the thread awakens (from either WaitSynchronization SVC) 187 * Sets the result after the thread awakens (from svcWaitSynchronization)
189 * @param result Value to set to the returned result 188 * @param result Value to set to the returned result
190 */ 189 */
191 void SetWaitSynchronizationResult(ResultCode result); 190 void SetWaitSynchronizationResult(ResultCode result);
192 191
193 /** 192 /**
194 * Sets the output parameter value after the thread awakens (from WaitSynchronizationN SVC only) 193 * Sets the output parameter value after the thread awakens (from svcWaitSynchronization)
195 * @param output Value to set to the output parameter 194 * @param output Value to set to the output parameter
196 */ 195 */
197 void SetWaitSynchronizationOutput(s32 output); 196 void SetWaitSynchronizationOutput(s32 output);
198 197
199 /** 198 /**
200 * Retrieves the index that this particular object occupies in the list of objects 199 * Retrieves the index that this particular object occupies in the list of objects
201 * that the thread passed to WaitSynchronizationN, starting the search from the last element. 200 * that the thread passed to WaitSynchronization, starting the search from the last element.
202 * It is used to set the output value of WaitSynchronizationN when the thread is awakened. 201 *
202 * It is used to set the output index of WaitSynchronization when the thread is awakened.
203 *
203 * When a thread wakes up due to an object signal, the kernel will use the index of the last 204 * When a thread wakes up due to an object signal, the kernel will use the index of the last
204 * matching object in the wait objects list in case of having multiple instances of the same 205 * matching object in the wait objects list in case of having multiple instances of the same
205 * object in the list. 206 * object in the list.
207 *
206 * @param object Object to query the index of. 208 * @param object Object to query the index of.
207 */ 209 */
208 s32 GetWaitObjectIndex(const WaitObject* object) const; 210 s32 GetWaitObjectIndex(const WaitObject* object) const;
@@ -239,13 +241,9 @@ public:
239 */ 241 */
240 VAddr GetCommandBufferAddress() const; 242 VAddr GetCommandBufferAddress() const;
241 243
242 /** 244 /// Returns whether this thread is waiting on objects from a WaitSynchronization call.
243 * Returns whether this thread is waiting for all the objects in 245 bool IsSleepingOnWait() const {
244 * its wait list to become ready, as a result of a WaitSynchronizationN call 246 return status == ThreadStatus::WaitSynch;
245 * with wait_all = true.
246 */
247 bool IsSleepingOnWaitAll() const {
248 return status == ThreadStatus::WaitSynchAll;
249 } 247 }
250 248
251 ThreadContext& GetContext() { 249 ThreadContext& GetContext() {
@@ -423,7 +421,7 @@ private:
423 Process* owner_process; 421 Process* owner_process;
424 422
425 /// Objects that the thread is waiting on, in the same order as they were 423 /// Objects that the thread is waiting on, in the same order as they were
426 /// passed to WaitSynchronization1/N. 424 /// passed to WaitSynchronization.
427 ThreadWaitObjects wait_objects; 425 ThreadWaitObjects wait_objects;
428 426
429 /// List of threads that are waiting for a mutex that is held by this thread. 427 /// List of threads that are waiting for a mutex that is held by this thread.
@@ -449,7 +447,7 @@ private:
449 Handle callback_handle = 0; 447 Handle callback_handle = 0;
450 448
451 /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread 449 /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
452 /// was waiting via WaitSynchronizationN then the object will be the last object that became 450 /// was waiting via WaitSynchronization then the object will be the last object that became
453 /// available. In case of a timeout, the object will be nullptr. 451 /// available. In case of a timeout, the object will be nullptr.
454 WakeupCallback wakeup_callback; 452 WakeupCallback wakeup_callback;
455 453
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index 90580ed93..38d8a6e0c 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -38,8 +38,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
38 const ThreadStatus thread_status = thread->GetStatus(); 38 const ThreadStatus thread_status = thread->GetStatus();
39 39
40 // The list of waiting threads must not contain threads that are not waiting to be awakened. 40 // The list of waiting threads must not contain threads that are not waiting to be awakened.
41 ASSERT_MSG(thread_status == ThreadStatus::WaitSynchAny || 41 ASSERT_MSG(thread_status == ThreadStatus::WaitSynch ||
42 thread_status == ThreadStatus::WaitSynchAll ||
43 thread_status == ThreadStatus::WaitHLEEvent, 42 thread_status == ThreadStatus::WaitHLEEvent,
44 "Inconsistent thread statuses in waiting_threads"); 43 "Inconsistent thread statuses in waiting_threads");
45 44
@@ -49,10 +48,10 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
49 if (ShouldWait(thread.get())) 48 if (ShouldWait(thread.get()))
50 continue; 49 continue;
51 50
52 // A thread is ready to run if it's either in ThreadStatus::WaitSynchAny or 51 // A thread is ready to run if it's either in ThreadStatus::WaitSynch
53 // in ThreadStatus::WaitSynchAll and the rest of the objects it is waiting on are ready. 52 // and the rest of the objects it is waiting on are ready.
54 bool ready_to_run = true; 53 bool ready_to_run = true;
55 if (thread_status == ThreadStatus::WaitSynchAll) { 54 if (thread_status == ThreadStatus::WaitSynch) {
56 ready_to_run = thread->AllWaitObjectsReady(); 55 ready_to_run = thread->AllWaitObjectsReady();
57 } 56 }
58 57
@@ -68,33 +67,35 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
68void WaitObject::WakeupWaitingThread(SharedPtr<Thread> thread) { 67void WaitObject::WakeupWaitingThread(SharedPtr<Thread> thread) {
69 ASSERT(!ShouldWait(thread.get())); 68 ASSERT(!ShouldWait(thread.get()));
70 69
71 if (!thread) 70 if (!thread) {
72 return; 71 return;
72 }
73 73
74 if (!thread->IsSleepingOnWaitAll()) { 74 if (thread->IsSleepingOnWait()) {
75 Acquire(thread.get());
76 } else {
77 for (const auto& object : thread->GetWaitObjects()) { 75 for (const auto& object : thread->GetWaitObjects()) {
78 ASSERT(!object->ShouldWait(thread.get())); 76 ASSERT(!object->ShouldWait(thread.get()));
79 object->Acquire(thread.get()); 77 object->Acquire(thread.get());
80 } 78 }
79 } else {
80 Acquire(thread.get());
81 } 81 }
82 82
83 const std::size_t index = thread->GetWaitObjectIndex(this); 83 const std::size_t index = thread->GetWaitObjectIndex(this);
84 84
85 for (const auto& object : thread->GetWaitObjects()) 85 for (const auto& object : thread->GetWaitObjects()) {
86 object->RemoveWaitingThread(thread.get()); 86 object->RemoveWaitingThread(thread.get());
87 }
87 thread->ClearWaitObjects(); 88 thread->ClearWaitObjects();
88 89
89 thread->CancelWakeupTimer(); 90 thread->CancelWakeupTimer();
90 91
91 bool resume = true; 92 bool resume = true;
92 93 if (thread->HasWakeupCallback()) {
93 if (thread->HasWakeupCallback())
94 resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Signal, thread, this, index); 94 resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Signal, thread, this, index);
95 95 }
96 if (resume) 96 if (resume) {
97 thread->ResumeFromWait(); 97 thread->ResumeFromWait();
98 }
98} 99}
99 100
100void WaitObject::WakeupAllWaitingThreads() { 101void WaitObject::WakeupAllWaitingThreads() {
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 593bb681f..85b095688 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -227,8 +227,7 @@ QString WaitTreeThread::GetText() const {
227 case Kernel::ThreadStatus::WaitIPC: 227 case Kernel::ThreadStatus::WaitIPC:
228 status = tr("waiting for IPC reply"); 228 status = tr("waiting for IPC reply");
229 break; 229 break;
230 case Kernel::ThreadStatus::WaitSynchAll: 230 case Kernel::ThreadStatus::WaitSynch:
231 case Kernel::ThreadStatus::WaitSynchAny:
232 status = tr("waiting for objects"); 231 status = tr("waiting for objects");
233 break; 232 break;
234 case Kernel::ThreadStatus::WaitMutex: 233 case Kernel::ThreadStatus::WaitMutex:
@@ -269,8 +268,7 @@ QColor WaitTreeThread::GetColor() const {
269 return QColor(Qt::GlobalColor::darkRed); 268 return QColor(Qt::GlobalColor::darkRed);
270 case Kernel::ThreadStatus::WaitSleep: 269 case Kernel::ThreadStatus::WaitSleep:
271 return QColor(Qt::GlobalColor::darkYellow); 270 return QColor(Qt::GlobalColor::darkYellow);
272 case Kernel::ThreadStatus::WaitSynchAll: 271 case Kernel::ThreadStatus::WaitSynch:
273 case Kernel::ThreadStatus::WaitSynchAny:
274 case Kernel::ThreadStatus::WaitMutex: 272 case Kernel::ThreadStatus::WaitMutex:
275 case Kernel::ThreadStatus::WaitCondVar: 273 case Kernel::ThreadStatus::WaitCondVar:
276 case Kernel::ThreadStatus::WaitArb: 274 case Kernel::ThreadStatus::WaitArb:
@@ -325,10 +323,9 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
325 list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex"))); 323 list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex")));
326 } 324 }
327 325
328 if (thread.GetStatus() == Kernel::ThreadStatus::WaitSynchAny || 326 if (thread.GetStatus() == Kernel::ThreadStatus::WaitSynch) {
329 thread.GetStatus() == Kernel::ThreadStatus::WaitSynchAll) {
330 list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetWaitObjects(), 327 list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetWaitObjects(),
331 thread.IsSleepingOnWaitAll())); 328 thread.IsSleepingOnWait()));
332 } 329 }
333 330
334 list.push_back(std::make_unique<WaitTreeCallstack>(thread)); 331 list.push_back(std::make_unique<WaitTreeCallstack>(thread));