summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/svc.cpp25
-rw-r--r--src/core/hle/kernel/svc_wrap.h7
2 files changed, 29 insertions, 3 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(
}
/// 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",
handles_address, handle_count, nano_seconds);
@@ -177,6 +178,8 @@ static ResultCode WaitSynchronization(VAddr handles_address, u64 handle_count, s
if (handle_count < 0)
return ERR_OUT_OF_RANGE;
+ auto thread = GetCurrentThread();
+
using ObjectPtr = SharedPtr<WaitObject>;
std::vector<ObjectPtr> objects(handle_count);
@@ -188,6 +191,26 @@ static ResultCode WaitSynchronization(VAddr handles_address, u64 handle_count, s
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
ASSERT(handle_count == 1);
return WaitSynchronization1(objects[0], GetCurrentThread(), nano_seconds);
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index bffa2f7f8..16c834cf3 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -80,9 +80,12 @@ void SvcWrap() {
FuncReturn(func(PARAM(0), PARAM(1), PARAM(2)).raw);
}
-template <ResultCode func(u64, u64, s64)>
+template <ResultCode func(u32*, u64, u64, s64)>
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)>