summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar Subv2018-01-09 11:53:50 -0500
committerGravatar Subv2018-01-09 11:53:50 -0500
commit8d9250fa70af00b5f40a58b0729588616bef94fa (patch)
tree956a699769296b21a52f0fe0209ab0b969d0ec2c /src/core/hle/kernel/svc.cpp
parentkernel: Rename Semaphore to ConditionVariable. (diff)
downloadyuzu-8d9250fa70af00b5f40a58b0729588616bef94fa.tar.gz
yuzu-8d9250fa70af00b5f40a58b0729588616bef94fa.tar.xz
yuzu-8d9250fa70af00b5f40a58b0729588616bef94fa.zip
SVC: Fixed WaitSynchronization with multiple handles when at least one of them is ready.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp25
1 files changed, 24 insertions, 1 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index b94503536..c3280bfa3 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -166,7 +166,8 @@ static ResultCode WaitSynchronization1(
166} 166}
167 167
168/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 168/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
169static ResultCode WaitSynchronization(VAddr handles_address, u64 handle_count, s64 nano_seconds) { 169static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count,
170 s64 nano_seconds) {
170 LOG_TRACE(Kernel_SVC, "called handles_address=0x%llx, handle_count=%d, nano_seconds=%d", 171 LOG_TRACE(Kernel_SVC, "called handles_address=0x%llx, handle_count=%d, nano_seconds=%d",
171 handles_address, handle_count, nano_seconds); 172 handles_address, handle_count, nano_seconds);
172 173
@@ -177,6 +178,8 @@ static ResultCode WaitSynchronization(VAddr handles_address, u64 handle_count, s
177 if (handle_count < 0) 178 if (handle_count < 0)
178 return ERR_OUT_OF_RANGE; 179 return ERR_OUT_OF_RANGE;
179 180
181 auto thread = GetCurrentThread();
182
180 using ObjectPtr = SharedPtr<WaitObject>; 183 using ObjectPtr = SharedPtr<WaitObject>;
181 std::vector<ObjectPtr> objects(handle_count); 184 std::vector<ObjectPtr> objects(handle_count);
182 185
@@ -188,6 +191,26 @@ static ResultCode WaitSynchronization(VAddr handles_address, u64 handle_count, s
188 objects[i] = object; 191 objects[i] = object;
189 } 192 }
190 193
194 // Find the first object that is acquirable in the provided list of objects
195 auto itr = std::find_if(objects.begin(), objects.end(), [thread](const ObjectPtr& object) {
196 return !object->ShouldWait(thread);
197 });
198
199 if (itr != objects.end()) {
200 // We found a ready object, acquire it and set the result value
201 WaitObject* object = itr->get();
202 object->Acquire(thread);
203 *index = static_cast<s32>(std::distance(objects.begin(), itr));
204 return RESULT_SUCCESS;
205 }
206
207 // No objects were ready to be acquired, prepare to suspend the thread.
208
209 // If a timeout value of 0 was provided, just return the Timeout error code instead of
210 // suspending the thread.
211 if (nano_seconds == 0)
212 return RESULT_TIMEOUT;
213
191 // Just implement for a single handle for now 214 // Just implement for a single handle for now
192 ASSERT(handle_count == 1); 215 ASSERT(handle_count == 1);
193 return WaitSynchronization1(objects[0], GetCurrentThread(), nano_seconds); 216 return WaitSynchronization1(objects[0], GetCurrentThread(), nano_seconds);