summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp58
1 files changed, 53 insertions, 5 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 0c8752670..209d35270 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <boost/range/algorithm_ext/erase.hpp>
6#include "common/assert.h" 7#include "common/assert.h"
7#include "common/logging/log.h" 8#include "common/logging/log.h"
8#include "core/hle/config_mem.h" 9#include "core/hle/config_mem.h"
@@ -31,13 +32,60 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
31 waiting_threads.erase(itr); 32 waiting_threads.erase(itr);
32} 33}
33 34
34void WaitObject::WakeupAllWaitingThreads() { 35SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
35 for (auto thread : waiting_threads) 36 // Remove the threads that are ready or already running from our waitlist
36 thread->ResumeFromWait(); 37 boost::range::remove_erase_if(waiting_threads, [](const SharedPtr<Thread>& thread) {
38 return thread->status == THREADSTATUS_RUNNING || thread->status == THREADSTATUS_READY;
39 });
40
41 // TODO(Subv): This call should be performed inside the loop below to check if an object can be
42 // acquired by a particular thread. This is useful for things like recursive locking of Mutexes.
43 if (ShouldWait())
44 return nullptr;
45
46 Thread* candidate = nullptr;
47 s32 candidate_priority = THREADPRIO_LOWEST + 1;
48
49 for (const auto& thread : waiting_threads) {
50 if (thread->current_priority >= candidate_priority)
51 continue;
37 52
38 waiting_threads.clear(); 53 bool ready_to_run =
54 std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
55 [](const SharedPtr<WaitObject>& object) { return object->ShouldWait(); });
56 if (ready_to_run) {
57 candidate = thread.get();
58 candidate_priority = thread->current_priority;
59 }
60 }
61
62 return candidate;
63}
39 64
40 HLE::Reschedule(__func__); 65void WaitObject::WakeupAllWaitingThreads() {
66 while (auto thread = GetHighestPriorityReadyThread()) {
67 if (!thread->IsSleepingOnWaitAll()) {
68 Acquire();
69 // Set the output index of the WaitSynchronizationN call to the index of this object.
70 if (thread->wait_set_output) {
71 thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(this));
72 thread->wait_set_output = false;
73 }
74 } else {
75 for (auto& object : thread->wait_objects) {
76 object->Acquire();
77 object->RemoveWaitingThread(thread.get());
78 }
79 // Note: This case doesn't update the output index of WaitSynchronizationN.
80 // Clear the thread's waitlist
81 thread->wait_objects.clear();
82 }
83
84 thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
85 thread->ResumeFromWait();
86 // Note: Removing the thread from the object's waitlist will be
87 // done by GetHighestPriorityReadyThread.
88 }
41} 89}
42 90
43const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const { 91const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const {