summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2020-12-04 01:43:18 +0100
committerbunnei <bunneidev@gmail.com>2020-12-06 09:03:24 +0100
commit8d3e06349e12e7de17c334619f1f986792d1de4b (patch)
tree926e34570e5e51d5d7dc03c13f45b1401f5ae829 /src/core/hle/kernel
parenthle: kernel: Rewrite scheduler implementation based on Mesopshere. (diff)
downloadyuzu-8d3e06349e12e7de17c334619f1f986792d1de4b.tar
yuzu-8d3e06349e12e7de17c334619f1f986792d1de4b.tar.gz
yuzu-8d3e06349e12e7de17c334619f1f986792d1de4b.tar.bz2
yuzu-8d3e06349e12e7de17c334619f1f986792d1de4b.tar.lz
yuzu-8d3e06349e12e7de17c334619f1f986792d1de4b.tar.xz
yuzu-8d3e06349e12e7de17c334619f1f986792d1de4b.tar.zst
yuzu-8d3e06349e12e7de17c334619f1f986792d1de4b.zip
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/global_scheduler_context.cpp55
-rw-r--r--src/core/hle/kernel/global_scheduler_context.h79
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp48
-rw-r--r--src/core/hle/kernel/k_scheduler.h74
4 files changed, 138 insertions, 118 deletions
diff --git a/src/core/hle/kernel/global_scheduler_context.cpp b/src/core/hle/kernel/global_scheduler_context.cpp
new file mode 100644
index 000000000..40e9adf47
--- /dev/null
+++ b/src/core/hle/kernel/global_scheduler_context.cpp
@@ -0,0 +1,55 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <mutex>
+
+#include "common/assert.h"
+#include "core/core.h"
+#include "core/hle/kernel/global_scheduler_context.h"
+#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/kernel.h"
+
+namespace Kernel {
+
+GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel)
+ : kernel{kernel}, scheduler_lock{kernel} {}
+
+GlobalSchedulerContext::~GlobalSchedulerContext() = default;
+
+void GlobalSchedulerContext::AddThread(std::shared_ptr<Thread> thread) {
+ std::scoped_lock lock{global_list_guard};
+ thread_list.push_back(std::move(thread));
+}
+
+void GlobalSchedulerContext::RemoveThread(std::shared_ptr<Thread> thread) {
+ std::scoped_lock lock{global_list_guard};
+ thread_list.erase(std::remove(thread_list.begin(), thread_list.end(), thread),
+ thread_list.end());
+}
+
+void GlobalSchedulerContext::PreemptThreads() {
+ // The priority levels at which the global scheduler preempts threads every 10 ms. They are
+ // ordered from Core 0 to Core 3.
+ std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 63};
+
+ ASSERT(IsLocked());
+ for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
+ const u32 priority = preemption_priorities[core_id];
+ kernel.Scheduler(core_id).RotateScheduledQueue(core_id, priority);
+ }
+}
+
+bool GlobalSchedulerContext::IsLocked() const {
+ return scheduler_lock.IsLockedByCurrentThread();
+}
+
+void GlobalSchedulerContext::Lock() {
+ scheduler_lock.Lock();
+}
+
+void GlobalSchedulerContext::Unlock() {
+ scheduler_lock.Unlock();
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h
new file mode 100644
index 000000000..40fe44cc0
--- /dev/null
+++ b/src/core/hle/kernel/global_scheduler_context.h
@@ -0,0 +1,79 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <atomic>
+#include <vector>
+
+#include "common/common_types.h"
+#include "common/spin_lock.h"
+#include "core/hardware_properties.h"
+#include "core/hle/kernel/k_priority_queue.h"
+#include "core/hle/kernel/k_scheduler_lock.h"
+#include "core/hle/kernel/thread.h"
+
+namespace Kernel {
+
+class KernelCore;
+class SchedulerLock;
+
+using KSchedulerPriorityQueue =
+ KPriorityQueue<Thread, Core::Hardware::NUM_CPU_CORES, THREADPRIO_LOWEST, THREADPRIO_HIGHEST>;
+static constexpr s32 HighestCoreMigrationAllowedPriority = 2;
+
+class GlobalSchedulerContext final {
+ friend class KScheduler;
+
+public:
+ explicit GlobalSchedulerContext(KernelCore& kernel);
+ ~GlobalSchedulerContext();
+
+ /// Adds a new thread to the scheduler
+ void AddThread(std::shared_ptr<Thread> thread);
+
+ /// Removes a thread from the scheduler
+ void RemoveThread(std::shared_ptr<Thread> thread);
+
+ /// Returns a list of all threads managed by the scheduler
+ const std::vector<std::shared_ptr<Thread>>& GetThreadList() const {
+ return thread_list;
+ }
+
+ /**
+ * Rotates the scheduling queues of threads at a preemption priority and then does
+ * some core rebalancing. Preemption priorities can be found in the array
+ * 'preemption_priorities'.
+ *
+ * @note This operation happens every 10ms.
+ */
+ void PreemptThreads();
+
+ /// Returns true if the global scheduler lock is acquired
+ bool IsLocked() const;
+
+private:
+ friend class SchedulerLock;
+
+ /// Lock the scheduler to the current thread.
+ void Lock();
+
+ /// Unlocks the scheduler, reselects threads, interrupts cores for rescheduling
+ /// and reschedules current core if needed.
+ void Unlock();
+
+ using LockType = KAbstractSchedulerLock<KScheduler>;
+
+ KernelCore& kernel;
+
+ std::atomic_bool scheduler_update_needed{};
+ KSchedulerPriorityQueue priority_queue;
+ LockType scheduler_lock;
+
+ /// Lists all thread ids that aren't deleted/etc.
+ std::vector<std::shared_ptr<Thread>> thread_list;
+ Common::SpinLock global_list_guard{};
+};
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 7f7da610d..c7e2eabd4 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -5,12 +5,6 @@
// This file references various implementation details from Atmosphere, an open-source firmware for
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-#include <algorithm>
-#include <mutex>
-#include <set>
-#include <unordered_set>
-#include <utility>
-
#include "common/assert.h"
#include "common/bit_util.h"
#include "common/fiber.h"
@@ -19,10 +13,10 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/cpu_manager.h"
+#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/time_manager.h"
@@ -34,11 +28,6 @@ static void IncrementScheduledCount(Kernel::Thread* thread) {
}
}
-GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel)
- : kernel{kernel}, scheduler_lock{kernel} {}
-
-GlobalSchedulerContext::~GlobalSchedulerContext() = default;
-
/*static*/ void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedule,
Core::EmuThreadHandle global_thread) {
u32 current_core = global_thread.host_handle;
@@ -205,33 +194,6 @@ u64 KScheduler::UpdateHighestPriorityThread(Thread* highest_thread) {
return cores_needing_scheduling;
}
-void GlobalSchedulerContext::AddThread(std::shared_ptr<Thread> thread) {
- std::scoped_lock lock{global_list_guard};
- thread_list.push_back(std::move(thread));
-}
-
-void GlobalSchedulerContext::RemoveThread(std::shared_ptr<Thread> thread) {
- std::scoped_lock lock{global_list_guard};
- thread_list.erase(std::remove(thread_list.begin(), thread_list.end(), thread),
- thread_list.end());
-}
-
-void GlobalSchedulerContext::PreemptThreads() {
- // The priority levels at which the global scheduler preempts threads every 10 ms. They are
- // ordered from Core 0 to Core 3.
- std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 63};
-
- ASSERT(IsLocked());
- for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
- const u32 priority = preemption_priorities[core_id];
- kernel.Scheduler(core_id).RotateScheduledQueue(core_id, priority);
- }
-}
-
-bool GlobalSchedulerContext::IsLocked() const {
- return scheduler_lock.IsLockedByCurrentThread();
-}
-
/*static*/ void KScheduler::OnThreadStateChanged(KernelCore& kernel, Thread* thread,
u32 old_state) {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
@@ -635,14 +597,6 @@ void KScheduler::YieldToAnyThread() {
}
}
-void GlobalSchedulerContext::Lock() {
- scheduler_lock.Lock();
-}
-
-void GlobalSchedulerContext::Unlock() {
- scheduler_lock.Unlock();
-}
-
KScheduler::KScheduler(Core::System& system, std::size_t core_id)
: system(system), core_id(core_id) {
switch_fiber = std::make_shared<Common::Fiber>(std::function<void(void*)>(OnSwitch), this);
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h
index 535ee34b9..7f020d96e 100644
--- a/src/core/hle/kernel/k_scheduler.h
+++ b/src/core/hle/kernel/k_scheduler.h
@@ -8,94 +8,27 @@
#pragma once
#include <atomic>
-#include <memory>
-#include <mutex>
-#include <vector>
#include "common/common_types.h"
-#include "common/multi_level_queue.h"
-#include "common/scope_exit.h"
#include "common/spin_lock.h"
-#include "core/core_timing.h"
-#include "core/hardware_properties.h"
+#include "core/hle/kernel/global_scheduler_context.h"
#include "core/hle/kernel/k_priority_queue.h"
#include "core/hle/kernel/k_scheduler_lock.h"
-#include "core/hle/kernel/thread.h"
namespace Common {
class Fiber;
}
namespace Core {
-class ARM_Interface;
class System;
-} // namespace Core
+}
namespace Kernel {
class KernelCore;
class Process;
class SchedulerLock;
-
-using KSchedulerPriorityQueue =
- KPriorityQueue<Thread, Core::Hardware::NUM_CPU_CORES, THREADPRIO_LOWEST, THREADPRIO_HIGHEST>;
-static constexpr s32 HighestCoreMigrationAllowedPriority = 2;
-
-class GlobalSchedulerContext final {
- friend class KScheduler;
-
-public:
- explicit GlobalSchedulerContext(KernelCore& kernel);
- ~GlobalSchedulerContext();
-
- /// Adds a new thread to the scheduler
- void AddThread(std::shared_ptr<Thread> thread);
-
- /// Removes a thread from the scheduler
- void RemoveThread(std::shared_ptr<Thread> thread);
-
- /// Returns a list of all threads managed by the scheduler
- const std::vector<std::shared_ptr<Thread>>& GetThreadList() const {
- return thread_list;
- }
-
- /**
- * Rotates the scheduling queues of threads at a preemption priority and then does
- * some core rebalancing. Preemption priorities can be found in the array
- * 'preemption_priorities'.
- *
- * @note This operation happens every 10ms.
- */
- void PreemptThreads();
-
- u32 CpuCoresCount() const {
- return Core::Hardware::NUM_CPU_CORES;
- }
-
- bool IsLocked() const;
-
-private:
- friend class SchedulerLock;
-
- /// Lock the scheduler to the current thread.
- void Lock();
-
- /// Unlocks the scheduler, reselects threads, interrupts cores for rescheduling
- /// and reschedules current core if needed.
- void Unlock();
-
- using LockType = KAbstractSchedulerLock<KScheduler>;
-
- KernelCore& kernel;
-
- std::atomic_bool scheduler_update_needed{};
- KSchedulerPriorityQueue priority_queue;
- LockType scheduler_lock;
-
- /// Lists all thread ids that aren't deleted/etc.
- std::vector<std::shared_ptr<Thread>> thread_list;
- Common::SpinLock global_list_guard{};
-};
+class Thread;
class KScheduler final {
public:
@@ -221,7 +154,6 @@ private:
/// Switches the CPU's active thread context to that of the specified thread
void ScheduleImpl();
- void SwitchThread(Thread* next_thread);
/// When a thread wakes up, it must run this through it's new scheduler
void SwitchContextStep2();