From fd69fd03259b71be521aeb69d3f73761b598be8a Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 20:16:13 -0400 Subject: kernel: added event module to support creation of CTR "Event" objects --- src/core/hle/kernel/event.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/core/hle/kernel/event.cpp (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp new file mode 100644 index 000000000..cc15ba9bc --- /dev/null +++ b/src/core/hle/kernel/event.cpp @@ -0,0 +1,91 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include + +#include "common/common.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/event.h" + +namespace Kernel { + +class Event : public Object { +public: + const char* GetTypeName() { return "Event"; } + + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } + Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } + + ResetType intitial_reset_type; ///< ResetType specified at Event initialization + ResetType reset_type; ///< Current ResetType + + bool locked; ///< Current locked state + + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result SyncRequest(bool* wait) { + // TODO(bunnei): ImplementMe + ERROR_LOG(KERNEL, "Unimplemented function Event::SyncRequest"); + return 0; + } + + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result WaitSynchronization(bool* wait) { + // TODO(bunnei): ImplementMe + *wait = locked; + if (reset_type != RESETTYPE_STICKY) { + locked = true; + } + return 0; + } +}; + +/** + * Clears an event + * @param handle Handle to event to clear + * @return Result of operation, 0 on success, otherwise error code + */ +Result ClearEvent(Handle handle) { + ERROR_LOG(KERNEL, "Unimplemented function ClearEvent"); + return 0; +} + +/** + * Creates an event + * @param handle Reference to handle for the newly created mutex + * @param reset_type ResetType describing how to create event + * @return Handle to newly created object + */ +Event* CreateEvent(Handle& handle, const ResetType reset_type) { + Event* evt = new Event; + + handle = Kernel::g_object_pool.Create(evt); + + evt->reset_type = evt->intitial_reset_type = reset_type; + evt->locked = false; + + return evt; +} + +/** + * Creates an event + * @param reset_type ResetType describing how to create event + * @return Handle to newly created object + */ +Handle CreateEvent(const ResetType reset_type) { + Handle handle; + Event* evt = CreateEvent(handle, reset_type); + return handle; +} + +} // namespace -- cgit v1.2.3 From beea6f054ae0bd40d1a564aa586735b81f2bf662 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 22:14:00 -0400 Subject: event: added SetEventLocked method to change status an events lock --- src/core/hle/kernel/event.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index cc15ba9bc..e85f39f0d 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -50,6 +50,17 @@ public: } }; +/** + * Changes whether an event is locked or not + * @param handle Handle to event to change + * @param locked Boolean locked value to set event + */ +void SetEventLocked(const Handle handle, const bool locked) { + Event* evt = g_object_pool.GetFast(handle); + evt->locked = locked; + return; +} + /** * Clears an event * @param handle Handle to event to clear -- cgit v1.2.3 From d51c84dde22549c7413e52a682158e6da3ff1fdc Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 20:00:44 -0400 Subject: event: added support for ClearEvent, fixed a bug with CreateEvent, fixed some comments --- src/core/hle/kernel/event.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index e85f39f0d..7cb8c5142 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -54,11 +54,16 @@ public: * Changes whether an event is locked or not * @param handle Handle to event to change * @param locked Boolean locked value to set event + * @return Result of operation, 0 on success, otherwise error code */ -void SetEventLocked(const Handle handle, const bool locked) { +Result SetEventLocked(const Handle handle, const bool locked) { Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "SetEventLocked called with unknown handle=0x%08X", handle); + return -1; + } evt->locked = locked; - return; + return 0; } /** @@ -67,23 +72,22 @@ void SetEventLocked(const Handle handle, const bool locked) { * @return Result of operation, 0 on success, otherwise error code */ Result ClearEvent(Handle handle) { - ERROR_LOG(KERNEL, "Unimplemented function ClearEvent"); - return 0; + return SetEventLocked(handle, true); } /** * Creates an event * @param handle Reference to handle for the newly created mutex * @param reset_type ResetType describing how to create event - * @return Handle to newly created object + * @return Newly created Event object */ Event* CreateEvent(Handle& handle, const ResetType reset_type) { Event* evt = new Event; handle = Kernel::g_object_pool.Create(evt); + evt->locked = true; evt->reset_type = evt->intitial_reset_type = reset_type; - evt->locked = false; return evt; } @@ -91,7 +95,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { /** * Creates an event * @param reset_type ResetType describing how to create event - * @return Handle to newly created object + * @return Handle to newly created Event object */ Handle CreateEvent(const ResetType reset_type) { Handle handle; -- cgit v1.2.3 From f7cececc5ca82f97a9fb1ab50c62fd9e3a49ccdc Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:33:55 -0400 Subject: event: added a hackish ability to set an event as "locked" to its current state, cleaned up some comments --- src/core/hle/kernel/event.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 7cb8c5142..e84d0b49e 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -23,6 +23,7 @@ public: ResetType reset_type; ///< Current ResetType bool locked; ///< Current locked state + bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) /** * Synchronize kernel object @@ -31,7 +32,7 @@ public: */ Result SyncRequest(bool* wait) { // TODO(bunnei): ImplementMe - ERROR_LOG(KERNEL, "Unimplemented function Event::SyncRequest"); + ERROR_LOG(KERNEL, "(UMIMPLEMENTED) call"); return 0; } @@ -43,7 +44,7 @@ public: Result WaitSynchronization(bool* wait) { // TODO(bunnei): ImplementMe *wait = locked; - if (reset_type != RESETTYPE_STICKY) { + if (reset_type != RESETTYPE_STICKY && !permanent_locked) { locked = true; } return 0; @@ -59,10 +60,28 @@ public: Result SetEventLocked(const Handle handle, const bool locked) { Event* evt = g_object_pool.GetFast(handle); if (!evt) { - ERROR_LOG(KERNEL, "SetEventLocked called with unknown handle=0x%08X", handle); + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); return -1; } - evt->locked = locked; + if (!evt->permanent_locked) { + evt->locked = locked; + } + return 0; +} + +/** + * Hackish function to set an events permanent lock state, used to pass through synch blocks + * @param handle Handle to event to change + * @param permanent_locked Boolean permanent locked value to set event + * @return Result of operation, 0 on success, otherwise error code + */ +Result SetPermanentLock(Handle handle, const bool permanent_locked) { + Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); + return -1; + } + evt->permanent_locked = permanent_locked; return 0; } @@ -87,6 +106,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { handle = Kernel::g_object_pool.Create(evt); evt->locked = true; + evt->permanent_locked = false; evt->reset_type = evt->intitial_reset_type = reset_type; return evt; -- cgit v1.2.3 From b78aff85857a3a356fdf11e1dbc4e5f52490676e Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 2 Jun 2014 20:38:34 -0400 Subject: svc: added optional name field to Event and Mutex (used for debugging) --- src/core/hle/kernel/event.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index e84d0b49e..70e50115d 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -15,6 +15,7 @@ namespace Kernel { class Event : public Object { public: const char* GetTypeName() { return "Event"; } + const char* GetName() { return name.c_str(); } static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } @@ -24,6 +25,7 @@ public: bool locked; ///< Current locked state bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) + std::string name; ///< Name of event (optional) /** * Synchronize kernel object @@ -98,9 +100,10 @@ Result ClearEvent(Handle handle) { * 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 */ -Event* CreateEvent(Handle& handle, const ResetType reset_type) { +Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string name) { Event* evt = new Event; handle = Kernel::g_object_pool.Create(evt); @@ -108,6 +111,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { evt->locked = true; evt->permanent_locked = false; evt->reset_type = evt->intitial_reset_type = reset_type; + evt->name = name; return evt; } @@ -115,11 +119,12 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { /** * 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) { +Handle CreateEvent(const ResetType reset_type, const std::string name) { Handle handle; - Event* evt = CreateEvent(handle, reset_type); + Event* evt = CreateEvent(handle, reset_type, name); return handle; } -- cgit v1.2.3 From f5c7c1543434e25a215286e6db5e71c055ba48cf Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 22:35:36 -0400 Subject: Kernel: Added real support for thread and event blocking - SVC: Added ExitThread support - SVC: Added SignalEvent support - Thread: Added WAITTYPE_EVENT for waiting threads for event signals - Thread: Added support for blocking on other threads to finish (e.g. Thread::Join) - Thread: Added debug function for printing current threads ready for execution - Thread: Removed hack/broken thread ready state code from Kernel::Reschedule - Mutex: Moved WaitCurrentThread from SVC to Mutex::WaitSynchronization - Event: Added support for blocking threads on event signalling Kernel: Added missing algorithm #include for use of std::find on non-Windows platforms. --- src/core/hle/kernel/event.cpp | 71 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 12 deletions(-) (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 70e50115d..787e9f5fd 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -3,12 +3,14 @@ // Refer to the license.txt file included. #include +#include #include #include "common/common.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/event.h" +#include "core/hle/kernel/thread.h" namespace Kernel { @@ -20,12 +22,13 @@ public: static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } - ResetType intitial_reset_type; ///< ResetType specified at Event initialization - ResetType reset_type; ///< Current ResetType + ResetType intitial_reset_type; ///< ResetType specified at Event initialization + ResetType reset_type; ///< Current ResetType - bool locked; ///< Current locked state - bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) - std::string name; ///< Name of event (optional) + bool locked; ///< Event signal wait + bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) + std::vector waiting_threads; ///< Threads that are waiting for the event + std::string name; ///< Name of event (optional) /** * Synchronize kernel object @@ -44,8 +47,14 @@ public: * @return Result of operation, 0 on success, otherwise error code */ Result WaitSynchronization(bool* wait) { - // TODO(bunnei): ImplementMe *wait = locked; + if (locked) { + Handle thread = GetCurrentThreadHandle(); + if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { + waiting_threads.push_back(thread); + } + Kernel::WaitCurrentThread(WAITTYPE_EVENT); + } if (reset_type != RESETTYPE_STICKY && !permanent_locked) { locked = true; } @@ -53,6 +62,22 @@ public: } }; +/** + * Hackish function to set an events permanent lock state, used to pass through synch blocks + * @param handle Handle to event to change + * @param permanent_locked Boolean permanent locked value to set event + * @return Result of operation, 0 on success, otherwise error code + */ +Result SetPermanentLock(Handle handle, const bool permanent_locked) { + Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); + return -1; + } + evt->permanent_locked = permanent_locked; + return 0; +} + /** * Changes whether an event is locked or not * @param handle Handle to event to change @@ -72,18 +97,32 @@ Result SetEventLocked(const Handle handle, const bool locked) { } /** - * Hackish function to set an events permanent lock state, used to pass through synch blocks - * @param handle Handle to event to change - * @param permanent_locked Boolean permanent locked value to set event + * Signals an event + * @param handle Handle to event to signal * @return Result of operation, 0 on success, otherwise error code */ -Result SetPermanentLock(Handle handle, const bool permanent_locked) { +Result SignalEvent(const Handle handle) { Event* evt = g_object_pool.GetFast(handle); if (!evt) { ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); return -1; } - evt->permanent_locked = permanent_locked; + // Resume threads waiting for event to signal + bool event_caught = false; + for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { + ResumeThreadFromWait( evt->waiting_threads[i]); + + // If any thread is signalled awake by this event, assume the event was "caught" and reset + // the event. This will result in the next thread waiting on the event to block. Otherwise, + // the event will not be reset, and the next thread to call WaitSynchronization on it will + // not block. Not sure if this is correct behavior, but it seems to work. + event_caught = true; + } + evt->waiting_threads.clear(); + + if (!evt->permanent_locked) { + evt->locked = event_caught; + } return 0; } @@ -93,7 +132,15 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) { * @return Result of operation, 0 on success, otherwise error code */ Result ClearEvent(Handle handle) { - return SetEventLocked(handle, true); + Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); + return -1; + } + if (!evt->permanent_locked) { + evt->locked = true; + } + return 0; } /** -- cgit v1.2.3 From aae9fcf4a4071a408af10ca1c72180cdc04687b8 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 23:13:28 -0400 Subject: Kernel: Made SyncRequest not pure virtual, with a default implementation of error (as this is not required for all kernel objects) --- src/core/hle/kernel/event.cpp | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 787e9f5fd..36c7dcbc8 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -30,17 +30,6 @@ public: std::vector waiting_threads; ///< Threads that are waiting for the event std::string name; ///< Name of event (optional) - /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result SyncRequest(bool* wait) { - // TODO(bunnei): ImplementMe - ERROR_LOG(KERNEL, "(UMIMPLEMENTED) call"); - return 0; - } - /** * Wait for kernel object to synchronize * @param wait Boolean wait set if current thread should wait as a result of sync operation -- cgit v1.2.3 From 8cac527c943253a9471849d17b1520f4762fbb5c Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:10:50 -0400 Subject: Kernel: Updated several member functions to be const --- src/core/hle/kernel/event.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 36c7dcbc8..72a190f8c 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -16,10 +16,10 @@ namespace Kernel { class Event : public Object { public: - const char* GetTypeName() { return "Event"; } - const char* GetName() { return name.c_str(); } + const char* GetTypeName() const { return "Event"; } + const char* GetName() const { return name.c_str(); } - static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } ResetType intitial_reset_type; ///< ResetType specified at Event initialization -- cgit v1.2.3 From 5365ca157d5cb81c5cba3922036839f3c58e85ba Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:23:33 -0400 Subject: Kernel: Updated various kernel function "name" arguments to be const references. --- src/core/hle/kernel/event.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 72a190f8c..3a522c190 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -139,7 +139,7 @@ Result ClearEvent(Handle handle) { * @param name Optional name of event * @return Newly created Event object */ -Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string name) { +Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { Event* evt = new Event; handle = Kernel::g_object_pool.Create(evt); @@ -158,7 +158,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string * @param name Optional name of event * @return Handle to newly created Event object */ -Handle CreateEvent(const ResetType reset_type, const std::string name) { +Handle CreateEvent(const ResetType reset_type, const std::string& name) { Handle handle; Event* evt = CreateEvent(handle, reset_type, name); return handle; -- cgit v1.2.3 From 83a4ad28854f6c90f688e3d4523708c2d06267de Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Jun 2014 22:46:54 -0400 Subject: Event: Updated several log messages to be assertions. --- src/core/hle/kernel/event.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'src/core/hle/kernel/event.cpp') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 3a522c190..127c0cfc6 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -59,10 +59,8 @@ public: */ Result SetPermanentLock(Handle handle, const bool permanent_locked) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + evt->permanent_locked = permanent_locked; return 0; } @@ -75,10 +73,8 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) { */ Result SetEventLocked(const Handle handle, const bool locked) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + if (!evt->permanent_locked) { evt->locked = locked; } @@ -92,10 +88,8 @@ Result SetEventLocked(const Handle handle, const bool locked) { */ Result SignalEvent(const Handle handle) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + // Resume threads waiting for event to signal bool event_caught = false; for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { @@ -122,10 +116,8 @@ Result SignalEvent(const Handle handle) { */ Result ClearEvent(Handle handle) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + if (!evt->permanent_locked) { evt->locked = true; } -- cgit v1.2.3