mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Kernel: Remove Thread::wait_objects_index and use wait_objects to hold all the objects that a thread is waiting on.
This commit is contained in:
		
							parent
							
								
									cef5f45de2
								
							
						
					
					
						commit
						fd95b6ee26
					
				
					 4 changed files with 22 additions and 21 deletions
				
			
		|  | @ -55,10 +55,16 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { | ||||||
|         if (ShouldWait(thread.get())) |         if (ShouldWait(thread.get())) | ||||||
|             continue; |             continue; | ||||||
| 
 | 
 | ||||||
|         bool ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(), |         // A thread is ready to run if it's either in THREADSTATUS_WAIT_SYNCH_ANY or
 | ||||||
|  |         // in THREADSTATUS_WAIT_SYNCH_ALL and the rest of the objects it is waiting on are ready.
 | ||||||
|  |         bool ready_to_run = true; | ||||||
|  |         if (thread->status == THREADSTATUS_WAIT_SYNCH_ALL) { | ||||||
|  |             ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(), | ||||||
|                                         [&thread](const SharedPtr<WaitObject>& object) { |                                         [&thread](const SharedPtr<WaitObject>& object) { | ||||||
|                                             return object->ShouldWait(thread.get()); |                                             return object->ShouldWait(thread.get()); | ||||||
|                                         }); |                                         }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if (ready_to_run) { |         if (ready_to_run) { | ||||||
|             candidate = thread.get(); |             candidate = thread.get(); | ||||||
|             candidate_priority = thread->current_priority; |             candidate_priority = thread->current_priority; | ||||||
|  |  | ||||||
|  | @ -579,6 +579,11 @@ void Thread::SetWaitSynchronizationOutput(s32 output) { | ||||||
|     context.cpu_registers[1] = output; |     context.cpu_registers[1] = output; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | s32 Thread::GetWaitObjectIndex(WaitObject* object) const { | ||||||
|  |     auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object); | ||||||
|  |     return std::distance(match, wait_objects.rend()) - 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
| void ThreadingInit() { | void ThreadingInit() { | ||||||
|  |  | ||||||
|  | @ -135,13 +135,14 @@ public: | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Retrieves the index that this particular object occupies in the list of objects |      * Retrieves the index that this particular object occupies in the list of objects | ||||||
|      * that the thread passed to WaitSynchronizationN. |      * that the thread passed to WaitSynchronizationN, starting the search from the last element. | ||||||
|      * It is used to set the output value of WaitSynchronizationN when the thread is awakened. |      * It is used to set the output value of WaitSynchronizationN when the thread is awakened. | ||||||
|  |      * When a thread wakes up due to an object signal, the kernel will use the index of the last | ||||||
|  |      * matching object in the wait objects list in case of having multiple instances of the same | ||||||
|  |      * object in the list. | ||||||
|      * @param object Object to query the index of. |      * @param object Object to query the index of. | ||||||
|      */ |      */ | ||||||
|     s32 GetWaitObjectIndex(const WaitObject* object) const { |     s32 GetWaitObjectIndex(WaitObject* object) const; | ||||||
|         return wait_objects_index.at(object->GetObjectId()); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Stops a thread, invalidating it from further use |      * Stops a thread, invalidating it from further use | ||||||
|  | @ -190,13 +191,10 @@ public: | ||||||
| 
 | 
 | ||||||
|     SharedPtr<Process> owner_process; ///< Process that owns this thread
 |     SharedPtr<Process> owner_process; ///< Process that owns this thread
 | ||||||
| 
 | 
 | ||||||
|     /// Objects that the thread is waiting on.
 |     /// Objects that the thread is waiting on, in the same order as they were
 | ||||||
|     /// This is only populated when the thread should wait for all the objects to become ready.
 |     // passed to WaitSynchronization1/N.
 | ||||||
|     std::vector<SharedPtr<WaitObject>> wait_objects; |     std::vector<SharedPtr<WaitObject>> wait_objects; | ||||||
| 
 | 
 | ||||||
|     /// Mapping of Object ids to their position in the last waitlist that this object waited on.
 |  | ||||||
|     boost::container::flat_map<int, s32> wait_objects_index; |  | ||||||
| 
 |  | ||||||
|     VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
 |     VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
 | ||||||
| 
 | 
 | ||||||
|     /// True if the WaitSynchronizationN output parameter should be set on thread wakeup.
 |     /// True if the WaitSynchronizationN output parameter should be set on thread wakeup.
 | ||||||
|  |  | ||||||
|  | @ -277,6 +277,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) | ||||||
|         if (nano_seconds == 0) |         if (nano_seconds == 0) | ||||||
|             return ERR_SYNC_TIMEOUT; |             return ERR_SYNC_TIMEOUT; | ||||||
| 
 | 
 | ||||||
|  |         thread->wait_objects = {object}; | ||||||
|         object->AddWaitingThread(thread); |         object->AddWaitingThread(thread); | ||||||
|         thread->status = THREADSTATUS_WAIT_SYNCH_ANY; |         thread->status = THREADSTATUS_WAIT_SYNCH_ANY; | ||||||
| 
 | 
 | ||||||
|  | @ -325,11 +326,6 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha | ||||||
|         objects[i] = object; |         objects[i] = object; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Clear the mapping of wait object indices.
 |  | ||||||
|     // We don't want any lingering state in this map.
 |  | ||||||
|     // It will be repopulated later in the wait_all = false case.
 |  | ||||||
|     thread->wait_objects_index.clear(); |  | ||||||
| 
 |  | ||||||
|     if (wait_all) { |     if (wait_all) { | ||||||
|         bool all_available = |         bool all_available = | ||||||
|             std::all_of(objects.begin(), objects.end(), |             std::all_of(objects.begin(), objects.end(), | ||||||
|  | @ -358,7 +354,6 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha | ||||||
|             object->AddWaitingThread(thread); |             object->AddWaitingThread(thread); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Set the thread's waitlist to the list of objects passed to WaitSynchronizationN
 |  | ||||||
|         thread->wait_objects = std::move(objects); |         thread->wait_objects = std::move(objects); | ||||||
| 
 | 
 | ||||||
|         // 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
 | ||||||
|  | @ -395,17 +390,14 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha | ||||||
|         // Put the thread to sleep
 |         // Put the thread to sleep
 | ||||||
|         thread->status = THREADSTATUS_WAIT_SYNCH_ANY; |         thread->status = THREADSTATUS_WAIT_SYNCH_ANY; | ||||||
| 
 | 
 | ||||||
|         // Clear the thread's waitlist, we won't use it for wait_all = false
 |  | ||||||
|         thread->wait_objects.clear(); |  | ||||||
| 
 |  | ||||||
|         // Add the thread to each of the objects' waiting threads.
 |         // Add the thread to each of the objects' waiting threads.
 | ||||||
|         for (size_t i = 0; i < objects.size(); ++i) { |         for (size_t i = 0; i < objects.size(); ++i) { | ||||||
|             Kernel::WaitObject* object = objects[i].get(); |             Kernel::WaitObject* object = objects[i].get(); | ||||||
|             // Set the index of this object in the mapping of Objects -> index for this thread.
 |  | ||||||
|             thread->wait_objects_index[object->GetObjectId()] = static_cast<int>(i); |  | ||||||
|             object->AddWaitingThread(thread); |             object->AddWaitingThread(thread); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         thread->wait_objects = std::move(objects); | ||||||
|  | 
 | ||||||
|         // Note: If no handles and no timeout were given, then the thread will deadlock, this is
 |         // Note: If no handles and no timeout were given, then the thread will deadlock, this is
 | ||||||
|         // consistent with hardware behavior.
 |         // consistent with hardware behavior.
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue