diff options
author | Zach Hilman <zachhilman@gmail.com> | 2018-11-22 06:33:53 +0100 |
---|---|---|
committer | Zach Hilman <zachhilman@gmail.com> | 2018-11-22 06:33:53 +0100 |
commit | 820d81b9a5392951c18daa5a47d6c0ffd28baa9b (patch) | |
tree | dab20f1ff49ab76cdcd511e189799f4d6e40677e /src/core/hle/kernel/scheduler.cpp | |
parent | svc: Implement yield types 0 and -1 (diff) | |
download | yuzu-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.cpp | 61 |
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 |