summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/scheduler.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-03-16 00:30:15 -0400
committerGravatar FernandoS272019-03-27 14:34:32 -0400
commitdde0814837866e5c27cd5c97be0461bdca481bc2 (patch)
treecbb05c812d264cff52db48e27dc776caa90c7201 /src/core/hle/kernel/scheduler.cpp
parentAdd MultiLevelQueue Tests (diff)
downloadyuzu-dde0814837866e5c27cd5c97be0461bdca481bc2.tar.gz
yuzu-dde0814837866e5c27cd5c97be0461bdca481bc2.tar.xz
yuzu-dde0814837866e5c27cd5c97be0461bdca481bc2.zip
Use MultiLevelQueue instead of old ThreadQueueList
Diffstat (limited to 'src/core/hle/kernel/scheduler.cpp')
-rw-r--r--src/core/hle/kernel/scheduler.cpp39
1 files changed, 22 insertions, 17 deletions
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index cc189cc64..58217b732 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -30,7 +30,7 @@ Scheduler::~Scheduler() {
30 30
31bool Scheduler::HaveReadyThreads() const { 31bool Scheduler::HaveReadyThreads() const {
32 std::lock_guard<std::mutex> lock(scheduler_mutex); 32 std::lock_guard<std::mutex> lock(scheduler_mutex);
33 return ready_queue.get_first() != nullptr; 33 return !ready_queue.empty();
34} 34}
35 35
36Thread* Scheduler::GetCurrentThread() const { 36Thread* Scheduler::GetCurrentThread() const {
@@ -45,23 +45,27 @@ Thread* Scheduler::PopNextReadyThread() {
45 Thread* next = nullptr; 45 Thread* next = nullptr;
46 Thread* thread = GetCurrentThread(); 46 Thread* thread = GetCurrentThread();
47 47
48
48 if (thread && thread->GetStatus() == ThreadStatus::Running) { 49 if (thread && thread->GetStatus() == ThreadStatus::Running) {
50 if (ready_queue.empty())
51 return thread;
49 // We have to do better than the current thread. 52 // We have to do better than the current thread.
50 // This call returns null when that's not possible. 53 // This call returns null when that's not possible.
51 next = ready_queue.pop_first_better(thread->GetPriority()); 54 next = ready_queue.front();
52 if (!next) { 55 if (next == nullptr || next->GetPriority() >= thread->GetPriority()) {
53 // Otherwise just keep going with the current thread
54 next = thread; 56 next = thread;
55 } 57 }
56 } else { 58 } else {
57 next = ready_queue.pop_first(); 59 if (ready_queue.empty())
60 return nullptr;
61 next = ready_queue.front();
58 } 62 }
59 63
60 return next; 64 return next;
61} 65}
62 66
63void Scheduler::SwitchContext(Thread* new_thread) { 67void Scheduler::SwitchContext(Thread* new_thread) {
64 Thread* const previous_thread = GetCurrentThread(); 68 Thread* previous_thread = GetCurrentThread();
65 Process* const previous_process = system.Kernel().CurrentProcess(); 69 Process* const previous_process = system.Kernel().CurrentProcess();
66 70
67 UpdateLastContextSwitchTime(previous_thread, previous_process); 71 UpdateLastContextSwitchTime(previous_thread, previous_process);
@@ -75,7 +79,7 @@ void Scheduler::SwitchContext(Thread* new_thread) {
75 if (previous_thread->GetStatus() == ThreadStatus::Running) { 79 if (previous_thread->GetStatus() == ThreadStatus::Running) {
76 // This is only the case when a reschedule is triggered without the current thread 80 // This is only the case when a reschedule is triggered without the current thread
77 // yielding execution (i.e. an event triggered, system core time-sliced, etc) 81 // yielding execution (i.e. an event triggered, system core time-sliced, etc)
78 ready_queue.push_front(previous_thread->GetPriority(), previous_thread); 82 ready_queue.add(previous_thread, previous_thread->GetPriority(), false);
79 previous_thread->SetStatus(ThreadStatus::Ready); 83 previous_thread->SetStatus(ThreadStatus::Ready);
80 } 84 }
81 } 85 }
@@ -90,7 +94,7 @@ void Scheduler::SwitchContext(Thread* new_thread) {
90 94
91 current_thread = new_thread; 95 current_thread = new_thread;
92 96
93 ready_queue.remove(new_thread->GetPriority(), new_thread); 97 ready_queue.remove(new_thread, new_thread->GetPriority());
94 new_thread->SetStatus(ThreadStatus::Running); 98 new_thread->SetStatus(ThreadStatus::Running);
95 99
96 auto* const thread_owner_process = current_thread->GetOwnerProcess(); 100 auto* const thread_owner_process = current_thread->GetOwnerProcess();
@@ -147,7 +151,6 @@ void Scheduler::AddThread(SharedPtr<Thread> thread, u32 priority) {
147 std::lock_guard<std::mutex> lock(scheduler_mutex); 151 std::lock_guard<std::mutex> lock(scheduler_mutex);
148 152
149 thread_list.push_back(std::move(thread)); 153 thread_list.push_back(std::move(thread));
150 ready_queue.prepare(priority);
151} 154}
152 155
153void Scheduler::RemoveThread(Thread* thread) { 156void Scheduler::RemoveThread(Thread* thread) {
@@ -161,33 +164,35 @@ void Scheduler::ScheduleThread(Thread* thread, u32 priority) {
161 std::lock_guard<std::mutex> lock(scheduler_mutex); 164 std::lock_guard<std::mutex> lock(scheduler_mutex);
162 165
163 ASSERT(thread->GetStatus() == ThreadStatus::Ready); 166 ASSERT(thread->GetStatus() == ThreadStatus::Ready);
164 ready_queue.push_back(priority, thread); 167 ready_queue.add(thread, priority);
165} 168}
166 169
167void Scheduler::UnscheduleThread(Thread* thread, u32 priority) { 170void Scheduler::UnscheduleThread(Thread* thread, u32 priority) {
168 std::lock_guard<std::mutex> lock(scheduler_mutex); 171 std::lock_guard<std::mutex> lock(scheduler_mutex);
169 172
170 ASSERT(thread->GetStatus() == ThreadStatus::Ready); 173 ASSERT(thread->GetStatus() == ThreadStatus::Ready);
171 ready_queue.remove(priority, thread); 174 ready_queue.remove(thread, priority);
172} 175}
173 176
174void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { 177void Scheduler::SetThreadPriority(Thread* thread, u32 priority) {
175 std::lock_guard<std::mutex> lock(scheduler_mutex); 178 std::lock_guard<std::mutex> lock(scheduler_mutex);
179 if (thread->GetPriority() == priority)
180 return;
176 181
177 // If thread was ready, adjust queues 182 // If thread was ready, adjust queues
178 if (thread->GetStatus() == ThreadStatus::Ready) 183 if (thread->GetStatus() == ThreadStatus::Ready)
179 ready_queue.move(thread, thread->GetPriority(), priority); 184 ready_queue.adjust(thread, thread->GetPriority(), priority);
180 else
181 ready_queue.prepare(priority);
182} 185}
183 186
184Thread* Scheduler::GetNextSuggestedThread(u32 core, u32 maximum_priority) const { 187Thread* Scheduler::GetNextSuggestedThread(u32 core, u32 maximum_priority) const {
185 std::lock_guard<std::mutex> lock(scheduler_mutex); 188 std::lock_guard<std::mutex> lock(scheduler_mutex);
186 189
187 const u32 mask = 1U << core; 190 const u32 mask = 1U << core;
188 return ready_queue.get_first_filter([mask, maximum_priority](Thread const* thread) { 191 for (auto& thread : ready_queue) {
189 return (thread->GetAffinityMask() & mask) != 0 && thread->GetPriority() < maximum_priority; 192 if ((thread->GetAffinityMask() & mask) != 0 && thread->GetPriority() < maximum_priority)
190 }); 193 return thread;
194 }
195 return nullptr;
191} 196}
192 197
193void Scheduler::YieldWithoutLoadBalancing(Thread* thread) { 198void Scheduler::YieldWithoutLoadBalancing(Thread* thread) {