diff options
| author | 2018-01-08 11:35:03 -0500 | |
|---|---|---|
| committer | 2018-01-08 21:12:49 -0500 | |
| commit | 2a3f8e8484fca54767c9874cc21f5985d2be1463 (patch) | |
| tree | 0976e02e0b495f07b11a51811618199d791d4c4e /src/core/hle/kernel/svc.cpp | |
| parent | cmake: Use LIBUNICORN_* on Windows. (diff) | |
| download | yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar.gz yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar.xz yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.zip | |
Kernel: Allow chaining WaitSynchronization calls inside a wakeup callback.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 56 |
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) { | |||
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | /// Default thread wakeup callback for WaitSynchronization | 122 | /// Default thread wakeup callback for WaitSynchronization |
| 123 | static void DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread, | 123 | static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread, |
| 124 | SharedPtr<WaitObject> object) { | 124 | SharedPtr<WaitObject> object, size_t index) { |
| 125 | ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); | 125 | ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); |
| 126 | 126 | ||
| 127 | if (reason == ThreadWakeupReason::Timeout) { | 127 | if (reason == ThreadWakeupReason::Timeout) { |
| 128 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | 128 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); |
| 129 | return; | 129 | return true; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | ASSERT(reason == ThreadWakeupReason::Signal); | 132 | ASSERT(reason == ThreadWakeupReason::Signal); |
| 133 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | 133 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); |
| 134 | |||
| 135 | return true; | ||
| 134 | }; | 136 | }; |
| 135 | 137 | ||
| 136 | /// Wait for a kernel object to synchronize, timeout after the specified nanoseconds | 138 | /// 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 | |||
| 499 | ASSERT(semaphore->available_count == 0); | 501 | ASSERT(semaphore->available_count == 0); |
| 500 | ASSERT(semaphore->mutex_addr == mutex_addr); | 502 | ASSERT(semaphore->mutex_addr == mutex_addr); |
| 501 | 503 | ||
| 502 | CASCADE_CODE(WaitSynchronization1( | 504 | auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason, |
| 503 | semaphore, thread.get(), nano_seconds, | 505 | SharedPtr<Thread> thread, |
| 504 | [mutex](ThreadWakeupReason reason, SharedPtr<Thread> thread, SharedPtr<WaitObject> object) { | 506 | SharedPtr<WaitObject> object, size_t index) { |
| 505 | ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); | 507 | ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); |
| 508 | |||
| 509 | if (reason == ThreadWakeupReason::Timeout) { | ||
| 510 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | ||
| 511 | return true; | ||
| 512 | } | ||
| 513 | |||
| 514 | ASSERT(reason == ThreadWakeupReason::Signal); | ||
| 515 | |||
| 516 | // Now try to acquire the mutex and don't resume if it's not available. | ||
| 517 | if (!mutex->ShouldWait(thread.get())) { | ||
| 518 | mutex->Acquire(thread.get()); | ||
| 519 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||
| 520 | return true; | ||
| 521 | } | ||
| 506 | 522 | ||
| 507 | if (reason == ThreadWakeupReason::Timeout) { | 523 | if (nano_seconds == 0) { |
| 508 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | 524 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); |
| 509 | return; | 525 | return true; |
| 510 | } | 526 | } |
| 527 | |||
| 528 | thread->wait_objects = {mutex}; | ||
| 529 | mutex->AddWaitingThread(thread); | ||
| 530 | thread->status = THREADSTATUS_WAIT_SYNCH_ANY; | ||
| 531 | |||
| 532 | // Create an event to wake the thread up after the | ||
| 533 | // specified nanosecond delay has passed | ||
| 534 | thread->WakeAfterDelay(nano_seconds); | ||
| 535 | thread->wakeup_callback = DefaultThreadWakeupCallback; | ||
| 536 | |||
| 537 | Core::System::GetInstance().PrepareReschedule(); | ||
| 511 | 538 | ||
| 512 | ASSERT(reason == ThreadWakeupReason::Signal); | 539 | return false; |
| 513 | thread->SetWaitSynchronizationResult(WaitSynchronization1(mutex, thread.get())); | 540 | }; |
| 514 | thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get())); | 541 | CASCADE_CODE(WaitSynchronization1(semaphore, thread.get(), nano_seconds, wakeup_callback)); |
| 515 | })); | ||
| 516 | 542 | ||
| 517 | mutex->Release(thread.get()); | 543 | mutex->Release(thread.get()); |
| 518 | 544 | ||