summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-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.cpp10
-rw-r--r--src/core/hle/kernel/thread.cpp9
-rw-r--r--src/core/hle/kernel/thread.h40
-rw-r--r--src/core/hle/kernel/wait_object.cpp29
-rw-r--r--src/yuzu/debugger/wait_tree.cpp11
7 files changed, 54 insertions, 51 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8539fabe4..757e5f21f 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 6d7a7e754..20d01fc88 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -147,8 +147,7 @@ void Process::PrepareForTermination() {
147 continue; 147 continue;
148 148
149 // TODO(Subv): When are the other running/ready threads terminated? 149 // TODO(Subv): When are the other running/ready threads terminated?
150 ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynchAny || 150 ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynch,
151 thread->GetStatus() == ThreadStatus::WaitSynchAll,
152 "Exiting processes with non-waiting threads is currently unimplemented"); 151 "Exiting processes with non-waiting threads is currently unimplemented");
153 152
154 thread->Stop(); 153 thread->Stop();
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 4c763b288..2dcf174c5 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);
@@ -518,16 +518,14 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
518 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); 518 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
519 519
520 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 520 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
521 const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle); 521 SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
522 if (!thread) { 522 if (!thread) {
523 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", 523 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
524 thread_handle); 524 thread_handle);
525 return ERR_INVALID_HANDLE; 525 return ERR_INVALID_HANDLE;
526 } 526 }
527 527
528 ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny); 528 thread->CancelWait();
529 thread->SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
530 thread->ResumeFromWait();
531 return RESULT_SUCCESS; 529 return RESULT_SUCCESS;
532} 530}
533 531
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index ca52267b2..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:
@@ -142,6 +141,12 @@ void Thread::ResumeFromWait() {
142 ChangeScheduler(); 141 ChangeScheduler();
143} 142}
144 143
144void Thread::CancelWait() {
145 ASSERT(GetStatus() == ThreadStatus::WaitSynch);
146 SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
147 ResumeFromWait();
148}
149
145/** 150/**
146 * Resets a thread context, making it ready to be scheduled and run by the CPU 151 * Resets a thread context, making it ready to be scheduled and run by the CPU
147 * @param context Thread context to reset 152 * @param context Thread context to reset
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 411a73b49..f07332f02 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
@@ -169,11 +168,17 @@ public:
169 return tls_memory; 168 return tls_memory;
170 } 169 }
171 170
172 /** 171 /// Resumes a thread from waiting
173 * Resumes a thread from waiting
174 */
175 void ResumeFromWait(); 172 void ResumeFromWait();
176 173
174 /// Cancels a waiting operation that this thread may or may not be within.
175 ///
176 /// When the thread is within a waiting state, this will set the thread's
177 /// waiting result to signal a canceled wait. The function will then resume
178 /// this thread.
179 ///
180 void CancelWait();
181
177 /** 182 /**
178 * Schedules an event to wake up the specified thread after the specified delay 183 * Schedules an event to wake up the specified thread after the specified delay
179 * @param nanoseconds The time this thread will be allowed to sleep for 184 * @param nanoseconds The time this thread will be allowed to sleep for
@@ -184,24 +189,27 @@ public:
184 void CancelWakeupTimer(); 189 void CancelWakeupTimer();
185 190
186 /** 191 /**
187 * Sets the result after the thread awakens (from either WaitSynchronization SVC) 192 * Sets the result after the thread awakens (from svcWaitSynchronization)
188 * @param result Value to set to the returned result 193 * @param result Value to set to the returned result
189 */ 194 */
190 void SetWaitSynchronizationResult(ResultCode result); 195 void SetWaitSynchronizationResult(ResultCode result);
191 196
192 /** 197 /**
193 * Sets the output parameter value after the thread awakens (from WaitSynchronizationN SVC only) 198 * Sets the output parameter value after the thread awakens (from svcWaitSynchronization)
194 * @param output Value to set to the output parameter 199 * @param output Value to set to the output parameter
195 */ 200 */
196 void SetWaitSynchronizationOutput(s32 output); 201 void SetWaitSynchronizationOutput(s32 output);
197 202
198 /** 203 /**
199 * Retrieves the index that this particular object occupies in the list of objects 204 * Retrieves the index that this particular object occupies in the list of objects
200 * that the thread passed to WaitSynchronizationN, starting the search from the last element. 205 * that the thread passed to WaitSynchronization, starting the search from the last element.
201 * It is used to set the output value of WaitSynchronizationN when the thread is awakened. 206 *
207 * It is used to set the output index of WaitSynchronization when the thread is awakened.
208 *
202 * When a thread wakes up due to an object signal, the kernel will use the index of the last 209 * When a thread wakes up due to an object signal, the kernel will use the index of the last
203 * matching object in the wait objects list in case of having multiple instances of the same 210 * matching object in the wait objects list in case of having multiple instances of the same
204 * object in the list. 211 * object in the list.
212 *
205 * @param object Object to query the index of. 213 * @param object Object to query the index of.
206 */ 214 */
207 s32 GetWaitObjectIndex(const WaitObject* object) const; 215 s32 GetWaitObjectIndex(const WaitObject* object) const;
@@ -238,13 +246,9 @@ public:
238 */ 246 */
239 VAddr GetCommandBufferAddress() const; 247 VAddr GetCommandBufferAddress() const;
240 248
241 /** 249 /// Returns whether this thread is waiting on objects from a WaitSynchronization call.
242 * Returns whether this thread is waiting for all the objects in 250 bool IsSleepingOnWait() const {
243 * its wait list to become ready, as a result of a WaitSynchronizationN call 251 return status == ThreadStatus::WaitSynch;
244 * with wait_all = true.
245 */
246 bool IsSleepingOnWaitAll() const {
247 return status == ThreadStatus::WaitSynchAll;
248 } 252 }
249 253
250 ThreadContext& GetContext() { 254 ThreadContext& GetContext() {
@@ -418,7 +422,7 @@ private:
418 Process* owner_process; 422 Process* owner_process;
419 423
420 /// Objects that the thread is waiting on, in the same order as they were 424 /// Objects that the thread is waiting on, in the same order as they were
421 /// passed to WaitSynchronization1/N. 425 /// passed to WaitSynchronization.
422 ThreadWaitObjects wait_objects; 426 ThreadWaitObjects wait_objects;
423 427
424 /// List of threads that are waiting for a mutex that is held by this thread. 428 /// List of threads that are waiting for a mutex that is held by this thread.
@@ -441,7 +445,7 @@ private:
441 Handle callback_handle = 0; 445 Handle callback_handle = 0;
442 446
443 /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread 447 /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
444 /// was waiting via WaitSynchronizationN then the object will be the last object that became 448 /// was waiting via WaitSynchronization then the object will be the last object that became
445 /// available. In case of a timeout, the object will be nullptr. 449 /// available. In case of a timeout, the object will be nullptr.
446 WakeupCallback wakeup_callback; 450 WakeupCallback wakeup_callback;
447 451
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index c8eaf9488..0e96ba872 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() const {
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() const {
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() const {
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));