summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar Subv2018-01-08 11:35:03 -0500
committerGravatar bunnei2018-01-08 21:12:49 -0500
commit2a3f8e8484fca54767c9874cc21f5985d2be1463 (patch)
tree0976e02e0b495f07b11a51811618199d791d4c4e /src/core/hle/kernel/svc.cpp
parentcmake: Use LIBUNICORN_* on Windows. (diff)
downloadyuzu-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.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) {
120} 120}
121 121
122/// Default thread wakeup callback for WaitSynchronization 122/// Default thread wakeup callback for WaitSynchronization
123static void DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread, 123static 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