mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 08:59:03 -06: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:
		@@ -55,10 +55,16 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
 | 
			
		||||
        if (ShouldWait(thread.get()))
 | 
			
		||||
            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) {
 | 
			
		||||
                                            return object->ShouldWait(thread.get());
 | 
			
		||||
                                        });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (ready_to_run) {
 | 
			
		||||
            candidate = thread.get();
 | 
			
		||||
            candidate_priority = thread->current_priority;
 | 
			
		||||
 
 | 
			
		||||
@@ -579,6 +579,11 @@ void Thread::SetWaitSynchronizationOutput(s32 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() {
 | 
			
		||||
 
 | 
			
		||||
@@ -135,13 +135,14 @@ public:
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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.
 | 
			
		||||
     * 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.
 | 
			
		||||
     */
 | 
			
		||||
    s32 GetWaitObjectIndex(const WaitObject* object) const {
 | 
			
		||||
        return wait_objects_index.at(object->GetObjectId());
 | 
			
		||||
    }
 | 
			
		||||
    s32 GetWaitObjectIndex(WaitObject* object) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Stops a thread, invalidating it from further use
 | 
			
		||||
@@ -190,13 +191,10 @@ public:
 | 
			
		||||
 | 
			
		||||
    SharedPtr<Process> owner_process; ///< Process that owns this thread
 | 
			
		||||
 | 
			
		||||
    /// Objects that the thread is waiting on.
 | 
			
		||||
    /// This is only populated when the thread should wait for all the objects to become ready.
 | 
			
		||||
    /// Objects that the thread is waiting on, in the same order as they were
 | 
			
		||||
    // passed to WaitSynchronization1/N.
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    /// 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)
 | 
			
		||||
            return ERR_SYNC_TIMEOUT;
 | 
			
		||||
 | 
			
		||||
        thread->wait_objects = {object};
 | 
			
		||||
        object->AddWaitingThread(thread);
 | 
			
		||||
        thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
 | 
			
		||||
 | 
			
		||||
@@ -325,11 +326,6 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
 | 
			
		||||
        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) {
 | 
			
		||||
        bool all_available =
 | 
			
		||||
            std::all_of(objects.begin(), objects.end(),
 | 
			
		||||
@@ -358,7 +354,6 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
 | 
			
		||||
            object->AddWaitingThread(thread);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Set the thread's waitlist to the list of objects passed to WaitSynchronizationN
 | 
			
		||||
        thread->wait_objects = std::move(objects);
 | 
			
		||||
 | 
			
		||||
        // 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
 | 
			
		||||
        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.
 | 
			
		||||
        for (size_t i = 0; i < objects.size(); ++i) {
 | 
			
		||||
            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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        thread->wait_objects = std::move(objects);
 | 
			
		||||
 | 
			
		||||
        // Note: If no handles and no timeout were given, then the thread will deadlock, this is
 | 
			
		||||
        // consistent with hardware behavior.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user