summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorSubv <subv2112@gmail.com>2018-01-08 17:35:03 +0100
committerbunnei <bunneidev@gmail.com>2018-01-09 03:12:49 +0100
commit2a3f8e8484fca54767c9874cc21f5985d2be1463 (patch)
tree0976e02e0b495f07b11a51811618199d791d4c4e /src/core/hle/kernel/svc.cpp
parentcmake: Use LIBUNICORN_* on Windows. (diff)
downloadyuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar
yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar.gz
yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar.bz2
yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar.lz
yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar.xz
yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar.zst
yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.zip
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/svc.cpp56
1 files changed, 41 insertions, 15 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 74643f598..73793955a 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -120,17 +120,19 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
}
/// Default thread wakeup callback for WaitSynchronization
-static void DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread,
- SharedPtr<WaitObject> object) {
+static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread,
+ SharedPtr<WaitObject> object, size_t index) {
ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
if (reason == ThreadWakeupReason::Timeout) {
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
- return;
+ return true;
}
ASSERT(reason == ThreadWakeupReason::Signal);
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
+
+ return true;
};
/// Wait for a kernel object to synchronize, timeout after the specified nanoseconds
@@ -499,20 +501,44 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_add
ASSERT(semaphore->available_count == 0);
ASSERT(semaphore->mutex_addr == mutex_addr);
- CASCADE_CODE(WaitSynchronization1(
- semaphore, thread.get(), nano_seconds,
- [mutex](ThreadWakeupReason reason, SharedPtr<Thread> thread, SharedPtr<WaitObject> object) {
- ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
+ auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason,
+ SharedPtr<Thread> thread,
+ SharedPtr<WaitObject> object, size_t index) {
+ ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
+
+ if (reason == ThreadWakeupReason::Timeout) {
+ thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
+ return true;
+ }
+
+ ASSERT(reason == ThreadWakeupReason::Signal);
+
+ // Now try to acquire the mutex and don't resume if it's not available.
+ if (!mutex->ShouldWait(thread.get())) {
+ mutex->Acquire(thread.get());
+ thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
+ return true;
+ }
- if (reason == ThreadWakeupReason::Timeout) {
- thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
- return;
- }
+ if (nano_seconds == 0) {
+ thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
+ return true;
+ }
+
+ thread->wait_objects = {mutex};
+ mutex->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 = DefaultThreadWakeupCallback;
+
+ Core::System::GetInstance().PrepareReschedule();
- ASSERT(reason == ThreadWakeupReason::Signal);
- thread->SetWaitSynchronizationResult(WaitSynchronization1(mutex, thread.get()));
- thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get()));
- }));
+ return false;
+ };
+ CASCADE_CODE(WaitSynchronization1(semaphore, thread.get(), nano_seconds, wakeup_callback));
mutex->Release(thread.get());