diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h index e7594db689..133122c5f4 100644 --- a/src/common/thread_queue_list.h +++ b/src/common/thread_queue_list.h @@ -49,22 +49,6 @@ struct ThreadQueueList { return T(); } - template - T get_first_filter(UnaryPredicate filter) const { - const Queue* cur = first; - while (cur != nullptr) { - if (!cur->data.empty()) { - for (const auto& item : cur->data) { - if (filter(item)) - return item; - } - } - cur = cur->next_nonempty; - } - - return T(); - } - T pop_first() { Queue* cur = first; while (cur != nullptr) { diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 624c841ad4..5a5f4cef1a 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -9,7 +9,6 @@ #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" @@ -170,16 +169,6 @@ void Scheduler::UnscheduleThread(Thread* thread, u32 priority) { ready_queue.remove(priority, thread); } -void Scheduler::MoveThreadToBackOfPriorityQueue(Thread* thread, u32 priority) { - std::lock_guard lock(scheduler_mutex); - - // Thread is not in queue - ASSERT(ready_queue.contains(thread) != -1); - - ready_queue.remove(priority, thread); - ready_queue.push_back(priority, thread); -} - void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { std::lock_guard lock(scheduler_mutex); @@ -190,64 +179,4 @@ void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { ready_queue.prepare(priority); } -Thread* Scheduler::GetNextSuggestedThread(u32 core) const { - std::lock_guard lock(scheduler_mutex); - - const u32 mask = 1U << core; - return ready_queue.get_first_filter( - [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(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 diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 71b32589a1..c63032b7d5 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -48,81 +48,9 @@ public: /// Unschedules a thread that was already scheduled void UnscheduleThread(Thread* thread, u32 priority); - /// Moves a thread to the back of the current priority queue - void MoveThreadToBackOfPriorityQueue(Thread* thread, u32 priority); - /// Sets the priority of a thread in the scheduler void SetThreadPriority(Thread* thread, u32 priority); - /// Gets the next suggested thread for load balancing - Thread* GetNextSuggestedThread(u32 core) const; - - /** - * YieldWithoutLoadBalancing -- analogous to normal yield on a system - * Moves the thread to the end of the ready queue for its priority, and then reschedules the - * system to the new head of the queue. - * - * Example (Single Core -- but can be extrapolated to multi): - * ready_queue[prio=0]: ThreadA, ThreadB, ThreadC (->exec order->) - * Currently Running: ThreadR - * - * ThreadR calls YieldWithoutLoadBalancing - * - * ThreadR is moved to the end of ready_queue[prio=0]: - * ready_queue[prio=0]: ThreadA, ThreadB, ThreadC, ThreadR (->exec order->) - * Currently Running: Nothing - * - * System is rescheduled (ThreadA is popped off of queue): - * ready_queue[prio=0]: ThreadB, ThreadC, ThreadR (->exec order->) - * Currently Running: ThreadA - * - * If the queue is empty at time of call, no yielding occurs. This does not cross between cores - * or priorities at all. - */ - void YieldWithoutLoadBalancing(Thread* thread); - - /** - * YieldWithLoadBalancing -- yield but with better selection of the new running thread - * Moves the current thread to the end of the ready queue for its priority, then selects a - * 'suggested thread' (a thread on a different core that could run on this core) from the - * scheduler, changes its core, and reschedules the current core to that thread. - * - * Example (Dual Core -- can be extrapolated to Quad Core, this is just normal yield if it were - * single core): - * ready_queue[core=0][prio=0]: ThreadA, ThreadB (affinities not pictured as irrelevant - * ready_queue[core=1][prio=0]: ThreadC[affinity=both], ThreadD[affinity=core1only] - * Currently Running: ThreadQ on Core 0 || ThreadP on Core 1 - * - * ThreadQ calls YieldWithLoadBalancing - * - * ThreadQ is moved to the end of ready_queue[core=0][prio=0]: - * ready_queue[core=0][prio=0]: ThreadA, ThreadB - * ready_queue[core=1][prio=0]: ThreadC[affinity=both], ThreadD[affinity=core1only] - * Currently Running: ThreadQ on Core 0 || ThreadP on Core 1 - * - * A list of suggested threads for each core is compiled - * Suggested Threads: {ThreadC on Core 1} - * If this were quad core (as the switch is), there could be between 0 and 3 threads in this - * list. If there are more than one, the thread is selected by highest prio. - * - * ThreadC is core changed to Core 0: - * ready_queue[core=0][prio=0]: ThreadC, ThreadA, ThreadB, ThreadQ - * ready_queue[core=1][prio=0]: ThreadD - * Currently Running: None on Core 0 || ThreadP on Core 1 - * - * System is rescheduled (ThreadC is popped off of queue): - * ready_queue[core=0][prio=0]: ThreadA, ThreadB, ThreadQ - * ready_queue[core=1][prio=0]: ThreadD - * Currently Running: ThreadC on Core 0 || ThreadP on Core 1 - * - * If no suggested threads can be found this will behave just as normal yield. If there are - * multiple candidates for the suggested thread on a core, the highest prio is taken. - */ - void YieldWithLoadBalancing(Thread* thread); - - /// Currently unknown -- asserts as unimplemented on call - void YieldAndWaitForLoadBalancing(Thread* thread); - /// Returns a list of all threads managed by the scheduler const std::vector>& GetThreadList() const { return thread_list; diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 77aec099ae..d384d50dbc 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -26,7 +26,6 @@ enum ThreadPriority : u32 { THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps THREADPRIO_DEFAULT = 44, ///< Default thread priority for userland apps THREADPRIO_LOWEST = 63, ///< Lowest thread priority - THREADPRIO_COUNT = 64, ///< Total number of possible thread priorities. }; enum ThreadProcessorId : s32 {