diff options
| author | 2018-01-09 15:02:43 -0500 | |
|---|---|---|
| committer | 2018-01-09 15:02:43 -0500 | |
| commit | c2ee513d353f1a66317b0632d10a148c784dde6e (patch) | |
| tree | 3905470b9439bd8088dc8d5416c2e5363d3f931c /src | |
| parent | SVC: Implemented CancelSynchronization. (diff) | |
| download | yuzu-c2ee513d353f1a66317b0632d10a148c784dde6e.tar.gz yuzu-c2ee513d353f1a66317b0632d10a148c784dde6e.tar.xz yuzu-c2ee513d353f1a66317b0632d10a148c784dde6e.zip | |
SVC: Fixed WaitSynchronization with multiple handles when none is immediately ready.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 25 |
1 files changed, 18 insertions, 7 deletions
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, SharedPtr<Thr | |||
| 131 | 131 | ||
| 132 | ASSERT(reason == ThreadWakeupReason::Signal); | 132 | ASSERT(reason == ThreadWakeupReason::Signal); |
| 133 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | 133 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); |
| 134 | 134 | thread->SetWaitSynchronizationOutput(static_cast<u32>(index)); | |
| 135 | return true; | 135 | return true; |
| 136 | }; | 136 | }; |
| 137 | 137 | ||
| @@ -174,9 +174,10 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 | |||
| 174 | if (!Memory::IsValidVirtualAddress(handles_address)) | 174 | if (!Memory::IsValidVirtualAddress(handles_address)) |
| 175 | return ERR_INVALID_POINTER; | 175 | return ERR_INVALID_POINTER; |
| 176 | 176 | ||
| 177 | // Check if 'handle_count' is invalid | 177 | static constexpr u64 MaxHandles = 0x40; |
| 178 | if (handle_count < 0) | 178 | |
| 179 | return ERR_OUT_OF_RANGE; | 179 | if (handle_count > MaxHandles) |
| 180 | return ResultCode(ErrorModule::Kernel, ErrCodes::TooLarge); | ||
| 180 | 181 | ||
| 181 | auto thread = GetCurrentThread(); | 182 | auto thread = GetCurrentThread(); |
| 182 | 183 | ||
| @@ -211,9 +212,19 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 | |||
| 211 | if (nano_seconds == 0) | 212 | if (nano_seconds == 0) |
| 212 | return RESULT_TIMEOUT; | 213 | return RESULT_TIMEOUT; |
| 213 | 214 | ||
| 214 | // Just implement for a single handle for now | 215 | for (auto& object : objects) |
| 215 | ASSERT(handle_count == 1); | 216 | object->AddWaitingThread(thread); |
| 216 | return WaitSynchronization1(objects[0], GetCurrentThread(), nano_seconds); | 217 | |
| 218 | thread->wait_objects = std::move(objects); | ||
| 219 | thread->status = THREADSTATUS_WAIT_SYNCH_ANY; | ||
| 220 | |||
| 221 | // Create an event to wake the thread up after the specified nanosecond delay has passed | ||
| 222 | thread->WakeAfterDelay(nano_seconds); | ||
| 223 | thread->wakeup_callback = DefaultThreadWakeupCallback; | ||
| 224 | |||
| 225 | Core::System::GetInstance().PrepareReschedule(); | ||
| 226 | |||
| 227 | return RESULT_TIMEOUT; | ||
| 217 | } | 228 | } |
| 218 | 229 | ||
| 219 | /// Resumes a thread waiting on WaitSynchronization | 230 | /// Resumes a thread waiting on WaitSynchronization |