summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/scheduler.cpp48
-rw-r--r--src/core/hle/kernel/scheduler.h41
2 files changed, 89 insertions, 0 deletions
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index 118c1aa95..9556df951 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -18,6 +18,7 @@
18#include "core/hle/kernel/kernel.h" 18#include "core/hle/kernel/kernel.h"
19#include "core/hle/kernel/process.h" 19#include "core/hle/kernel/process.h"
20#include "core/hle/kernel/scheduler.h" 20#include "core/hle/kernel/scheduler.h"
21#include "core/hle/kernel/time_manager.h"
21 22
22namespace Kernel { 23namespace Kernel {
23 24
@@ -356,6 +357,29 @@ void GlobalScheduler::Shutdown() {
356 thread_list.clear(); 357 thread_list.clear();
357} 358}
358 359
360void GlobalScheduler::Lock() {
361 Core::EmuThreadHandle current_thread = kernel.GetCurrentEmuThreadId();
362 if (current_thread == current_owner) {
363 ++scope_lock;
364 } else {
365 inner_lock.lock();
366 current_owner = current_thread;
367 scope_lock = 1;
368 }
369}
370
371void GlobalScheduler::Unlock() {
372 if (--scope_lock == 0) {
373 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
374 SelectThread(i);
375 }
376 current_owner = Core::EmuThreadHandle::InvalidHandle();
377 scope_lock = 1;
378 inner_lock.unlock();
379 // TODO(Blinkhawk): Setup the interrupts and change context on current core.
380 }
381}
382
359Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) 383Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id)
360 : system(system), cpu_core(cpu_core), core_id(core_id) {} 384 : system(system), cpu_core(cpu_core), core_id(core_id) {}
361 385
@@ -485,4 +509,28 @@ void Scheduler::Shutdown() {
485 selected_thread = nullptr; 509 selected_thread = nullptr;
486} 510}
487 511
512SchedulerLock::SchedulerLock(KernelCore& kernel) : kernel{kernel} {
513 auto& global_scheduler = kernel.GlobalScheduler();
514 global_scheduler.Lock();
515}
516
517SchedulerLock::~SchedulerLock() {
518 auto& global_scheduler = kernel.GlobalScheduler();
519 global_scheduler.Unlock();
520}
521
522SchedulerLockAndSleep::SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle,
523 Thread* time_task, s64 nanoseconds)
524 : SchedulerLock{kernel}, event_handle{event_handle}, time_task{time_task}, nanoseconds{
525 nanoseconds} {
526 event_handle = InvalidHandle;
527}
528
529SchedulerLockAndSleep::~SchedulerLockAndSleep() {
530 if (!sleep_cancelled) {
531 auto& time_manager = kernel.TimeManager();
532 time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds);
533 }
534}
535
488} // namespace Kernel 536} // namespace Kernel
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index 283236d4c..a779bb70f 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -6,6 +6,7 @@
6 6
7#include <atomic> 7#include <atomic>
8#include <memory> 8#include <memory>
9#include <mutex>
9#include <vector> 10#include <vector>
10 11
11#include "common/common_types.h" 12#include "common/common_types.h"
@@ -22,6 +23,7 @@ namespace Kernel {
22 23
23class KernelCore; 24class KernelCore;
24class Process; 25class Process;
26class SchedulerLock;
25 27
26class GlobalScheduler final { 28class GlobalScheduler final {
27public: 29public:
@@ -139,6 +141,14 @@ public:
139 void Shutdown(); 141 void Shutdown();
140 142
141private: 143private:
144 friend class SchedulerLock;
145
146 /// Lock the scheduler to the current thread.
147 void Lock();
148
149 /// Unlocks the scheduler, reselects threads, interrupts cores for rescheduling
150 /// and reschedules current core if needed.
151 void Unlock();
142 /** 152 /**
143 * Transfers a thread into an specific core. If the destination_core is -1 153 * Transfers a thread into an specific core. If the destination_core is -1
144 * it will be unscheduled from its source code and added into its suggested 154 * it will be unscheduled from its source code and added into its suggested
@@ -159,6 +169,11 @@ private:
159 // ordered from Core 0 to Core 3. 169 // ordered from Core 0 to Core 3.
160 std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62}; 170 std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62};
161 171
172 /// Scheduler lock mechanisms.
173 std::mutex inner_lock{}; // TODO(Blinkhawk): Replace for a SpinLock
174 std::atomic<std::size_t> scope_lock{};
175 Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()};
176
162 /// Lists all thread ids that aren't deleted/etc. 177 /// Lists all thread ids that aren't deleted/etc.
163 std::vector<std::shared_ptr<Thread>> thread_list; 178 std::vector<std::shared_ptr<Thread>> thread_list;
164 KernelCore& kernel; 179 KernelCore& kernel;
@@ -228,4 +243,30 @@ private:
228 bool is_context_switch_pending = false; 243 bool is_context_switch_pending = false;
229}; 244};
230 245
246class SchedulerLock {
247public:
248 SchedulerLock(KernelCore& kernel);
249 ~SchedulerLock();
250
251protected:
252 KernelCore& kernel;
253};
254
255class SchedulerLockAndSleep : public SchedulerLock {
256public:
257 SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, Thread* time_task,
258 s64 nanoseconds);
259 ~SchedulerLockAndSleep();
260
261 void CancelSleep() {
262 sleep_cancelled = true;
263 }
264
265private:
266 Handle& event_handle;
267 Thread* time_task;
268 s64 nanoseconds;
269 bool sleep_cancelled{};
270};
271
231} // namespace Kernel 272} // namespace Kernel