diff options
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 14 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 5 |
3 files changed, 11 insertions, 13 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b8b69f9d0..653697843 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -34,14 +34,11 @@ void WaitObject::RemoveWaitingThread(Thread* thread) { | |||
| 34 | 34 | ||
| 35 | SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { | 35 | SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { |
| 36 | // Remove the threads that are ready or already running from our waitlist | 36 | // Remove the threads that are ready or already running from our waitlist |
| 37 | boost::range::remove_erase_if(waiting_threads, [](const SharedPtr<Thread>& thread) -> bool { | 37 | boost::range::remove_erase_if(waiting_threads, [](const SharedPtr<Thread>& thread) { |
| 38 | return thread->status == THREADSTATUS_RUNNING || thread->status == THREADSTATUS_READY; | 38 | return thread->status == THREADSTATUS_RUNNING || thread->status == THREADSTATUS_READY; |
| 39 | }); | 39 | }); |
| 40 | 40 | ||
| 41 | if (waiting_threads.empty()) | 41 | Thread* candidate = nullptr; |
| 42 | return nullptr; | ||
| 43 | |||
| 44 | SharedPtr<Thread> candidate = nullptr; | ||
| 45 | s32 candidate_priority = THREADPRIO_LOWEST + 1; | 42 | s32 candidate_priority = THREADPRIO_LOWEST + 1; |
| 46 | 43 | ||
| 47 | for (const auto& thread : waiting_threads) { | 44 | for (const auto& thread : waiting_threads) { |
| @@ -52,7 +49,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { | |||
| 52 | return object->ShouldWait(); | 49 | return object->ShouldWait(); |
| 53 | }); | 50 | }); |
| 54 | if (ready_to_run) { | 51 | if (ready_to_run) { |
| 55 | candidate = thread; | 52 | candidate = thread.get(); |
| 56 | candidate_priority = thread->current_priority; | 53 | candidate_priority = thread->current_priority; |
| 57 | } | 54 | } |
| 58 | } | 55 | } |
| @@ -61,9 +58,8 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { | |||
| 61 | } | 58 | } |
| 62 | 59 | ||
| 63 | void WaitObject::WakeupAllWaitingThreads() { | 60 | void WaitObject::WakeupAllWaitingThreads() { |
| 64 | // Wake up all threads that can be awoken, in priority order | ||
| 65 | while (auto thread = GetHighestPriorityReadyThread()) { | 61 | while (auto thread = GetHighestPriorityReadyThread()) { |
| 66 | if (thread->wait_objects.empty()) { | 62 | if (!thread->IsSleepingOnWaitAll()) { |
| 67 | Acquire(); | 63 | Acquire(); |
| 68 | // Set the output index of the WaitSynchronizationN call to the index of this object. | 64 | // Set the output index of the WaitSynchronizationN call to the index of this object. |
| 69 | if (thread->wait_set_output) { | 65 | if (thread->wait_set_output) { |
| @@ -73,7 +69,6 @@ void WaitObject::WakeupAllWaitingThreads() { | |||
| 73 | } else { | 69 | } else { |
| 74 | for (auto object : thread->wait_objects) { | 70 | for (auto object : thread->wait_objects) { |
| 75 | object->Acquire(); | 71 | object->Acquire(); |
| 76 | // Remove the thread from the object's waitlist | ||
| 77 | object->RemoveWaitingThread(thread.get()); | 72 | object->RemoveWaitingThread(thread.get()); |
| 78 | } | 73 | } |
| 79 | // Note: This case doesn't update the output index of WaitSynchronizationN. | 74 | // Note: This case doesn't update the output index of WaitSynchronizationN. |
| @@ -81,7 +76,6 @@ void WaitObject::WakeupAllWaitingThreads() { | |||
| 81 | thread->wait_objects.clear(); | 76 | thread->wait_objects.clear(); |
| 82 | } | 77 | } |
| 83 | 78 | ||
| 84 | // Set the result of the call to WaitSynchronization to RESULT_SUCCESS | ||
| 85 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | 79 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); |
| 86 | thread->ResumeFromWait(); | 80 | thread->ResumeFromWait(); |
| 87 | // Note: Removing the thread from the object's waitlist will be done by GetHighestPriorityReadyThread | 81 | // Note: Removing the thread from the object's waitlist will be done by GetHighestPriorityReadyThread |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index eb5a3bf7e..4227d2373 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -152,7 +152,10 @@ public: | |||
| 152 | */ | 152 | */ |
| 153 | void RemoveWaitingThread(Thread* thread); | 153 | void RemoveWaitingThread(Thread* thread); |
| 154 | 154 | ||
| 155 | /// Wake up all threads waiting on this object | 155 | /** |
| 156 | * Wake up all threads waiting on this object that can be awoken, in priority order, | ||
| 157 | * and set the synchronization result and output of the thread. | ||
| 158 | */ | ||
| 156 | void WakeupAllWaitingThreads(); | 159 | void WakeupAllWaitingThreads(); |
| 157 | 160 | ||
| 158 | /// Obtains the highest priority thread that is ready to run from this object's waiting list. | 161 | /// Obtains the highest priority thread that is ready to run from this object's waiting list. |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 1b29fb3a3..4c254cb9d 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include <unordered_map> | 8 | #include <unordered_map> |
| 9 | #include <vector> | 9 | #include <vector> |
| 10 | #include <boost/container/flat_map.hpp> | ||
| 10 | #include <boost/container/flat_set.hpp> | 11 | #include <boost/container/flat_set.hpp> |
| 11 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 12 | #include "core/core.h" | 13 | #include "core/core.h" |
| @@ -153,7 +154,7 @@ public: | |||
| 153 | * its wait list to become ready, as a result of a WaitSynchronizationN call | 154 | * its wait list to become ready, as a result of a WaitSynchronizationN call |
| 154 | * with wait_all = true, or a ReplyAndReceive call. | 155 | * with wait_all = true, or a ReplyAndReceive call. |
| 155 | */ | 156 | */ |
| 156 | bool IsWaitingAll() const { | 157 | bool IsSleepingOnWaitAll() const { |
| 157 | return !wait_objects.empty(); | 158 | return !wait_objects.empty(); |
| 158 | } | 159 | } |
| 159 | 160 | ||
| @@ -183,7 +184,7 @@ public: | |||
| 183 | /// This is only populated when the thread should wait for all the objects to become ready. | 184 | /// This is only populated when the thread should wait for all the objects to become ready. |
| 184 | std::vector<SharedPtr<WaitObject>> wait_objects; | 185 | std::vector<SharedPtr<WaitObject>> wait_objects; |
| 185 | 186 | ||
| 186 | std::unordered_map<int, s32> wait_objects_index; ///< Mapping of Object ids to their position in the last waitlist that this object waited on. | 187 | boost::container::flat_map<int, s32> wait_objects_index; ///< Mapping of Object ids to their position in the last waitlist that this object waited on. |
| 187 | 188 | ||
| 188 | VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address | 189 | VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address |
| 189 | 190 | ||