summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-02-11 17:36:39 -0400
committerGravatar FernandoS272020-02-11 18:47:31 -0400
commitd23d504d776007c1244a85ac1b7bb67c407067b2 (patch)
treed6e992004bf752819084d648ca8b81fd1fc1db18 /src/core/hle/kernel/svc.cpp
parentKernel: Change WaitObject to Synchronization object. In order to better refle... (diff)
downloadyuzu-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.cpp67
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
437static 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
454static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, 438static 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