summaryrefslogtreecommitdiff
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
authorGravatar Subv2017-09-28 11:53:32 -0500
committerGravatar Subv2017-09-28 11:53:32 -0500
commit8432749db7afecc9beea20f993cc036418caaa15 (patch)
tree10dd3fcd755bd7bdc27eef120885c7e700ab4288 /src/core/hle/svc.cpp
parentMerge pull request #2907 from Subv/warnings3 (diff)
downloadyuzu-8432749db7afecc9beea20f993cc036418caaa15.tar.gz
yuzu-8432749db7afecc9beea20f993cc036418caaa15.tar.xz
yuzu-8432749db7afecc9beea20f993cc036418caaa15.zip
Kernel/Threads: When putting a thread to wait, specify a function to execute when it is awoken.
This change makes for a clearer (less confusing) path of execution in the scheduler, now the code to execute when a thread awakes is closer to the code that puts the thread to sleep (WaitSynch1, WaitSynchN). It also allows us to implement the special wake up behavior of ReplyAndReceive without hacking up WaitObject::WakeupAllWaitingThreads. If savestates are desired in the future, we can change this implementation to one similar to the CoreTiming event system, where we first register the callback functions at startup and assign their identifiers to the Thread callback variable instead of directly assigning a lambda to the wake up callback variable.
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp69
1 files changed, 65 insertions, 4 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index dfc36748c..41e62cf62 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -271,6 +271,24 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
271 // Create an event to wake the thread up after the specified nanosecond delay has passed 271 // Create an event to wake the thread up after the specified nanosecond delay has passed
272 thread->WakeAfterDelay(nano_seconds); 272 thread->WakeAfterDelay(nano_seconds);
273 273
274 thread->wakeup_callback = [](ThreadWakeupReason reason,
275 Kernel::SharedPtr<Kernel::Thread> thread,
276 Kernel::SharedPtr<Kernel::WaitObject> object) {
277
278 ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
279
280 if (reason == ThreadWakeupReason::Timeout) {
281 thread->SetWaitSynchronizationResult(Kernel::RESULT_TIMEOUT);
282 return;
283 }
284
285 ASSERT(reason == ThreadWakeupReason::Signal);
286 thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
287
288 // WaitSynchronization1 doesn't have an output index like WaitSynchronizationN, so we
289 // don't have to do anything else here.
290 };
291
274 Core::System::GetInstance().PrepareReschedule(); 292 Core::System::GetInstance().PrepareReschedule();
275 293
276 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread 294 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread
@@ -344,6 +362,23 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
344 // Create an event to wake the thread up after the specified nanosecond delay has passed 362 // Create an event to wake the thread up after the specified nanosecond delay has passed
345 thread->WakeAfterDelay(nano_seconds); 363 thread->WakeAfterDelay(nano_seconds);
346 364
365 thread->wakeup_callback = [](ThreadWakeupReason reason,
366 Kernel::SharedPtr<Kernel::Thread> thread,
367 Kernel::SharedPtr<Kernel::WaitObject> object) {
368
369 ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ALL);
370
371 if (reason == ThreadWakeupReason::Timeout) {
372 thread->SetWaitSynchronizationResult(Kernel::RESULT_TIMEOUT);
373 return;
374 }
375
376 ASSERT(reason == ThreadWakeupReason::Signal);
377
378 thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
379 // The wait_all case does not update the output index.
380 };
381
347 Core::System::GetInstance().PrepareReschedule(); 382 Core::System::GetInstance().PrepareReschedule();
348 383
349 // This value gets set to -1 by default in this case, it is not modified after this. 384 // This value gets set to -1 by default in this case, it is not modified after this.
@@ -389,12 +424,28 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
389 // Create an event to wake the thread up after the specified nanosecond delay has passed 424 // Create an event to wake the thread up after the specified nanosecond delay has passed
390 thread->WakeAfterDelay(nano_seconds); 425 thread->WakeAfterDelay(nano_seconds);
391 426
427 thread->wakeup_callback = [](ThreadWakeupReason reason,
428 Kernel::SharedPtr<Kernel::Thread> thread,
429 Kernel::SharedPtr<Kernel::WaitObject> object) {
430
431 ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
432
433 if (reason == ThreadWakeupReason::Timeout) {
434 thread->SetWaitSynchronizationResult(Kernel::RESULT_TIMEOUT);
435 return;
436 }
437
438 ASSERT(reason == ThreadWakeupReason::Signal);
439
440 thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
441 thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get()));
442 };
443
392 Core::System::GetInstance().PrepareReschedule(); 444 Core::System::GetInstance().PrepareReschedule();
393 445
394 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a 446 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a
395 // signal in one of its wait objects. 447 // signal in one of its wait objects.
396 // Otherwise we retain the default value of timeout, and -1 in the out parameter 448 // Otherwise we retain the default value of timeout, and -1 in the out parameter
397 thread->wait_set_output = true;
398 *out = -1; 449 *out = -1;
399 return Kernel::RESULT_TIMEOUT; 450 return Kernel::RESULT_TIMEOUT;
400 } 451 }
@@ -483,8 +534,6 @@ static ResultCode ReplyAndReceive(s32* index, Kernel::Handle* handles, s32 handl
483 534
484 // No objects were ready to be acquired, prepare to suspend the thread. 535 // No objects were ready to be acquired, prepare to suspend the thread.
485 536
486 // TODO(Subv): Perform IPC translation upon wakeup.
487
488 // Put the thread to sleep 537 // Put the thread to sleep
489 thread->status = THREADSTATUS_WAIT_SYNCH_ANY; 538 thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
490 539
@@ -496,12 +545,24 @@ static ResultCode ReplyAndReceive(s32* index, Kernel::Handle* handles, s32 handl
496 545
497 thread->wait_objects = std::move(objects); 546 thread->wait_objects = std::move(objects);
498 547
548 thread->wakeup_callback = [](ThreadWakeupReason reason,
549 Kernel::SharedPtr<Kernel::Thread> thread,
550 Kernel::SharedPtr<Kernel::WaitObject> object) {
551
552 ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
553 ASSERT(reason == ThreadWakeupReason::Signal);
554
555 thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
556 thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get()));
557
558 // TODO(Subv): Perform IPC translation upon wakeup.
559 };
560
499 Core::System::GetInstance().PrepareReschedule(); 561 Core::System::GetInstance().PrepareReschedule();
500 562
501 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a 563 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a
502 // signal in one of its wait objects, or to 0xC8A01836 if there was a translation error. 564 // signal in one of its wait objects, or to 0xC8A01836 if there was a translation error.
503 // By default the index is set to -1. 565 // By default the index is set to -1.
504 thread->wait_set_output = true;
505 *index = -1; 566 *index = -1;
506 return RESULT_SUCCESS; 567 return RESULT_SUCCESS;
507} 568}