diff options
| author | 2020-06-28 12:37:50 -0400 | |
|---|---|---|
| committer | 2020-06-28 12:37:50 -0400 | |
| commit | b05795d704e0c194215f815a5703db09e524b59a (patch) | |
| tree | ecf4023b4ee0c91555c1d8263762fcb9dcb04a17 /src/core/hle/kernel/scheduler.h | |
| parent | Merge pull request #4196 from ogniK5377/nrr-nro-fixes (diff) | |
| parent | Core/Common: Address Feedback. (diff) | |
| download | yuzu-b05795d704e0c194215f815a5703db09e524b59a.tar.gz yuzu-b05795d704e0c194215f815a5703db09e524b59a.tar.xz yuzu-b05795d704e0c194215f815a5703db09e524b59a.zip | |
Merge pull request #3955 from FernandoS27/prometheus-2b
Remake Kernel Scheduling, CPU Management & Boot Management (Prometheus)
Diffstat (limited to 'src/core/hle/kernel/scheduler.h')
| -rw-r--r-- | src/core/hle/kernel/scheduler.h | 123 |
1 files changed, 85 insertions, 38 deletions
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 07df33f9c..b3b4b5169 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h | |||
| @@ -11,9 +11,14 @@ | |||
| 11 | 11 | ||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/multi_level_queue.h" | 13 | #include "common/multi_level_queue.h" |
| 14 | #include "common/spin_lock.h" | ||
| 14 | #include "core/hardware_properties.h" | 15 | #include "core/hardware_properties.h" |
| 15 | #include "core/hle/kernel/thread.h" | 16 | #include "core/hle/kernel/thread.h" |
| 16 | 17 | ||
| 18 | namespace Common { | ||
| 19 | class Fiber; | ||
| 20 | } | ||
| 21 | |||
| 17 | namespace Core { | 22 | namespace Core { |
| 18 | class ARM_Interface; | 23 | class ARM_Interface; |
| 19 | class System; | 24 | class System; |
| @@ -41,41 +46,17 @@ public: | |||
| 41 | return thread_list; | 46 | return thread_list; |
| 42 | } | 47 | } |
| 43 | 48 | ||
| 44 | /** | 49 | /// Notify the scheduler a thread's status has changed. |
| 45 | * Add a thread to the suggested queue of a cpu core. Suggested threads may be | 50 | void AdjustSchedulingOnStatus(Thread* thread, u32 old_flags); |
| 46 | * picked if no thread is scheduled to run on the core. | ||
| 47 | */ | ||
| 48 | void Suggest(u32 priority, std::size_t core, Thread* thread); | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Remove a thread to the suggested queue of a cpu core. Suggested threads may be | ||
| 52 | * picked if no thread is scheduled to run on the core. | ||
| 53 | */ | ||
| 54 | void Unsuggest(u32 priority, std::size_t core, Thread* thread); | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Add a thread to the scheduling queue of a cpu core. The thread is added at the | ||
| 58 | * back the queue in its priority level. | ||
| 59 | */ | ||
| 60 | void Schedule(u32 priority, std::size_t core, Thread* thread); | ||
| 61 | |||
| 62 | /** | ||
| 63 | * Add a thread to the scheduling queue of a cpu core. The thread is added at the | ||
| 64 | * front the queue in its priority level. | ||
| 65 | */ | ||
| 66 | void SchedulePrepend(u32 priority, std::size_t core, Thread* thread); | ||
| 67 | 51 | ||
| 68 | /// Reschedule an already scheduled thread based on a new priority | 52 | /// Notify the scheduler a thread's priority has changed. |
| 69 | void Reschedule(u32 priority, std::size_t core, Thread* thread); | 53 | void AdjustSchedulingOnPriority(Thread* thread, u32 old_priority); |
| 70 | |||
| 71 | /// Unschedules a thread. | ||
| 72 | void Unschedule(u32 priority, std::size_t core, Thread* thread); | ||
| 73 | 54 | ||
| 74 | /// Selects a core and forces it to unload its current thread's context | 55 | /// Notify the scheduler a thread's core and/or affinity mask has changed. |
| 75 | void UnloadThread(std::size_t core); | 56 | void AdjustSchedulingOnAffinity(Thread* thread, u64 old_affinity_mask, s32 old_core); |
| 76 | 57 | ||
| 77 | /** | 58 | /** |
| 78 | * Takes care of selecting the new scheduled thread in three steps: | 59 | * Takes care of selecting the new scheduled threads in three steps: |
| 79 | * | 60 | * |
| 80 | * 1. First a thread is selected from the top of the priority queue. If no thread | 61 | * 1. First a thread is selected from the top of the priority queue. If no thread |
| 81 | * is obtained then we move to step two, else we are done. | 62 | * is obtained then we move to step two, else we are done. |
| @@ -85,8 +66,10 @@ public: | |||
| 85 | * | 66 | * |
| 86 | * 3. Third is no suggested thread is found, we do a second pass and pick a running | 67 | * 3. Third is no suggested thread is found, we do a second pass and pick a running |
| 87 | * thread in another core and swap it with its current thread. | 68 | * thread in another core and swap it with its current thread. |
| 69 | * | ||
| 70 | * returns the cores needing scheduling. | ||
| 88 | */ | 71 | */ |
| 89 | void SelectThread(std::size_t core); | 72 | u32 SelectThreads(); |
| 90 | 73 | ||
| 91 | bool HaveReadyThreads(std::size_t core_id) const { | 74 | bool HaveReadyThreads(std::size_t core_id) const { |
| 92 | return !scheduled_queue[core_id].empty(); | 75 | return !scheduled_queue[core_id].empty(); |
| @@ -149,6 +132,40 @@ private: | |||
| 149 | /// Unlocks the scheduler, reselects threads, interrupts cores for rescheduling | 132 | /// Unlocks the scheduler, reselects threads, interrupts cores for rescheduling |
| 150 | /// and reschedules current core if needed. | 133 | /// and reschedules current core if needed. |
| 151 | void Unlock(); | 134 | void Unlock(); |
| 135 | |||
| 136 | void EnableInterruptAndSchedule(u32 cores_pending_reschedule, | ||
| 137 | Core::EmuThreadHandle global_thread); | ||
| 138 | |||
| 139 | /** | ||
| 140 | * Add a thread to the suggested queue of a cpu core. Suggested threads may be | ||
| 141 | * picked if no thread is scheduled to run on the core. | ||
| 142 | */ | ||
| 143 | void Suggest(u32 priority, std::size_t core, Thread* thread); | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Remove a thread to the suggested queue of a cpu core. Suggested threads may be | ||
| 147 | * picked if no thread is scheduled to run on the core. | ||
| 148 | */ | ||
| 149 | void Unsuggest(u32 priority, std::size_t core, Thread* thread); | ||
| 150 | |||
| 151 | /** | ||
| 152 | * Add a thread to the scheduling queue of a cpu core. The thread is added at the | ||
| 153 | * back the queue in its priority level. | ||
| 154 | */ | ||
| 155 | void Schedule(u32 priority, std::size_t core, Thread* thread); | ||
| 156 | |||
| 157 | /** | ||
| 158 | * Add a thread to the scheduling queue of a cpu core. The thread is added at the | ||
| 159 | * front the queue in its priority level. | ||
| 160 | */ | ||
| 161 | void SchedulePrepend(u32 priority, std::size_t core, Thread* thread); | ||
| 162 | |||
| 163 | /// Reschedule an already scheduled thread based on a new priority | ||
| 164 | void Reschedule(u32 priority, std::size_t core, Thread* thread); | ||
| 165 | |||
| 166 | /// Unschedules a thread. | ||
| 167 | void Unschedule(u32 priority, std::size_t core, Thread* thread); | ||
| 168 | |||
| 152 | /** | 169 | /** |
| 153 | * Transfers a thread into an specific core. If the destination_core is -1 | 170 | * Transfers a thread into an specific core. If the destination_core is -1 |
| 154 | * it will be unscheduled from its source code and added into its suggested | 171 | * it will be unscheduled from its source code and added into its suggested |
| @@ -170,10 +187,13 @@ private: | |||
| 170 | std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62}; | 187 | std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62}; |
| 171 | 188 | ||
| 172 | /// Scheduler lock mechanisms. | 189 | /// Scheduler lock mechanisms. |
| 173 | std::mutex inner_lock{}; // TODO(Blinkhawk): Replace for a SpinLock | 190 | bool is_locked{}; |
| 191 | Common::SpinLock inner_lock{}; | ||
| 174 | std::atomic<s64> scope_lock{}; | 192 | std::atomic<s64> scope_lock{}; |
| 175 | Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()}; | 193 | Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()}; |
| 176 | 194 | ||
| 195 | Common::SpinLock global_list_guard{}; | ||
| 196 | |||
| 177 | /// Lists all thread ids that aren't deleted/etc. | 197 | /// Lists all thread ids that aren't deleted/etc. |
| 178 | std::vector<std::shared_ptr<Thread>> thread_list; | 198 | std::vector<std::shared_ptr<Thread>> thread_list; |
| 179 | KernelCore& kernel; | 199 | KernelCore& kernel; |
| @@ -190,11 +210,11 @@ public: | |||
| 190 | /// Reschedules to the next available thread (call after current thread is suspended) | 210 | /// Reschedules to the next available thread (call after current thread is suspended) |
| 191 | void TryDoContextSwitch(); | 211 | void TryDoContextSwitch(); |
| 192 | 212 | ||
| 193 | /// Unloads currently running thread | 213 | /// The next two are for SingleCore Only. |
| 194 | void UnloadThread(); | 214 | /// Unload current thread before preempting core. |
| 195 | 215 | void Unload(); | |
| 196 | /// Select the threads in top of the scheduling multilist. | 216 | /// Reload current thread after core preemption. |
| 197 | void SelectThreads(); | 217 | void Reload(); |
| 198 | 218 | ||
| 199 | /// Gets the current running thread | 219 | /// Gets the current running thread |
| 200 | Thread* GetCurrentThread() const; | 220 | Thread* GetCurrentThread() const; |
| @@ -209,15 +229,30 @@ public: | |||
| 209 | return is_context_switch_pending; | 229 | return is_context_switch_pending; |
| 210 | } | 230 | } |
| 211 | 231 | ||
| 232 | void Initialize(); | ||
| 233 | |||
| 212 | /// Shutdowns the scheduler. | 234 | /// Shutdowns the scheduler. |
| 213 | void Shutdown(); | 235 | void Shutdown(); |
| 214 | 236 | ||
| 237 | void OnThreadStart(); | ||
| 238 | |||
| 239 | std::shared_ptr<Common::Fiber>& ControlContext() { | ||
| 240 | return switch_fiber; | ||
| 241 | } | ||
| 242 | |||
| 243 | const std::shared_ptr<Common::Fiber>& ControlContext() const { | ||
| 244 | return switch_fiber; | ||
| 245 | } | ||
| 246 | |||
| 215 | private: | 247 | private: |
| 216 | friend class GlobalScheduler; | 248 | friend class GlobalScheduler; |
| 217 | 249 | ||
| 218 | /// Switches the CPU's active thread context to that of the specified thread | 250 | /// Switches the CPU's active thread context to that of the specified thread |
| 219 | void SwitchContext(); | 251 | void SwitchContext(); |
| 220 | 252 | ||
| 253 | /// When a thread wakes up, it must run this through it's new scheduler | ||
| 254 | void SwitchContextStep2(); | ||
| 255 | |||
| 221 | /** | 256 | /** |
| 222 | * Called on every context switch to update the internal timestamp | 257 | * Called on every context switch to update the internal timestamp |
| 223 | * This also updates the running time ticks for the given thread and | 258 | * This also updates the running time ticks for the given thread and |
| @@ -231,14 +266,24 @@ private: | |||
| 231 | */ | 266 | */ |
| 232 | void UpdateLastContextSwitchTime(Thread* thread, Process* process); | 267 | void UpdateLastContextSwitchTime(Thread* thread, Process* process); |
| 233 | 268 | ||
| 269 | static void OnSwitch(void* this_scheduler); | ||
| 270 | void SwitchToCurrent(); | ||
| 271 | |||
| 234 | std::shared_ptr<Thread> current_thread = nullptr; | 272 | std::shared_ptr<Thread> current_thread = nullptr; |
| 235 | std::shared_ptr<Thread> selected_thread = nullptr; | 273 | std::shared_ptr<Thread> selected_thread = nullptr; |
| 274 | std::shared_ptr<Thread> current_thread_prev = nullptr; | ||
| 275 | std::shared_ptr<Thread> selected_thread_set = nullptr; | ||
| 276 | std::shared_ptr<Thread> idle_thread = nullptr; | ||
| 277 | |||
| 278 | std::shared_ptr<Common::Fiber> switch_fiber = nullptr; | ||
| 236 | 279 | ||
| 237 | Core::System& system; | 280 | Core::System& system; |
| 238 | u64 last_context_switch_time = 0; | 281 | u64 last_context_switch_time = 0; |
| 239 | u64 idle_selection_count = 0; | 282 | u64 idle_selection_count = 0; |
| 240 | const std::size_t core_id; | 283 | const std::size_t core_id; |
| 241 | 284 | ||
| 285 | Common::SpinLock guard{}; | ||
| 286 | |||
| 242 | bool is_context_switch_pending = false; | 287 | bool is_context_switch_pending = false; |
| 243 | }; | 288 | }; |
| 244 | 289 | ||
| @@ -261,6 +306,8 @@ public: | |||
| 261 | sleep_cancelled = true; | 306 | sleep_cancelled = true; |
| 262 | } | 307 | } |
| 263 | 308 | ||
| 309 | void Release(); | ||
| 310 | |||
| 264 | private: | 311 | private: |
| 265 | Handle& event_handle; | 312 | Handle& event_handle; |
| 266 | Thread* time_task; | 313 | Thread* time_task; |