diff options
| author | 2017-01-04 11:37:19 -0500 | |
|---|---|---|
| committer | 2017-01-05 09:40:15 -0500 | |
| commit | 7f1dca8cd26fe9be0080efee4e456630960af459 (patch) | |
| tree | 5eae30d01e21d54e529a1074bbc5cbf3cde8ff6a /src/core | |
| parent | Kernel: Remove Thread::wait_objects_index and use wait_objects to hold all th... (diff) | |
| download | yuzu-7f1dca8cd26fe9be0080efee4e456630960af459.tar.gz yuzu-7f1dca8cd26fe9be0080efee4e456630960af459.tar.xz yuzu-7f1dca8cd26fe9be0080efee4e456630960af459.zip | |
Kernel: Remove a thread from all of its waiting objects' waiting_threads list when it is awoken.
This fixes a potential bug where threads would not get removed from said list if they awoke after waiting with WaitSynchronizationN with wait_all = false
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 22 |
1 files changed, 4 insertions, 18 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 955f50a9b..47d4df69c 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -32,19 +32,6 @@ void WaitObject::RemoveWaitingThread(Thread* thread) { | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { | 34 | SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { |
| 35 | // Remove the threads that are ready or already running from our waitlist | ||
| 36 | auto to_remove = waiting_threads.end(); | ||
| 37 | do { | ||
| 38 | to_remove = std::find_if(waiting_threads.begin(), waiting_threads.end(), | ||
| 39 | [](const SharedPtr<Thread>& thread) { | ||
| 40 | return thread->status == THREADSTATUS_RUNNING || | ||
| 41 | thread->status == THREADSTATUS_READY || | ||
| 42 | thread->status == THREADSTATUS_DEAD; | ||
| 43 | }); | ||
| 44 | // Call RemoveWaitingThread so that child classes can override the behavior. | ||
| 45 | RemoveWaitingThread(to_remove->get()); | ||
| 46 | } while (to_remove != waiting_threads.end()); | ||
| 47 | |||
| 48 | Thread* candidate = nullptr; | 35 | Thread* candidate = nullptr; |
| 49 | s32 candidate_priority = THREADPRIO_LOWEST + 1; | 36 | s32 candidate_priority = THREADPRIO_LOWEST + 1; |
| 50 | 37 | ||
| @@ -86,17 +73,16 @@ void WaitObject::WakeupAllWaitingThreads() { | |||
| 86 | } else { | 73 | } else { |
| 87 | for (auto& object : thread->wait_objects) { | 74 | for (auto& object : thread->wait_objects) { |
| 88 | object->Acquire(thread.get()); | 75 | object->Acquire(thread.get()); |
| 89 | object->RemoveWaitingThread(thread.get()); | ||
| 90 | } | 76 | } |
| 91 | // Note: This case doesn't update the output index of WaitSynchronizationN. | 77 | // Note: This case doesn't update the output index of WaitSynchronizationN. |
| 92 | // Clear the thread's waitlist | ||
| 93 | thread->wait_objects.clear(); | ||
| 94 | } | 78 | } |
| 95 | 79 | ||
| 80 | for (auto& object : thread->wait_objects) | ||
| 81 | object->RemoveWaitingThread(thread.get()); | ||
| 82 | thread->wait_objects.clear(); | ||
| 83 | |||
| 96 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | 84 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); |
| 97 | thread->ResumeFromWait(); | 85 | thread->ResumeFromWait(); |
| 98 | // Note: Removing the thread from the object's waitlist will be | ||
| 99 | // done by GetHighestPriorityReadyThread. | ||
| 100 | } | 86 | } |
| 101 | } | 87 | } |
| 102 | 88 | ||