mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Thread: Remove the idle thread
Instead just use nullptr to represent no thread is active.
This commit is contained in:
		
							parent
							
								
									10eb8b0c02
								
							
						
					
					
						commit
						4f7a055081
					
				
					 3 changed files with 21 additions and 46 deletions
				
			
		|  | @ -24,9 +24,9 @@ ARM_Interface*     g_sys_core = nullptr;  ///< ARM11 system (OS) core | ||||||
| 
 | 
 | ||||||
| /// Run the core CPU loop
 | /// Run the core CPU loop
 | ||||||
| void RunLoop(int tight_loop) { | void RunLoop(int tight_loop) { | ||||||
|     // If the current thread is an idle thread, then don't execute instructions,
 |     // If we don't have a currently active thread then don't execute instructions,
 | ||||||
|     // instead advance to the next event and try to yield to the next thread
 |     // instead advance to the next event and try to yield to the next thread
 | ||||||
|     if (Kernel::GetCurrentThread()->IsIdle()) { |     if (Kernel::GetCurrentThread() == nullptr) { | ||||||
|         LOG_TRACE(Core_ARM11, "Idling"); |         LOG_TRACE(Core_ARM11, "Idling"); | ||||||
|         CoreTiming::Idle(); |         CoreTiming::Idle(); | ||||||
|         CoreTiming::Advance(); |         CoreTiming::Advance(); | ||||||
|  |  | ||||||
|  | @ -157,7 +157,7 @@ static void PriorityBoostStarvedThreads() { | ||||||
| 
 | 
 | ||||||
|         u64 delta = current_ticks - thread->last_running_ticks; |         u64 delta = current_ticks - thread->last_running_ticks; | ||||||
| 
 | 
 | ||||||
|         if (thread->status == THREADSTATUS_READY && delta > boost_timeout && !thread->idle) { |         if (thread->status == THREADSTATUS_READY && delta > boost_timeout) { | ||||||
|             const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0); |             const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0); | ||||||
|             thread->BoostPriority(priority); |             thread->BoostPriority(priority); | ||||||
|         } |         } | ||||||
|  | @ -169,8 +169,6 @@ static void PriorityBoostStarvedThreads() { | ||||||
|  * @param new_thread The thread to switch to |  * @param new_thread The thread to switch to | ||||||
|  */ |  */ | ||||||
| static void SwitchContext(Thread* new_thread) { | static void SwitchContext(Thread* new_thread) { | ||||||
|     DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); |  | ||||||
| 
 |  | ||||||
|     Thread* previous_thread = GetCurrentThread(); |     Thread* previous_thread = GetCurrentThread(); | ||||||
| 
 | 
 | ||||||
|     // Save context for previous thread
 |     // Save context for previous thread
 | ||||||
|  | @ -188,6 +186,8 @@ static void SwitchContext(Thread* new_thread) { | ||||||
| 
 | 
 | ||||||
|     // Load context of new thread
 |     // Load context of new thread
 | ||||||
|     if (new_thread) { |     if (new_thread) { | ||||||
|  |         DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); | ||||||
|  | 
 | ||||||
|         current_thread = new_thread; |         current_thread = new_thread; | ||||||
| 
 | 
 | ||||||
|         ready_queue.remove(new_thread->current_priority, new_thread); |         ready_queue.remove(new_thread->current_priority, new_thread); | ||||||
|  | @ -215,6 +215,10 @@ static Thread* PopNextReadyThread() { | ||||||
|         // We have to do better than the current thread.
 |         // We have to do better than the current thread.
 | ||||||
|         // This call returns null when that's not possible.
 |         // This call returns null when that's not possible.
 | ||||||
|         next = ready_queue.pop_first_better(thread->current_priority); |         next = ready_queue.pop_first_better(thread->current_priority); | ||||||
|  |         if (!next) { | ||||||
|  |             // Otherwise just keep going with the current thread
 | ||||||
|  |             next = thread; | ||||||
|  |         } | ||||||
|     } else  { |     } else  { | ||||||
|         next = ready_queue.pop_first(); |         next = ready_queue.pop_first(); | ||||||
|     } |     } | ||||||
|  | @ -448,16 +452,6 @@ void Thread::BoostPriority(s32 priority) { | ||||||
|     current_priority = priority; |     current_priority = priority; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| SharedPtr<Thread> SetupIdleThread() { |  | ||||||
|     // We need to pass a few valid values to get around parameter checking in Thread::Create.
 |  | ||||||
|     // TODO(yuriks): Figure out a way to avoid passing the bogus VAddr parameter
 |  | ||||||
|     auto thread = Thread::Create("idle", Memory::TLS_AREA_VADDR, THREADPRIO_LOWEST, 0, |  | ||||||
|             THREADPROCESSORID_0, 0).MoveFrom(); |  | ||||||
| 
 |  | ||||||
|     thread->idle = true; |  | ||||||
|     return thread; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { | SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { | ||||||
|     DEBUG_ASSERT(!GetCurrentThread()); |     DEBUG_ASSERT(!GetCurrentThread()); | ||||||
| 
 | 
 | ||||||
|  | @ -474,24 +468,25 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Reschedule() { | void Reschedule() { | ||||||
|     Thread* prev = GetCurrentThread(); |  | ||||||
| 
 |  | ||||||
|     PriorityBoostStarvedThreads(); |     PriorityBoostStarvedThreads(); | ||||||
| 
 | 
 | ||||||
|  |     Thread* cur = GetCurrentThread(); | ||||||
|     Thread* next = PopNextReadyThread(); |     Thread* next = PopNextReadyThread(); | ||||||
|     HLE::g_reschedule = false; |     HLE::g_reschedule = false; | ||||||
| 
 | 
 | ||||||
|     if (next != nullptr) { |     // Don't bother switching to the same thread
 | ||||||
|         LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId()); |     if (next == cur) | ||||||
|         SwitchContext(next); |         return; | ||||||
|     } else { |  | ||||||
|         LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId()); |  | ||||||
| 
 | 
 | ||||||
|         for (auto& thread : thread_list) { |     if (cur && next) { | ||||||
|             LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(),  |         LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId()); | ||||||
|                       thread->current_priority, thread->status); |     } else if (cur) { | ||||||
|         } |         LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId()); | ||||||
|  |     } else { | ||||||
|  |         LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId()); | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     SwitchContext(next); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Thread::SetWaitSynchronizationResult(ResultCode result) { | void Thread::SetWaitSynchronizationResult(ResultCode result) { | ||||||
|  | @ -516,9 +511,6 @@ void ThreadingInit() { | ||||||
| 
 | 
 | ||||||
|     thread_list.clear(); |     thread_list.clear(); | ||||||
|     ready_queue.clear(); |     ready_queue.clear(); | ||||||
| 
 |  | ||||||
|     // Setup the idle thread
 |  | ||||||
|     SetupIdleThread(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ThreadingShutdown() { | void ThreadingShutdown() { | ||||||
|  |  | ||||||
|  | @ -71,12 +71,6 @@ public: | ||||||
|     bool ShouldWait() override; |     bool ShouldWait() override; | ||||||
|     void Acquire() override; |     void Acquire() override; | ||||||
| 
 | 
 | ||||||
|     /**
 |  | ||||||
|      * Checks if the thread is an idle (stub) thread |  | ||||||
|      * @return True if the thread is an idle (stub) thread, false otherwise |  | ||||||
|      */ |  | ||||||
|     inline bool IsIdle() const { return idle; } |  | ||||||
| 
 |  | ||||||
|     /**
 |     /**
 | ||||||
|      * Gets the thread's current priority |      * Gets the thread's current priority | ||||||
|      * @return The current thread's priority |      * @return The current thread's priority | ||||||
|  | @ -168,9 +162,6 @@ public: | ||||||
| 
 | 
 | ||||||
|     std::string name; |     std::string name; | ||||||
| 
 | 
 | ||||||
|     /// Whether this thread is intended to never actually be executed, i.e. always idle
 |  | ||||||
|     bool idle = false; |  | ||||||
| 
 |  | ||||||
| private: | private: | ||||||
|     Thread(); |     Thread(); | ||||||
|     ~Thread() override; |     ~Thread() override; | ||||||
|  | @ -228,14 +219,6 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa | ||||||
|  */ |  */ | ||||||
| void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * Sets up the idle thread, this is a thread that is intended to never execute instructions, |  | ||||||
|  * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue |  | ||||||
|  * and will try to yield on every call. |  | ||||||
|  * @return The handle of the idle thread |  | ||||||
|  */ |  | ||||||
| SharedPtr<Thread> SetupIdleThread(); |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * Initialize threading |  * Initialize threading | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue