diff options
| author | 2020-02-11 17:36:39 -0400 | |
|---|---|---|
| committer | 2020-02-11 18:47:31 -0400 | |
| commit | d23d504d776007c1244a85ac1b7bb67c407067b2 (patch) | |
| tree | d6e992004bf752819084d648ca8b81fd1fc1db18 /src/core/hle/kernel/svc.cpp | |
| parent | Kernel: Change WaitObject to Synchronization object. In order to better refle... (diff) | |
| download | yuzu-d23d504d776007c1244a85ac1b7bb67c407067b2.tar.gz yuzu-d23d504d776007c1244a85ac1b7bb67c407067b2.tar.xz yuzu-d23d504d776007c1244a85ac1b7bb67c407067b2.zip | |
Kernel: Refactor synchronization to better match RE
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 67 |
1 files changed, 7 insertions, 60 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 39552a176..86c660cdf 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "core/hle/kernel/shared_memory.h" | 32 | #include "core/hle/kernel/shared_memory.h" |
| 33 | #include "core/hle/kernel/svc.h" | 33 | #include "core/hle/kernel/svc.h" |
| 34 | #include "core/hle/kernel/svc_wrap.h" | 34 | #include "core/hle/kernel/svc_wrap.h" |
| 35 | #include "core/hle/kernel/synchronization.h" | ||
| 35 | #include "core/hle/kernel/thread.h" | 36 | #include "core/hle/kernel/thread.h" |
| 36 | #include "core/hle/kernel/transfer_memory.h" | 37 | #include "core/hle/kernel/transfer_memory.h" |
| 37 | #include "core/hle/kernel/writable_event.h" | 38 | #include "core/hle/kernel/writable_event.h" |
| @@ -433,23 +434,6 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han | |||
| 433 | return ERR_INVALID_HANDLE; | 434 | return ERR_INVALID_HANDLE; |
| 434 | } | 435 | } |
| 435 | 436 | ||
| 436 | /// Default thread wakeup callback for WaitSynchronization | ||
| 437 | static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, | ||
| 438 | std::shared_ptr<SynchronizationObject> object, | ||
| 439 | std::size_t index) { | ||
| 440 | ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); | ||
| 441 | |||
| 442 | if (reason == ThreadWakeupReason::Timeout) { | ||
| 443 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | ||
| 444 | return true; | ||
| 445 | } | ||
| 446 | |||
| 447 | ASSERT(reason == ThreadWakeupReason::Signal); | ||
| 448 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||
| 449 | thread->SetWaitSynchronizationOutput(static_cast<u32>(index)); | ||
| 450 | return true; | ||
| 451 | }; | ||
| 452 | |||
| 453 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 437 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| 454 | static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, | 438 | static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, |
| 455 | u64 handle_count, s64 nano_seconds) { | 439 | u64 handle_count, s64 nano_seconds) { |
| @@ -473,10 +457,10 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr | |||
| 473 | } | 457 | } |
| 474 | 458 | ||
| 475 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); | 459 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); |
| 476 | 460 | auto& kernel = system.Kernel(); | |
| 477 | using ObjectPtr = Thread::ThreadSynchronizationObjects::value_type; | 461 | using ObjectPtr = Thread::ThreadSynchronizationObjects::value_type; |
| 478 | Thread::ThreadSynchronizationObjects objects(handle_count); | 462 | Thread::ThreadSynchronizationObjects objects(handle_count); |
| 479 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 463 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 480 | 464 | ||
| 481 | for (u64 i = 0; i < handle_count; ++i) { | 465 | for (u64 i = 0; i < handle_count; ++i) { |
| 482 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); | 466 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); |
| @@ -489,47 +473,10 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr | |||
| 489 | 473 | ||
| 490 | objects[i] = object; | 474 | objects[i] = object; |
| 491 | } | 475 | } |
| 492 | 476 | auto& synchronization = kernel.Synchronization(); | |
| 493 | // Find the first object that is acquirable in the provided list of objects | 477 | auto [result, handle_result] = synchronization.WaitFor(objects, nano_seconds); |
| 494 | auto itr = std::find_if(objects.begin(), objects.end(), [thread](const ObjectPtr& object) { | 478 | *index = handle_result; |
| 495 | return !object->ShouldWait(thread); | 479 | return result; |
| 496 | }); | ||
| 497 | |||
| 498 | if (itr != objects.end()) { | ||
| 499 | // We found a ready object, acquire it and set the result value | ||
| 500 | SynchronizationObject* object = itr->get(); | ||
| 501 | object->Acquire(thread); | ||
| 502 | *index = static_cast<s32>(std::distance(objects.begin(), itr)); | ||
| 503 | return RESULT_SUCCESS; | ||
| 504 | } | ||
| 505 | |||
| 506 | // No objects were ready to be acquired, prepare to suspend the thread. | ||
| 507 | |||
| 508 | // If a timeout value of 0 was provided, just return the Timeout error code instead of | ||
| 509 | // suspending the thread. | ||
| 510 | if (nano_seconds == 0) { | ||
| 511 | return RESULT_TIMEOUT; | ||
| 512 | } | ||
| 513 | |||
| 514 | if (thread->IsSyncCancelled()) { | ||
| 515 | thread->SetSyncCancelled(false); | ||
| 516 | return ERR_SYNCHRONIZATION_CANCELED; | ||
| 517 | } | ||
| 518 | |||
| 519 | for (auto& object : objects) { | ||
| 520 | object->AddWaitingThread(SharedFrom(thread)); | ||
| 521 | } | ||
| 522 | |||
| 523 | thread->SetSynchronizationObjects(std::move(objects)); | ||
| 524 | thread->SetStatus(ThreadStatus::WaitSynch); | ||
| 525 | |||
| 526 | // Create an event to wake the thread up after the specified nanosecond delay has passed | ||
| 527 | thread->WakeAfterDelay(nano_seconds); | ||
| 528 | thread->SetWakeupCallback(DefaultThreadWakeupCallback); | ||
| 529 | |||
| 530 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 531 | |||
| 532 | return RESULT_TIMEOUT; | ||
| 533 | } | 480 | } |
| 534 | 481 | ||
| 535 | /// Resumes a thread waiting on WaitSynchronization | 482 | /// Resumes a thread waiting on WaitSynchronization |