mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Thread: Keep track of multiple wait objects.
This commit is contained in:
		
							parent
							
								
									14cbbf4d9b
								
							
						
					
					
						commit
						1f7a04f05a
					
				@ -15,7 +15,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Kernel {
 | 
					namespace Kernel {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AddressArbiter : public Object {
 | 
					class AddressArbiter : public WaitObject {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    std::string GetTypeName() const override { return "Arbiter"; }
 | 
					    std::string GetTypeName() const override { return "Arbiter"; }
 | 
				
			||||||
    std::string GetName() const override { return name; }
 | 
					    std::string GetName() const override { return name; }
 | 
				
			||||||
@ -30,7 +30,8 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Arbitrate an address
 | 
					/// Arbitrate an address
 | 
				
			||||||
ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) {
 | 
					ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) {
 | 
				
			||||||
    Object* object = Kernel::g_handle_table.GetGeneric(handle).get();
 | 
					    WaitObject* object = static_cast<WaitObject*>(Kernel::g_handle_table.GetGeneric(handle).get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (object == nullptr)
 | 
					    if (object == nullptr)
 | 
				
			||||||
        return InvalidHandle(ErrorModule::Kernel);
 | 
					        return InvalidHandle(ErrorModule::Kernel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -65,7 +65,7 @@ static void ResetThread(Thread* t, u32 arg, s32 lowest_priority) {
 | 
				
			|||||||
        t->current_priority = t->initial_priority;
 | 
					        t->current_priority = t->initial_priority;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    t->wait_type = WAITTYPE_NONE;
 | 
					    t->wait_type = WAITTYPE_NONE;
 | 
				
			||||||
    t->wait_object = nullptr;
 | 
					    t->wait_objects.clear();
 | 
				
			||||||
    t->wait_address = 0;
 | 
					    t->wait_address = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -92,7 +92,11 @@ static bool CheckWaitType(const Thread* thread, WaitType type) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Check if a thread is blocking on a specified wait type with a specified handle
 | 
					/// Check if a thread is blocking on a specified wait type with a specified handle
 | 
				
			||||||
static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object) {
 | 
					static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object) {
 | 
				
			||||||
    return CheckWaitType(thread, type) && wait_object == thread->wait_object;
 | 
					    auto itr = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object);
 | 
				
			||||||
 | 
					    if (itr == thread->wait_objects.end()) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return CheckWaitType(thread, type);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Check if a thread is blocking on a specified wait type with a specified handle and address
 | 
					/// Check if a thread is blocking on a specified wait type with a specified handle and address
 | 
				
			||||||
@ -111,7 +115,7 @@ void Thread::Stop(const char* reason) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Stopped threads are never waiting.
 | 
					    // Stopped threads are never waiting.
 | 
				
			||||||
    wait_type = WAITTYPE_NONE;
 | 
					    wait_type = WAITTYPE_NONE;
 | 
				
			||||||
    wait_object = nullptr;
 | 
					    wait_objects.clear();
 | 
				
			||||||
    wait_address = 0;
 | 
					    wait_address = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -216,14 +220,18 @@ static Thread* NextThread() {
 | 
				
			|||||||
    return next;
 | 
					    return next;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WaitCurrentThread(WaitType wait_type, Object* wait_object) {
 | 
					void WaitCurrentThread(WaitType wait_type, WaitObject* wait_object) {
 | 
				
			||||||
    Thread* thread = GetCurrentThread();
 | 
					    Thread* thread = GetCurrentThread();
 | 
				
			||||||
    thread->wait_type = wait_type;
 | 
					    thread->wait_type = wait_type;
 | 
				
			||||||
    thread->wait_object = wait_object;
 | 
					
 | 
				
			||||||
 | 
					    auto res = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object);
 | 
				
			||||||
 | 
					    if (res == thread->wait_objects.end()) {
 | 
				
			||||||
 | 
					        thread->wait_objects.push_back(wait_object);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));
 | 
					    ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WaitCurrentThread(WaitType wait_type, Object* wait_object, VAddr wait_address) {
 | 
					void WaitCurrentThread(WaitType wait_type, WaitObject* wait_object, VAddr wait_address) {
 | 
				
			||||||
    WaitCurrentThread(wait_type, wait_object);
 | 
					    WaitCurrentThread(wait_type, wait_object);
 | 
				
			||||||
    GetCurrentThread()->wait_address = wait_address;
 | 
					    GetCurrentThread()->wait_address = wait_address;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -260,7 +268,13 @@ void Thread::ResumeFromWait() {
 | 
				
			|||||||
    CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle());
 | 
					    CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    status &= ~THREADSTATUS_WAIT;
 | 
					    status &= ~THREADSTATUS_WAIT;
 | 
				
			||||||
    wait_object = nullptr;
 | 
					
 | 
				
			||||||
 | 
					    // Remove this thread from all other WaitObjects
 | 
				
			||||||
 | 
					    for (auto wait_object : wait_objects)
 | 
				
			||||||
 | 
					        wait_object->RemoveWaitingThread(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wait_objects.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wait_type = WAITTYPE_NONE;
 | 
					    wait_type = WAITTYPE_NONE;
 | 
				
			||||||
    if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
 | 
					    if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
 | 
				
			||||||
        ChangeReadyState(this, true);
 | 
					        ChangeReadyState(this, true);
 | 
				
			||||||
@ -328,7 +342,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
 | 
				
			|||||||
    thread->initial_priority = thread->current_priority = priority;
 | 
					    thread->initial_priority = thread->current_priority = priority;
 | 
				
			||||||
    thread->processor_id = processor_id;
 | 
					    thread->processor_id = processor_id;
 | 
				
			||||||
    thread->wait_type = WAITTYPE_NONE;
 | 
					    thread->wait_type = WAITTYPE_NONE;
 | 
				
			||||||
    thread->wait_object = nullptr;
 | 
					    thread->wait_objects.clear();
 | 
				
			||||||
    thread->wait_address = 0;
 | 
					    thread->wait_address = 0;
 | 
				
			||||||
    thread->name = std::move(name);
 | 
					    thread->name = std::move(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -412,9 +426,8 @@ void Reschedule() {
 | 
				
			|||||||
        LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle());
 | 
					        LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (auto& thread : thread_list) {
 | 
					        for (auto& thread : thread_list) {
 | 
				
			||||||
            LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X",
 | 
					            LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X",
 | 
				
			||||||
                thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type,
 | 
					                thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type);
 | 
				
			||||||
                (thread->wait_object ? thread->wait_object->GetHandle() : INVALID_HANDLE));
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -96,7 +96,7 @@ public:
 | 
				
			|||||||
    s32 processor_id;
 | 
					    s32 processor_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WaitType wait_type;
 | 
					    WaitType wait_type;
 | 
				
			||||||
    Object* wait_object;
 | 
					    std::vector<SharedPtr<WaitObject>> wait_objects;
 | 
				
			||||||
    VAddr wait_address;
 | 
					    VAddr wait_address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string name;
 | 
					    std::string name;
 | 
				
			||||||
@ -128,7 +128,7 @@ Thread* GetCurrentThread();
 | 
				
			|||||||
 * @param wait_type Type of wait
 | 
					 * @param wait_type Type of wait
 | 
				
			||||||
 * @param wait_object Kernel object that we are waiting on, defaults to current thread
 | 
					 * @param wait_object Kernel object that we are waiting on, defaults to current thread
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void WaitCurrentThread(WaitType wait_type, Object* wait_object = GetCurrentThread());
 | 
					void WaitCurrentThread(WaitType wait_type, WaitObject* wait_object = GetCurrentThread());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Schedules an event to wake up the specified thread after the specified delay.
 | 
					 * Schedules an event to wake up the specified thread after the specified delay.
 | 
				
			||||||
@ -143,7 +143,7 @@ void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds);
 | 
				
			|||||||
 * @param wait_object Kernel object that we are waiting on
 | 
					 * @param wait_object Kernel object that we are waiting on
 | 
				
			||||||
 * @param wait_address Arbitration address used to resume from wait
 | 
					 * @param wait_address Arbitration address used to resume from wait
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void WaitCurrentThread(WaitType wait_type, Object* wait_object, VAddr wait_address);
 | 
					void WaitCurrentThread(WaitType wait_type, WaitObject* wait_object, VAddr wait_address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user