From d52d85993683a6948285801ab54d51c79c98afba Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Fri, 23 Jan 2015 03:11:25 -0200 Subject: Kernel: Convert Event to not use Handles --- src/core/hle/kernel/event.cpp | 83 +++++++++-------------------------- src/core/hle/kernel/event.h | 51 ++++++++++++--------- src/core/hle/service/apt_u.cpp | 26 +++++------ src/core/hle/service/dsp_dsp.cpp | 26 +++++++---- src/core/hle/service/gsp_gpu.cpp | 19 ++++---- src/core/hle/service/hid/hid.cpp | 28 ++++++------ src/core/hle/service/hid/hid.h | 11 ++--- src/core/hle/service/hid/hid_user.cpp | 11 ++--- src/core/hle/service/srv.cpp | 8 ++-- src/core/hle/svc.cpp | 40 ++++++++++++----- 10 files changed, 151 insertions(+), 152 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 74df47a0..d9ad40c6 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -14,78 +14,37 @@ namespace Kernel { -class Event : public WaitObject { -public: - std::string GetTypeName() const override { return "Event"; } - std::string GetName() const override { return name; } - - static const HandleType HANDLE_TYPE = HandleType::Event; - HandleType GetHandleType() const override { return HANDLE_TYPE; } - - ResetType intitial_reset_type; ///< ResetType specified at Event initialization - ResetType reset_type; ///< Current ResetType - - bool signaled; ///< Whether the event has already been signaled - std::string name; ///< Name of event (optional) - - bool ShouldWait() override { - return !signaled; - } - - void Acquire() override { - _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); - - // Release the event if it's not sticky... - if (reset_type != RESETTYPE_STICKY) - signaled = false; - } -}; - -ResultCode SignalEvent(const Handle handle) { - Event* evt = g_handle_table.Get(handle).get(); - if (evt == nullptr) - return InvalidHandle(ErrorModule::Kernel); - - evt->signaled = true; - evt->WakeupAllWaitingThreads(); - - return RESULT_SUCCESS; -} - -ResultCode ClearEvent(Handle handle) { - Event* evt = g_handle_table.Get(handle).get(); - if (evt == nullptr) - return InvalidHandle(ErrorModule::Kernel); +ResultVal> Event::Create(ResetType reset_type, std::string name) { + SharedPtr evt(new Event); + // TOOD(yuriks): Don't create Handle (see Thread::Create()) + CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(evt)); evt->signaled = false; + evt->reset_type = evt->intitial_reset_type = reset_type; + evt->name = std::move(name); - return RESULT_SUCCESS; + return MakeResult>(evt); } -/** - * Creates an event - * @param handle Reference to handle for the newly created mutex - * @param reset_type ResetType describing how to create event - * @param name Optional name of event - * @return Newly created Event object - */ -static Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { - Event* evt = new Event; +bool Event::ShouldWait() { + return !signaled; +} - // TOOD(yuriks): Fix error reporting - handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE); +void Event::Acquire() { + _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); - evt->signaled = false; - evt->reset_type = evt->intitial_reset_type = reset_type; - evt->name = name; + // Release the event if it's not sticky... + if (reset_type != RESETTYPE_STICKY) + signaled = false; +} - return evt; +void Event::Signal() { + signaled = true; + WakeupAllWaitingThreads(); } -Handle CreateEvent(const ResetType reset_type, const std::string& name) { - Handle handle; - Event* evt = CreateEvent(handle, reset_type, name); - return handle; +void Event::Clear() { + signaled = false; } } // namespace diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index c08b12ee..47420b15 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -11,26 +11,35 @@ namespace Kernel { -/** - * Signals an event - * @param handle Handle to event to signal - * @return Result of operation, 0 on success, otherwise error code - */ -ResultCode SignalEvent(const Handle handle); - -/** - * Clears an event - * @param handle Handle to event to clear - * @return Result of operation, 0 on success, otherwise error code - */ -ResultCode ClearEvent(Handle handle); - -/** - * Creates an event - * @param reset_type ResetType describing how to create event - * @param name Optional name of event - * @return Handle to newly created Event object - */ -Handle CreateEvent(const ResetType reset_type, const std::string& name="Unknown"); +class Event : public WaitObject { +public: + /** + * Creates an event + * @param reset_type ResetType describing how to create event + * @param name Optional name of event + */ + static ResultVal> Create(ResetType reset_type, std::string name = "Unknown"); + + std::string GetTypeName() const override { return "Event"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::Event; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + ResetType intitial_reset_type; ///< ResetType specified at Event initialization + ResetType reset_type; ///< Current ResetType + + bool signaled; ///< Whether the event has already been signaled + std::string name; ///< Name of event (optional) + + bool ShouldWait() override; + void Acquire() override; + + void Signal(); + void Clear(); + +private: + Event() = default; +}; } // namespace diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index 5d7a6e06..629b670e 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp @@ -30,8 +30,8 @@ static const VAddr SHARED_FONT_VADDR = 0x18000000; static Kernel::SharedPtr shared_font_mem; static Kernel::SharedPtr lock; -static Handle notification_event_handle = 0; ///< APT notification event handle -static Handle pause_event_handle = 0; ///< APT pause event handle +static Kernel::SharedPtr notification_event; ///< APT notification event +static Kernel::SharedPtr pause_event = 0; ///< APT pause event static std::vector shared_font; /// Signals used by APT functions @@ -68,14 +68,16 @@ enum class AppID : u32 { void Initialize(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - notification_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Notification"); - pause_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); + // TODO(bunnei): Check if these are created in Initialize or on APT process startup. + notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification").MoveFrom(); + pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause").MoveFrom(); - cmd_buff[3] = notification_event_handle; - cmd_buff[4] = pause_event_handle; + cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); + cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom(); - Kernel::ClearEvent(notification_event_handle); - Kernel::SignalEvent(pause_event_handle); // Fire start event + // TODO(bunnei): Check if these events are cleared/signaled every time Initialize is called. + notification_event->Clear(); + pause_event->Signal(); // Fire start event _assert_msg_(KERNEL, (nullptr != lock), "Cannot initialize without lock"); lock->Release(); @@ -94,7 +96,7 @@ void NotifyToWait(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 app_id = cmd_buff[1]; // TODO(Subv): Verify this, it seems to get SWKBD and Home Menu further. - Kernel::SignalEvent(pause_event_handle); + pause_event->Signal(); cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); @@ -104,10 +106,6 @@ void GetLockHandle(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field - if (nullptr == lock) { - // TODO(bunnei): Verify if this is created here or at application boot? - lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom(); - } cmd_buff[1] = RESULT_SUCCESS.raw; // No error // Not sure what these parameters are used for, but retail apps check that they are 0 after @@ -520,7 +518,7 @@ Interface::Interface() { shared_font_mem = nullptr; } - lock = nullptr; + lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom(); Register(FunctionTable, ARRAY_SIZE(FunctionTable)); } diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index d5e39ea4..9a38be39 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -13,8 +13,8 @@ namespace DSP_DSP { static u32 read_pipe_count = 0; -static Handle semaphore_event = 0; -static Handle interrupt_event = 0; +static Kernel::SharedPtr semaphore_event; +static Kernel::SharedPtr interrupt_event; void SignalInterrupt() { // TODO(bunnei): This is just a stub, it does not do anything other than signal to the emulated @@ -24,7 +24,7 @@ void SignalInterrupt() { // DSP interrupts, and trigger them at the appropriate times. if (interrupt_event != 0) - Kernel::SignalEvent(interrupt_event); + interrupt_event->Signal(); } /** @@ -78,8 +78,8 @@ void LoadComponent(Service::Interface* self) { void GetSemaphoreEventHandle(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = 0; // No error - cmd_buff[3] = semaphore_event; // Event handle + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).MoveFrom(); // Event handle LOG_WARNING(Service_DSP, "(STUBBED) called"); } @@ -96,9 +96,16 @@ void GetSemaphoreEventHandle(Service::Interface* self) { void RegisterInterruptEvents(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - interrupt_event = static_cast(cmd_buff[4]); + auto evt = Kernel::g_handle_table.Get(cmd_buff[4]); + if (evt != nullptr) { + interrupt_event = evt; + cmd_buff[1] = 0; // No error + } else { + LOG_ERROR(Service_DSP, "called with invalid handle=%08X", cmd_buff[4]); - cmd_buff[1] = 0; // No error + // TODO(yuriks): An error should be returned from SendSyncRequest, not in the cmdbuf + cmd_buff[1] = -1; + } LOG_WARNING(Service_DSP, "(STUBBED) called"); } @@ -194,8 +201,9 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - semaphore_event = Kernel::CreateEvent(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event"); - interrupt_event = 0; + semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, + "DSP_DSP::semaphore_event").MoveFrom(); + interrupt_event = nullptr; read_pipe_count = 0; Register(FunctionTable, ARRAY_SIZE(FunctionTable)); diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 1be2438c..5b91f17d 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -22,9 +22,12 @@ GraphicsDebugger g_debugger; namespace GSP_GPU { -Handle g_interrupt_event = 0; ///< Handle to event triggered when GSP interrupt has been signalled -Kernel::SharedPtr g_shared_memory; ///< GSP shared memoryings -u32 g_thread_id = 1; ///< Thread index into interrupt relay queue, 1 is arbitrary +/// Event triggered when GSP interrupt has been signalled +Kernel::SharedPtr g_interrupt_event; +/// GSP shared memoryings +Kernel::SharedPtr g_shared_memory; +/// Thread index into interrupt relay queue, 1 is arbitrary +u32 g_thread_id = 1; /// Gets a pointer to a thread command buffer in GSP shared memory static inline u8* GetCommandBuffer(u32 thread_id) { @@ -181,10 +184,10 @@ static void FlushDataCache(Service::Interface* self) { static void RegisterInterruptRelayQueue(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 flags = cmd_buff[1]; - g_interrupt_event = cmd_buff[3]; - g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom(); - _assert_msg_(GSP, (g_interrupt_event != 0), "handle is not valid!"); + g_interrupt_event = Kernel::g_handle_table.Get(cmd_buff[3]); + _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!"); + g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom(); Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); @@ -192,7 +195,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { cmd_buff[2] = g_thread_id++; // Thread ID cmd_buff[4] = shmem_handle; // GSP shared memory - Kernel::SignalEvent(g_interrupt_event); // TODO(bunnei): Is this correct? + g_interrupt_event->Signal(); // TODO(bunnei): Is this correct? } /** @@ -234,7 +237,7 @@ void SignalInterrupt(InterruptId interrupt_id) { info->is_dirty = false; } } - Kernel::SignalEvent(g_interrupt_event); + g_interrupt_event->Signal(); } /// Executes the next GSP command diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index ee2ba7e0..835055af 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -14,11 +14,11 @@ namespace HID { Kernel::SharedPtr g_shared_mem = nullptr; -Handle g_event_pad_or_touch_1 = 0; -Handle g_event_pad_or_touch_2 = 0; -Handle g_event_accelerometer = 0; -Handle g_event_gyroscope = 0; -Handle g_event_debug_pad = 0; +Kernel::SharedPtr g_event_pad_or_touch_1; +Kernel::SharedPtr g_event_pad_or_touch_2; +Kernel::SharedPtr g_event_accelerometer; +Kernel::SharedPtr g_event_gyroscope; +Kernel::SharedPtr g_event_debug_pad; // Next Pad state update information static PadState next_state = {{0}}; @@ -115,19 +115,21 @@ void PadUpdateComplete() { } // Signal both handles when there's an update to Pad or touch - Kernel::SignalEvent(g_event_pad_or_touch_1); - Kernel::SignalEvent(g_event_pad_or_touch_2); + g_event_pad_or_touch_1->Signal(); + g_event_pad_or_touch_2->Signal(); } void HIDInit() { - g_shared_mem = Kernel::SharedMemory::Create("HID:SharedMem").MoveFrom(); + using namespace Kernel; + + g_shared_mem = SharedMemory::Create("HID:SharedMem").MoveFrom(); // Create event handles - g_event_pad_or_touch_1 = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1"); - g_event_pad_or_touch_2 = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2"); - g_event_accelerometer = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventAccelerometer"); - g_event_gyroscope = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventGyroscope"); - g_event_debug_pad = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventDebugPad"); + g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1").MoveFrom(); + g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2").MoveFrom(); + g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer").MoveFrom(); + g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope").MoveFrom(); + g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad").MoveFrom(); } void HIDShutdown() { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 5e623664..2116d2ca 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -11,6 +11,7 @@ namespace Kernel { class SharedMemory; + class Event; } namespace Service { @@ -20,11 +21,11 @@ namespace HID { extern Kernel::SharedPtr g_shared_mem; // Event handles -extern Handle g_event_pad_or_touch_1; -extern Handle g_event_pad_or_touch_2; -extern Handle g_event_accelerometer; -extern Handle g_event_gyroscope; -extern Handle g_event_debug_pad; +extern Kernel::SharedPtr g_event_pad_or_touch_1; +extern Kernel::SharedPtr g_event_pad_or_touch_2; +extern Kernel::SharedPtr g_event_accelerometer; +extern Kernel::SharedPtr g_event_gyroscope; +extern Kernel::SharedPtr g_event_debug_pad; /** * Structure of a Pad controller state. diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp index c167927e..5444aa5e 100644 --- a/src/core/hle/service/hid/hid_user.cpp +++ b/src/core/hle/service/hid/hid_user.cpp @@ -5,6 +5,7 @@ #include "common/log.h" #include "core/hle/hle.h" +#include "core/hle/kernel/event.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/service/hid/hid.h" #include "hid_user.h" @@ -49,11 +50,11 @@ void GetIPCHandles(Service::Interface* self) { cmd_buff[1] = 0; // No error // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::g_shared_mem).MoveFrom(); - cmd_buff[4] = Service::HID::g_event_pad_or_touch_1; - cmd_buff[5] = Service::HID::g_event_pad_or_touch_2; - cmd_buff[6] = Service::HID::g_event_accelerometer; - cmd_buff[7] = Service::HID::g_event_gyroscope; - cmd_buff[8] = Service::HID::g_event_debug_pad; + cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::g_event_pad_or_touch_1).MoveFrom(); + cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::g_event_pad_or_touch_2).MoveFrom(); + cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::g_event_accelerometer).MoveFrom(); + cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::g_event_gyroscope).MoveFrom(); + cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::g_event_debug_pad).MoveFrom(); } const Interface::FunctionInfo FunctionTable[] = { diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 082834cf..aa0aac3b 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -11,7 +11,7 @@ namespace SRV { -static Handle g_event_handle = 0; +static Kernel::SharedPtr event_handle; static void Initialize(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); @@ -23,11 +23,11 @@ static void GetProcSemaphore(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); // TODO(bunnei): Change to a semaphore once these have been implemented - g_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "SRV:Event"); - Kernel::ClearEvent(g_event_handle); + event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event").MoveFrom(); + event_handle->Clear(); cmd_buff[1] = 0; // No error - cmd_buff[3] = g_event_handle; + cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom(); } static void GetServiceHandle(Service::Interface* self) { diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 95403644..0c50f0d5 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -447,11 +447,17 @@ static Result QueryMemory(void* info, void* out, u32 addr) { } /// Create an event -static Result CreateEvent(Handle* evt, u32 reset_type) { - *evt = Kernel::CreateEvent((ResetType)reset_type); - LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", - reset_type, *evt); - return 0; +static Result CreateEvent(Handle* handle, u32 reset_type) { + auto evt_res = Kernel::Event::Create(static_cast(reset_type)); + if (evt_res.Failed()) + return evt_res.Code().raw; + auto handle_res = Kernel::g_handle_table.Create(evt_res.MoveFrom()); + if (handle_res.Failed()) + return handle_res.Code().raw; + *handle = handle_res.MoveFrom(); + + LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, *handle); + return RESULT_SUCCESS.raw; } /// Duplicates a kernel handle @@ -465,16 +471,28 @@ static Result DuplicateHandle(Handle* out, Handle handle) { } /// Signals an event -static Result SignalEvent(Handle evt) { - LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); +static Result SignalEvent(Handle handle) { + LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); + + auto evt = Kernel::g_handle_table.Get(handle); + if (evt == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + evt->Signal(); HLE::Reschedule(__func__); - return Kernel::SignalEvent(evt).raw; + return RESULT_SUCCESS.raw; } /// Clears an event -static Result ClearEvent(Handle evt) { - LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); - return Kernel::ClearEvent(evt).raw; +static Result ClearEvent(Handle handle) { + LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); + + auto evt = Kernel::g_handle_table.Get(handle); + if (evt == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + evt->Clear(); + return RESULT_SUCCESS.raw; } /// Creates a timer -- cgit v1.2.3