From eba3c59a611962a1b019a5edfbc16c8d6db58be9 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 31 Jan 2021 16:55:11 -0800 Subject: [PATCH] hle: kernel: svc: Cleanup KEvent/KReadableEvent/KWritableEvent SVCs. --- src/core/hle/kernel/k_readable_event.cpp | 1 - src/core/hle/kernel/process.cpp | 19 ++- src/core/hle/kernel/process.h | 2 +- src/core/hle/kernel/svc.cpp | 149 +++++++++++++---------- src/core/hle/kernel/svc_results.h | 1 + 5 files changed, 96 insertions(+), 76 deletions(-) diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp index 0fa895c56..cd15aa529 100644 --- a/src/core/hle/kernel/k_readable_event.cpp +++ b/src/core/hle/kernel/k_readable_event.cpp @@ -49,7 +49,6 @@ ResultCode KReadableEvent::Reset() { R_UNLESS_NOLOG(is_signaled, Svc::ResultInvalidState); is_signaled = false; - return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index afdb27c54..2286b292d 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -23,6 +23,7 @@ #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/memory/slab_heap.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/svc_results.h" #include "core/hle/lock.h" #include "core/memory.h" #include "core/settings.h" @@ -241,18 +242,16 @@ void Process::UnregisterThread(const KThread* thread) { thread_list.remove(thread); } -ResultCode Process::ClearSignalState() { - KScopedSchedulerLock lock(system.Kernel()); - if (status == ProcessStatus::Exited) { - LOG_ERROR(Kernel, "called on a terminated process instance."); - return ERR_INVALID_STATE; - } +ResultCode Process::Reset() { + // Lock the process and the scheduler. + KScopedLightLock lk(state_lock); + KScopedSchedulerLock sl{kernel}; - if (!is_signaled) { - LOG_ERROR(Kernel, "called on a process instance that isn't signaled."); - return ERR_INVALID_STATE; - } + // Validate that we're in a state that we can reset. + R_UNLESS(status != ProcessStatus::Exited, Svc::ResultInvalidState); + R_UNLESS(is_signaled, Svc::ResultInvalidState); + // Clear signaled. is_signaled = false; return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index c8af76ce8..320b0f347 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -312,7 +312,7 @@ public: /// @pre The process must be in a signaled state. If this is called on a /// process instance that is not signaled, ERR_INVALID_STATE will be /// returned. - ResultCode ClearSignalState(); + ResultCode Reset(); /** * Loads process-specifics configuration info with metadata provided diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9d036f45d..edf208eff 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -14,6 +14,7 @@ #include "common/fiber.h" #include "common/logging/log.h" #include "common/microprofile.h" +#include "common/scope_exit.h" #include "common/string_util.h" #include "core/arm/exclusive_monitor.h" #include "core/core.h" @@ -1726,20 +1727,28 @@ static ResultCode CloseHandle32(Core::System& system, Handle handle) { static ResultCode ResetSignal(Core::System& system, Handle handle) { LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle); + // Get the current handle table. const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - auto event = handle_table.Get(handle); - if (event) { - return event->Reset(); + // Try to reset as readable event. + { + auto readable_event = handle_table.Get(handle); + if (readable_event) { + return readable_event->Reset(); + } } - auto process = handle_table.Get(handle); - if (process) { - return process->ClearSignalState(); + // Try to reset as process. + { + auto process = handle_table.Get(handle); + if (process) { + return process->Reset(); + } } - LOG_ERROR(Kernel_SVC, "Invalid handle (0x{:08X})", handle); - return ERR_INVALID_HANDLE; + LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle); + + return Svc::ResultInvalidHandle; } static ResultCode ResetSignal32(Core::System& system, Handle handle) { @@ -1867,80 +1876,92 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask); } -static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) { +static ResultCode SignalEvent(Core::System& system, Handle event_handle) { + LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); + + // Get the current handle table. + const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); + + // Get the writable event. + auto writable_event = handle_table.Get(event_handle); + R_UNLESS(writable_event, Svc::ResultInvalidHandle); + + return writable_event->Signal(); +} + +static ResultCode SignalEvent32(Core::System& system, Handle event_handle) { + return SignalEvent(system, event_handle); +} + +static ResultCode ClearEvent(Core::System& system, Handle event_handle) { + LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); + + // Get the current handle table. + const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); + + // Try to clear the writable event. + { + auto writable_event = handle_table.Get(event_handle); + if (writable_event) { + return writable_event->Clear(); + } + } + + // Try to clear the readable event. + { + auto readable_event = handle_table.Get(event_handle); + if (readable_event) { + return readable_event->Clear(); + } + } + + LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle); + + return Svc::ResultInvalidHandle; +} + +static ResultCode ClearEvent32(Core::System& system, Handle event_handle) { + return ClearEvent(system, event_handle); +} + +static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) { LOG_DEBUG(Kernel_SVC, "called"); + // Get the kernel reference and handle table. auto& kernel = system.Kernel(); - const auto event = KEvent::Create(kernel, "CreateEvent"); - event->Initialize(); - HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); + // Create a new event. + const auto event = KEvent::Create(kernel, "CreateEvent"); + R_UNLESS(event != nullptr, Svc::ResultOutOfResource); + + // Initialize the event. + event->Initialize(); + + // Add the writable event to the handle table. const auto write_create_result = handle_table.Create(event->GetWritableEvent()); if (write_create_result.Failed()) { return write_create_result.Code(); } - *write_handle = *write_create_result; + *out_write = *write_create_result; + // Add the writable event to the handle table. + auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); }); + + // Add the readable event to the handle table. const auto read_create_result = handle_table.Create(event->GetReadableEvent()); if (read_create_result.Failed()) { - handle_table.Close(*write_create_result); return read_create_result.Code(); } - *read_handle = *read_create_result; + *out_read = *read_create_result; - LOG_DEBUG(Kernel_SVC, - "successful. Writable event handle=0x{:08X}, Readable event handle=0x{:08X}", - *write_create_result, *read_create_result); + // We succeeded. + handle_guard.Cancel(); return RESULT_SUCCESS; } -static ResultCode CreateEvent32(Core::System& system, Handle* write_handle, Handle* read_handle) { - return CreateEvent(system, write_handle, read_handle); -} - -static ResultCode ClearEvent(Core::System& system, Handle handle) { - LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); - - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - - auto writable_event = handle_table.Get(handle); - if (writable_event) { - writable_event->Clear(); - return RESULT_SUCCESS; - } - - auto readable_event = handle_table.Get(handle); - if (readable_event) { - readable_event->Clear(); - return RESULT_SUCCESS; - } - - LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle); - return ERR_INVALID_HANDLE; -} - -static ResultCode ClearEvent32(Core::System& system, Handle handle) { - return ClearEvent(system, handle); -} - -static ResultCode SignalEvent(Core::System& system, Handle handle) { - LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle); - - HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - auto writable_event = handle_table.Get(handle); - - if (!writable_event) { - LOG_ERROR(Kernel_SVC, "Non-existent writable event handle used (0x{:08X})", handle); - return ERR_INVALID_HANDLE; - } - - writable_event->Signal(); - return RESULT_SUCCESS; -} - -static ResultCode SignalEvent32(Core::System& system, Handle handle) { - return SignalEvent(system, handle); +static ResultCode CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) { + return CreateEvent(system, out_write, out_read); } static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h index 7b897fbce..204cd989d 100644 --- a/src/core/hle/kernel/svc_results.h +++ b/src/core/hle/kernel/svc_results.h @@ -11,6 +11,7 @@ namespace Kernel::Svc { constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57}; constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59}; constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; +constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103}; constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113};