summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/scheduler.cpp
diff options
context:
space:
mode:
authorZach Hilman <zachhilman@gmail.com>2018-11-22 06:33:53 +0100
committerZach Hilman <zachhilman@gmail.com>2018-11-22 06:33:53 +0100
commit820d81b9a5392951c18daa5a47d6c0ffd28baa9b (patch)
treedab20f1ff49ab76cdcd511e189799f4d6e40677e /src/core/hle/kernel/scheduler.cpp
parentsvc: Implement yield types 0 and -1 (diff)
downloadyuzu-820d81b9a5392951c18daa5a47d6c0ffd28baa9b.tar
yuzu-820d81b9a5392951c18daa5a47d6c0ffd28baa9b.tar.gz
yuzu-820d81b9a5392951c18daa5a47d6c0ffd28baa9b.tar.bz2
yuzu-820d81b9a5392951c18daa5a47d6c0ffd28baa9b.tar.lz
yuzu-820d81b9a5392951c18daa5a47d6c0ffd28baa9b.tar.xz
yuzu-820d81b9a5392951c18daa5a47d6c0ffd28baa9b.tar.zst
yuzu-820d81b9a5392951c18daa5a47d6c0ffd28baa9b.zip
Diffstat (limited to 'src/core/hle/kernel/scheduler.cpp')
-rw-r--r--src/core/hle/kernel/scheduler.cpp61
1 files changed, 57 insertions, 4 deletions
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index fb5e14950..624c841ad 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -9,6 +9,7 @@
#include "common/logging/log.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
+#include "core/core_cpu.h"
#include "core/core_timing.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
@@ -169,7 +170,7 @@ void Scheduler::UnscheduleThread(Thread* thread, u32 priority) {
ready_queue.remove(priority, thread);
}
-void Scheduler::RescheduleThread(Thread* thread, u32 priority) {
+void Scheduler::MoveThreadToBackOfPriorityQueue(Thread* thread, u32 priority) {
std::lock_guard<std::mutex> lock(scheduler_mutex);
// Thread is not in queue
@@ -189,12 +190,64 @@ void Scheduler::SetThreadPriority(Thread* thread, u32 priority) {
ready_queue.prepare(priority);
}
-Thread* Scheduler::GetNextSuggestedThread(u32 core) {
+Thread* Scheduler::GetNextSuggestedThread(u32 core) const {
std::lock_guard<std::mutex> lock(scheduler_mutex);
- const auto mask = 1 << core;
+ const u32 mask = 1U << core;
return ready_queue.get_first_filter(
- [&mask](Thread* thread) { return (thread->GetAffinityMask() & mask) != 0; });
+ [mask](Thread const* thread) { return (thread->GetAffinityMask() & mask) != 0; });
+}
+
+void Scheduler::YieldWithoutLoadBalancing(Thread* thread) {
+ ASSERT(thread != nullptr);
+ // Avoid yielding if the thread isn't even running.
+ ASSERT(thread->GetStatus() == ThreadStatus::Running);
+
+ // Sanity check that the priority is valid
+ ASSERT(thread->GetPriority() < THREADPRIO_COUNT);
+
+ // Yield this thread
+ MoveThreadToBackOfPriorityQueue(thread, thread->GetPriority());
+ Reschedule();
+}
+
+void Scheduler::YieldWithLoadBalancing(Thread* thread) {
+ ASSERT(thread != nullptr);
+ const auto priority = thread->GetPriority();
+ const auto core = static_cast<u32>(thread->GetProcessorID());
+
+ // Avoid yielding if the thread isn't even running.
+ ASSERT(thread->GetStatus() == ThreadStatus::Running);
+
+ // Sanity check that the priority is valid
+ ASSERT(priority < THREADPRIO_COUNT);
+
+ // Reschedule thread to end of queue.
+ MoveThreadToBackOfPriorityQueue(thread, priority);
+
+ Thread* suggested_thread = nullptr;
+
+ // Search through all of the cpu cores (except this one) for a suggested thread.
+ // Take the first non-nullptr one
+ for (unsigned cur_core = 0; cur_core < Core::NUM_CPU_CORES; ++cur_core) {
+ if (cur_core == core)
+ continue;
+
+ const auto res =
+ Core::System::GetInstance().CpuCore(cur_core).Scheduler().GetNextSuggestedThread(core);
+ if (res != nullptr) {
+ suggested_thread = res;
+ break;
+ }
+ }
+
+ // If a suggested thread was found, queue that for this core
+ if (suggested_thread != nullptr)
+ suggested_thread->ChangeCore(core, suggested_thread->GetAffinityMask());
+}
+
+void Scheduler::YieldAndWaitForLoadBalancing(Thread* thread) {
+ UNIMPLEMENTED_MSG("Wait for load balancing thread yield type is not implemented!");
}
} // namespace Kernel