summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2020-02-14 14:40:20 -0500
committerGravatar GitHub2020-02-14 14:40:20 -0500
commitf552d553bac1374c583d748dad27f8c86e86c4a0 (patch)
tree1da4aa037ff417fa4fd43bffac267dcb2b55a72d /src/core/hle/kernel/svc.cpp
parentMerge pull request #3379 from ReinUsesLisp/cbuf-offset (diff)
parentCore: Correct compilition in GCC (diff)
downloadyuzu-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.cpp72
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
437static 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
453static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, 438static 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