mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-30 07:29:02 -05:00 
			
		
		
		
	Kernel: Implement Scheduler locks
This commit is contained in:
		 Fernando Sahmkow
					Fernando Sahmkow
				
			
				
					committed by
					
						 FernandoS27
						FernandoS27
					
				
			
			
				
	
			
			
			 FernandoS27
						FernandoS27
					
				
			
						parent
						
							5c90d22f3d
						
					
				
				
					commit
					ea956c823e
				
			| @@ -18,6 +18,7 @@ | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/scheduler.h" | ||||
| #include "core/hle/kernel/time_manager.h" | ||||
|  | ||||
| namespace Kernel { | ||||
|  | ||||
| @@ -356,6 +357,29 @@ void GlobalScheduler::Shutdown() { | ||||
|     thread_list.clear(); | ||||
| } | ||||
|  | ||||
| void GlobalScheduler::Lock() { | ||||
|     Core::EmuThreadHandle current_thread = kernel.GetCurrentEmuThreadId(); | ||||
|     if (current_thread == current_owner) { | ||||
|         ++scope_lock; | ||||
|     } else { | ||||
|         inner_lock.lock(); | ||||
|         current_owner = current_thread; | ||||
|         scope_lock = 1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void GlobalScheduler::Unlock() { | ||||
|     if (--scope_lock == 0) { | ||||
|         for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { | ||||
|             SelectThread(i); | ||||
|         } | ||||
|         current_owner = Core::EmuThreadHandle::InvalidHandle(); | ||||
|         scope_lock = 1; | ||||
|         inner_lock.unlock(); | ||||
|         // TODO(Blinkhawk): Setup the interrupts and change context on current core. | ||||
|     } | ||||
| } | ||||
|  | ||||
| Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) | ||||
|     : system(system), cpu_core(cpu_core), core_id(core_id) {} | ||||
|  | ||||
| @@ -485,4 +509,28 @@ void Scheduler::Shutdown() { | ||||
|     selected_thread = nullptr; | ||||
| } | ||||
|  | ||||
| SchedulerLock::SchedulerLock(KernelCore& kernel) : kernel{kernel} { | ||||
|     auto& global_scheduler = kernel.GlobalScheduler(); | ||||
|     global_scheduler.Lock(); | ||||
| } | ||||
|  | ||||
| SchedulerLock::~SchedulerLock() { | ||||
|     auto& global_scheduler = kernel.GlobalScheduler(); | ||||
|     global_scheduler.Unlock(); | ||||
| } | ||||
|  | ||||
| SchedulerLockAndSleep::SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, | ||||
|                                              Thread* time_task, s64 nanoseconds) | ||||
|     : SchedulerLock{kernel}, event_handle{event_handle}, time_task{time_task}, nanoseconds{ | ||||
|                                                                                    nanoseconds} { | ||||
|     event_handle = InvalidHandle; | ||||
| } | ||||
|  | ||||
| SchedulerLockAndSleep::~SchedulerLockAndSleep() { | ||||
|     if (!sleep_cancelled) { | ||||
|         auto& time_manager = kernel.TimeManager(); | ||||
|         time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds); | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace Kernel | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
|  | ||||
| #include <atomic> | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
| #include <vector> | ||||
|  | ||||
| #include "common/common_types.h" | ||||
| @@ -22,6 +23,7 @@ namespace Kernel { | ||||
|  | ||||
| class KernelCore; | ||||
| class Process; | ||||
| class SchedulerLock; | ||||
|  | ||||
| class GlobalScheduler final { | ||||
| public: | ||||
| @@ -139,6 +141,14 @@ public: | ||||
|     void Shutdown(); | ||||
|  | ||||
| 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(); | ||||
|     /** | ||||
|      * Transfers a thread into an specific core. If the destination_core is -1 | ||||
|      * it will be unscheduled from its source code and added into its suggested | ||||
| @@ -159,6 +169,11 @@ private: | ||||
|     // ordered from Core 0 to Core 3. | ||||
|     std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62}; | ||||
|  | ||||
|     /// Scheduler lock mechanisms. | ||||
|     std::mutex inner_lock{}; // TODO(Blinkhawk): Replace for a SpinLock | ||||
|     std::atomic<std::size_t> scope_lock{}; | ||||
|     Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()}; | ||||
|  | ||||
|     /// Lists all thread ids that aren't deleted/etc. | ||||
|     std::vector<std::shared_ptr<Thread>> thread_list; | ||||
|     KernelCore& kernel; | ||||
| @@ -228,4 +243,30 @@ private: | ||||
|     bool is_context_switch_pending = false; | ||||
| }; | ||||
|  | ||||
| class SchedulerLock { | ||||
| public: | ||||
|     SchedulerLock(KernelCore& kernel); | ||||
|     ~SchedulerLock(); | ||||
|  | ||||
| protected: | ||||
|     KernelCore& kernel; | ||||
| }; | ||||
|  | ||||
| class SchedulerLockAndSleep : public SchedulerLock { | ||||
| public: | ||||
|     SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, Thread* time_task, | ||||
|                           s64 nanoseconds); | ||||
|     ~SchedulerLockAndSleep(); | ||||
|  | ||||
|     void CancelSleep() { | ||||
|         sleep_cancelled = true; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     Handle& event_handle; | ||||
|     Thread* time_task; | ||||
|     s64 nanoseconds; | ||||
|     bool sleep_cancelled{}; | ||||
| }; | ||||
|  | ||||
| } // namespace Kernel | ||||
|   | ||||
		Reference in New Issue
	
	Block a user