summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2018-01-09 15:02:43 -0500
committerGravatar Subv2018-01-09 15:02:43 -0500
commitc2ee513d353f1a66317b0632d10a148c784dde6e (patch)
tree3905470b9439bd8088dc8d5416c2e5363d3f931c /src
parentSVC: Implemented CancelSynchronization. (diff)
downloadyuzu-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.cpp25
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