summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp58
1 files changed, 45 insertions, 13 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index be9743d9f..a24641399 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -118,6 +118,50 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
return RESULT_SUCCESS;
}
+/// Default thread wakeup callback for WaitSynchronization
+static void DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread,
+ SharedPtr<WaitObject> object) {
+ ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
+
+ if (reason == ThreadWakeupReason::Timeout) {
+ thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
+ return;
+ }
+
+ ASSERT(reason == ThreadWakeupReason::Signal);
+ thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
+};
+
+/// Wait for a kernel object to synchronize, timeout after the specified nanoseconds
+static ResultCode WaitSynchronization1(
+ SharedPtr<WaitObject> object, Thread* thread, s64 nano_seconds = -1,
+ std::function<Thread::WakeupCallback> wakeup_callback = DefaultThreadWakeupCallback) {
+
+ if (!object) {
+ return ERR_INVALID_HANDLE;
+ }
+
+ if (object->ShouldWait(thread)) {
+ if (nano_seconds == 0) {
+ return RESULT_TIMEOUT;
+ }
+
+ thread->wait_objects = {object};
+ object->AddWaitingThread(thread);
+ thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
+
+ // Create an event to wake the thread up after the specified nanosecond delay has passed
+ thread->WakeAfterDelay(nano_seconds);
+ thread->wakeup_callback = wakeup_callback;
+
+ Core::System::GetInstance().PrepareReschedule();
+ } else {
+ object->Acquire(thread);
+ }
+
+ return RESULT_SUCCESS;
+}
+
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronization(VAddr handles_address, u64 handle_count, s64 nano_seconds) {
LOG_WARNING(Kernel_SVC,
@@ -147,19 +191,7 @@ static ResultCode LockMutex(Handle holding_thread_handle, VAddr mutex_addr,
mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
}
- if (mutex->ShouldWait(requesting_thread.get())) {
- // If we cannot lock the mutex, then put the thread too sleep and trigger a reschedule
- requesting_thread->wait_objects = {mutex};
- mutex->AddWaitingThread(requesting_thread);
- requesting_thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
-
- Core::System::GetInstance().PrepareReschedule();
- } else {
- // The mutex is available, lock it
- mutex->Acquire(requesting_thread.get());
- }
-
- return RESULT_SUCCESS;
+ return WaitSynchronization1(mutex, requesting_thread.get());
}
/// Unlock a mutex