diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 28 | ||||
| -rw-r--r-- | src/core/hle/kernel/wait_object.cpp | 29 | ||||
| -rw-r--r-- | src/yuzu/debugger/wait_tree.cpp | 11 |
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 |
| 425 | static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread, | 425 | static 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 | ||
| 145 | void Thread::CancelWait() { | 144 | void 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() { | |||
| 68 | void WaitObject::WakeupWaitingThread(SharedPtr<Thread> thread) { | 67 | void 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 | ||
| 100 | void WaitObject::WakeupAllWaitingThreads() { | 101 | void 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)); |