forked from eden-emu/eden
		
	scheduler: Only work steal higher priority threads from other cores
This commit is contained in:
		
							parent
							
								
									9caabad517
								
							
						
					
					
						commit
						5d50fa0824
					
				
					 3 changed files with 24 additions and 35 deletions
				
			
		|  | @ -170,16 +170,6 @@ void Scheduler::UnscheduleThread(Thread* thread, u32 priority) { | ||||||
|     ready_queue.remove(priority, thread); |     ready_queue.remove(priority, thread); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Scheduler::MoveThreadToBackOfPriorityQueue(Thread* thread, u32 priority) { |  | ||||||
|     std::lock_guard<std::mutex> 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) { | void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { | ||||||
|     std::lock_guard<std::mutex> lock(scheduler_mutex); |     std::lock_guard<std::mutex> lock(scheduler_mutex); | ||||||
| 
 | 
 | ||||||
|  | @ -190,12 +180,13 @@ void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { | ||||||
|         ready_queue.prepare(priority); |         ready_queue.prepare(priority); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Thread* Scheduler::GetNextSuggestedThread(u32 core) const { | Thread* Scheduler::GetNextSuggestedThread(u32 core, u32 maximum_priority) const { | ||||||
|     std::lock_guard<std::mutex> lock(scheduler_mutex); |     std::lock_guard<std::mutex> lock(scheduler_mutex); | ||||||
| 
 | 
 | ||||||
|     const u32 mask = 1U << core; |     const u32 mask = 1U << core; | ||||||
|     return ready_queue.get_first_filter( |     return ready_queue.get_first_filter([mask, maximum_priority](Thread const* thread) { | ||||||
|         [mask](Thread const* thread) { return (thread->GetAffinityMask() & mask) != 0; }); |         return (thread->GetAffinityMask() & mask) != 0 && thread->GetPriority() < maximum_priority; | ||||||
|  |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Scheduler::YieldWithoutLoadBalancing(Thread* thread) { | void Scheduler::YieldWithoutLoadBalancing(Thread* thread) { | ||||||
|  | @ -206,9 +197,10 @@ void Scheduler::YieldWithoutLoadBalancing(Thread* thread) { | ||||||
|     // Sanity check that the priority is valid
 |     // Sanity check that the priority is valid
 | ||||||
|     ASSERT(thread->GetPriority() < THREADPRIO_COUNT); |     ASSERT(thread->GetPriority() < THREADPRIO_COUNT); | ||||||
| 
 | 
 | ||||||
|     // Yield this thread
 |     // Yield this thread -- sleep for zero time and force reschedule to different thread
 | ||||||
|  |     WaitCurrentThread_Sleep(); | ||||||
|  |     GetCurrentThread()->WakeAfterDelay(0); | ||||||
|     Reschedule(); |     Reschedule(); | ||||||
|     MoveThreadToBackOfPriorityQueue(thread, thread->GetPriority()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Scheduler::YieldWithLoadBalancing(Thread* thread) { | void Scheduler::YieldWithLoadBalancing(Thread* thread) { | ||||||
|  | @ -222,9 +214,9 @@ void Scheduler::YieldWithLoadBalancing(Thread* thread) { | ||||||
|     // Sanity check that the priority is valid
 |     // Sanity check that the priority is valid
 | ||||||
|     ASSERT(priority < THREADPRIO_COUNT); |     ASSERT(priority < THREADPRIO_COUNT); | ||||||
| 
 | 
 | ||||||
|     // Reschedule thread to end of queue.
 |     // Sleep for zero time to be able to force reschedule to different thread
 | ||||||
|     Reschedule(); |     WaitCurrentThread_Sleep(); | ||||||
|     MoveThreadToBackOfPriorityQueue(thread, priority); |     GetCurrentThread()->WakeAfterDelay(0); | ||||||
| 
 | 
 | ||||||
|     Thread* suggested_thread = nullptr; |     Thread* suggested_thread = nullptr; | ||||||
| 
 | 
 | ||||||
|  | @ -235,16 +227,20 @@ void Scheduler::YieldWithLoadBalancing(Thread* thread) { | ||||||
|             continue; |             continue; | ||||||
| 
 | 
 | ||||||
|         const auto res = |         const auto res = | ||||||
|             Core::System::GetInstance().CpuCore(cur_core).Scheduler().GetNextSuggestedThread(core); |             Core::System::GetInstance().CpuCore(cur_core).Scheduler().GetNextSuggestedThread( | ||||||
|         if (res != nullptr) { |                 core, priority); | ||||||
|  |         if (res != nullptr && | ||||||
|  |             (suggested_thread == nullptr || suggested_thread->GetPriority() > res->GetPriority())) { | ||||||
|             suggested_thread = res; |             suggested_thread = res; | ||||||
|             break; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // If a suggested thread was found, queue that for this core
 |     // If a suggested thread was found, queue that for this core
 | ||||||
|     if (suggested_thread != nullptr) |     if (suggested_thread != nullptr) | ||||||
|         suggested_thread->ChangeCore(core, suggested_thread->GetAffinityMask()); |         suggested_thread->ChangeCore(core, suggested_thread->GetAffinityMask()); | ||||||
|  | 
 | ||||||
|  |     // Perform actual yielding.
 | ||||||
|  |     Reschedule(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Scheduler::YieldAndWaitForLoadBalancing(Thread* thread) { | void Scheduler::YieldAndWaitForLoadBalancing(Thread* thread) { | ||||||
|  |  | ||||||
|  | @ -48,14 +48,11 @@ public: | ||||||
|     /// Unschedules a thread that was already scheduled
 |     /// Unschedules a thread that was already scheduled
 | ||||||
|     void UnscheduleThread(Thread* thread, u32 priority); |     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
 |     /// Sets the priority of a thread in the scheduler
 | ||||||
|     void SetThreadPriority(Thread* thread, u32 priority); |     void SetThreadPriority(Thread* thread, u32 priority); | ||||||
| 
 | 
 | ||||||
|     /// Gets the next suggested thread for load balancing
 |     /// Gets the next suggested thread for load balancing
 | ||||||
|     Thread* GetNextSuggestedThread(u32 core) const; |     Thread* GetNextSuggestedThread(u32 core, u32 minimum_priority) const; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * YieldWithoutLoadBalancing -- analogous to normal yield on a system |      * YieldWithoutLoadBalancing -- analogous to normal yield on a system | ||||||
|  |  | ||||||
|  | @ -984,19 +984,15 @@ static void SleepThread(s64 nanoseconds) { | ||||||
|             scheduler.YieldAndWaitForLoadBalancing(GetCurrentThread()); |             scheduler.YieldAndWaitForLoadBalancing(GetCurrentThread()); | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             UNREACHABLE_MSG( |             UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); | ||||||
|                 "Unimplemented sleep yield type '{:016X}'! Falling back to forced reschedule...", |  | ||||||
|                 nanoseconds); |  | ||||||
|         } |         } | ||||||
| 
 |     } else { | ||||||
|         nanoseconds = 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|         // Sleep current thread and check for next thread to schedule
 |         // Sleep current thread and check for next thread to schedule
 | ||||||
|         WaitCurrentThread_Sleep(); |         WaitCurrentThread_Sleep(); | ||||||
| 
 | 
 | ||||||
|         // Create an event to wake the thread up after the specified nanosecond delay has passed
 |         // Create an event to wake the thread up after the specified nanosecond delay has passed
 | ||||||
|         GetCurrentThread()->WakeAfterDelay(nanoseconds); |         GetCurrentThread()->WakeAfterDelay(nanoseconds); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     Core::System::GetInstance().PrepareReschedule(); |     Core::System::GetInstance().PrepareReschedule(); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Zach Hilman
						Zach Hilman