diff options
| author | 2020-02-14 14:40:20 -0500 | |
|---|---|---|
| committer | 2020-02-14 14:40:20 -0500 | |
| commit | f552d553bac1374c583d748dad27f8c86e86c4a0 (patch) | |
| tree | 1da4aa037ff417fa4fd43bffac267dcb2b55a72d /src/core/hle/kernel/svc.cpp | |
| parent | Merge pull request #3379 from ReinUsesLisp/cbuf-offset (diff) | |
| parent | Core: Correct compilition in GCC (diff) | |
| download | yuzu-f552d553bac1374c583d748dad27f8c86e86c4a0.tar.gz yuzu-f552d553bac1374c583d748dad27f8c86e86c4a0.tar.xz yuzu-f552d553bac1374c583d748dad27f8c86e86c4a0.zip | |
Merge pull request #3401 from FernandoS27/synchronization
Set of refactors for Kernel Synchronization and Hardware Constants
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 72 |
1 files changed, 10 insertions, 62 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9cae5c73d..fd91779a3 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,22 +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<WaitObject> object, std::size_t index) { | ||
| 439 | ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); | ||
| 440 | |||
| 441 | if (reason == ThreadWakeupReason::Timeout) { | ||
| 442 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | ||
| 443 | return true; | ||
| 444 | } | ||
| 445 | |||
| 446 | ASSERT(reason == ThreadWakeupReason::Signal); | ||
| 447 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||
| 448 | thread->SetWaitSynchronizationOutput(static_cast<u32>(index)); | ||
| 449 | return true; | ||
| 450 | }; | ||
| 451 | |||
| 452 | /// 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 |
| 453 | static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, | 438 | static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, |
| 454 | u64 handle_count, s64 nano_seconds) { | 439 | u64 handle_count, s64 nano_seconds) { |
| @@ -472,14 +457,14 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr | |||
| 472 | } | 457 | } |
| 473 | 458 | ||
| 474 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); | 459 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); |
| 475 | 460 | auto& kernel = system.Kernel(); | |
| 476 | using ObjectPtr = Thread::ThreadWaitObjects::value_type; | 461 | using ObjectPtr = Thread::ThreadSynchronizationObjects::value_type; |
| 477 | Thread::ThreadWaitObjects objects(handle_count); | 462 | Thread::ThreadSynchronizationObjects objects(handle_count); |
| 478 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 463 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 479 | 464 | ||
| 480 | for (u64 i = 0; i < handle_count; ++i) { | 465 | for (u64 i = 0; i < handle_count; ++i) { |
| 481 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); | 466 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); |
| 482 | const auto object = handle_table.Get<WaitObject>(handle); | 467 | const auto object = handle_table.Get<SynchronizationObject>(handle); |
| 483 | 468 | ||
| 484 | if (object == nullptr) { | 469 | if (object == nullptr) { |
| 485 | LOG_ERROR(Kernel_SVC, "Object is a nullptr"); | 470 | LOG_ERROR(Kernel_SVC, "Object is a nullptr"); |
| @@ -488,47 +473,10 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr | |||
| 488 | 473 | ||
| 489 | objects[i] = object; | 474 | objects[i] = object; |
| 490 | } | 475 | } |
| 491 | 476 | auto& synchronization = kernel.Synchronization(); | |
| 492 | // Find the first object that is acquirable in the provided list of objects | 477 | const auto [result, handle_result] = synchronization.WaitFor(objects, nano_seconds); |
| 493 | auto itr = std::find_if(objects.begin(), objects.end(), [thread](const ObjectPtr& object) { | 478 | *index = handle_result; |
| 494 | return !object->ShouldWait(thread); | 479 | return result; |
| 495 | }); | ||
| 496 | |||
| 497 | if (itr != objects.end()) { | ||
| 498 | // We found a ready object, acquire it and set the result value | ||
| 499 | WaitObject* object = itr->get(); | ||
| 500 | object->Acquire(thread); | ||
| 501 | *index = static_cast<s32>(std::distance(objects.begin(), itr)); | ||
| 502 | return RESULT_SUCCESS; | ||
| 503 | } | ||
| 504 | |||
| 505 | // No objects were ready to be acquired, prepare to suspend the thread. | ||
| 506 | |||
| 507 | // If a timeout value of 0 was provided, just return the Timeout error code instead of | ||
| 508 | // suspending the thread. | ||
| 509 | if (nano_seconds == 0) { | ||
| 510 | return RESULT_TIMEOUT; | ||
| 511 | } | ||
| 512 | |||
| 513 | if (thread->IsSyncCancelled()) { | ||
| 514 | thread->SetSyncCancelled(false); | ||
| 515 | return ERR_SYNCHRONIZATION_CANCELED; | ||
| 516 | } | ||
| 517 | |||
| 518 | for (auto& object : objects) { | ||
| 519 | object->AddWaitingThread(SharedFrom(thread)); | ||
| 520 | } | ||
| 521 | |||
| 522 | thread->SetWaitObjects(std::move(objects)); | ||
| 523 | thread->SetStatus(ThreadStatus::WaitSynch); | ||
| 524 | |||
| 525 | // Create an event to wake the thread up after the specified nanosecond delay has passed | ||
| 526 | thread->WakeAfterDelay(nano_seconds); | ||
| 527 | thread->SetWakeupCallback(DefaultThreadWakeupCallback); | ||
| 528 | |||
| 529 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 530 | |||
| 531 | return RESULT_TIMEOUT; | ||
| 532 | } | 480 | } |
| 533 | 481 | ||
| 534 | /// Resumes a thread waiting on WaitSynchronization | 482 | /// Resumes a thread waiting on WaitSynchronization |