From c2ee513d353f1a66317b0632d10a148c784dde6e Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 9 Jan 2018 15:02:43 -0500 Subject: SVC: Fixed WaitSynchronization with multiple handles when none is immediately ready. --- src/core/hle/kernel/svc.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index b7cad2248..bfe1907e3 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -131,7 +131,7 @@ static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtrSetWaitSynchronizationResult(RESULT_SUCCESS); - + thread->SetWaitSynchronizationOutput(static_cast(index)); return true; }; @@ -174,9 +174,10 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 if (!Memory::IsValidVirtualAddress(handles_address)) return ERR_INVALID_POINTER; - // Check if 'handle_count' is invalid - if (handle_count < 0) - return ERR_OUT_OF_RANGE; + static constexpr u64 MaxHandles = 0x40; + + if (handle_count > MaxHandles) + return ResultCode(ErrorModule::Kernel, ErrCodes::TooLarge); auto thread = GetCurrentThread(); @@ -211,9 +212,19 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 if (nano_seconds == 0) return RESULT_TIMEOUT; - // Just implement for a single handle for now - ASSERT(handle_count == 1); - return WaitSynchronization1(objects[0], GetCurrentThread(), nano_seconds); + for (auto& object : objects) + object->AddWaitingThread(thread); + + thread->wait_objects = std::move(objects); + thread->status = THREADSTATUS_WAIT_SYNCH_ANY; + + // Create an event to wake the thread up after the specified nanosecond delay has passed + thread->WakeAfterDelay(nano_seconds); + thread->wakeup_callback = DefaultThreadWakeupCallback; + + Core::System::GetInstance().PrepareReschedule(); + + return RESULT_TIMEOUT; } /// Resumes a thread waiting on WaitSynchronization -- cgit v1.2.3