diff options
Diffstat (limited to 'src/core/hle/svc.cpp')
| -rw-r--r-- | src/core/hle/svc.cpp | 69 |
1 files changed, 65 insertions, 4 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 41c82c922..fefd50805 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 | } |