Просмотр исходного кода

SVC: Fixed WaitSynchronization with multiple handles when at least one of them is ready.

Subv 8 лет назад
Родитель
Сommit
8d9250fa70
2 измененных файлов с 29 добавлено и 3 удалено
  1. 24 1
      src/core/hle/kernel/svc.cpp
  2. 5 2
      src/core/hle/kernel/svc_wrap.h

+ 24 - 1
src/core/hle/kernel/svc.cpp

@@ -166,7 +166,8 @@ static ResultCode WaitSynchronization1(
 }
 }
 
 
 /// Wait for the given handles to synchronize, timeout after the specified nanoseconds
 /// Wait for the given handles to synchronize, timeout after the specified nanoseconds
-static ResultCode WaitSynchronization(VAddr handles_address, u64 handle_count, s64 nano_seconds) {
+static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count,
+                                      s64 nano_seconds) {
     LOG_TRACE(Kernel_SVC, "called handles_address=0x%llx, handle_count=%d, nano_seconds=%d",
     LOG_TRACE(Kernel_SVC, "called handles_address=0x%llx, handle_count=%d, nano_seconds=%d",
               handles_address, handle_count, nano_seconds);
               handles_address, handle_count, nano_seconds);
 
 
@@ -177,6 +178,8 @@ static ResultCode WaitSynchronization(VAddr handles_address, u64 handle_count, s
     if (handle_count < 0)
     if (handle_count < 0)
         return ERR_OUT_OF_RANGE;
         return ERR_OUT_OF_RANGE;
 
 
+    auto thread = GetCurrentThread();
+
     using ObjectPtr = SharedPtr<WaitObject>;
     using ObjectPtr = SharedPtr<WaitObject>;
     std::vector<ObjectPtr> objects(handle_count);
     std::vector<ObjectPtr> objects(handle_count);
 
 
@@ -188,6 +191,26 @@ static ResultCode WaitSynchronization(VAddr handles_address, u64 handle_count, s
         objects[i] = object;
         objects[i] = object;
     }
     }
 
 
+    // Find the first object that is acquirable in the provided list of objects
+    auto itr = std::find_if(objects.begin(), objects.end(), [thread](const ObjectPtr& object) {
+        return !object->ShouldWait(thread);
+    });
+
+    if (itr != objects.end()) {
+        // We found a ready object, acquire it and set the result value
+        WaitObject* object = itr->get();
+        object->Acquire(thread);
+        *index = static_cast<s32>(std::distance(objects.begin(), itr));
+        return RESULT_SUCCESS;
+    }
+
+    // No objects were ready to be acquired, prepare to suspend the thread.
+
+    // If a timeout value of 0 was provided, just return the Timeout error code instead of
+    // suspending the thread.
+    if (nano_seconds == 0)
+        return RESULT_TIMEOUT;
+
     // Just implement for a single handle for now
     // Just implement for a single handle for now
     ASSERT(handle_count == 1);
     ASSERT(handle_count == 1);
     return WaitSynchronization1(objects[0], GetCurrentThread(), nano_seconds);
     return WaitSynchronization1(objects[0], GetCurrentThread(), nano_seconds);

+ 5 - 2
src/core/hle/kernel/svc_wrap.h

@@ -80,9 +80,12 @@ void SvcWrap() {
     FuncReturn(func(PARAM(0), PARAM(1), PARAM(2)).raw);
     FuncReturn(func(PARAM(0), PARAM(1), PARAM(2)).raw);
 }
 }
 
 
-template <ResultCode func(u64, u64, s64)>
+template <ResultCode func(u32*, u64, u64, s64)>
 void SvcWrap() {
 void SvcWrap() {
-    FuncReturn(func(PARAM(1), PARAM(2), (s64)PARAM(3)).raw);
+    u32 param_1 = 0;
+    ResultCode retval = func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3));
+    Core::CPU().SetReg(1, param_1);
+    FuncReturn(retval.raw);
 }
 }
 
 
 template <ResultCode func(u64, u64, u32, s64)>
 template <ResultCode func(u64, u64, u32, s64)>