diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp index 8e088559d..503510a4b 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp @@ -104,7 +104,6 @@ namespace ams::kern { KSession, KSharedMemory, KEvent, - KWritableEvent, KLightClientSession, KLightServerSession, KTransferMemory, diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_client_session.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_client_session.hpp index 8ff0bbf23..4315b6a83 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_client_session.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_client_session.hpp @@ -20,6 +20,7 @@ namespace ams::kern { class KSession; + class KEvent; class KClientSession final : public KAutoObject { MESOSPHERE_AUTOOBJECT_TRAITS(KClientSession, KAutoObject); @@ -39,7 +40,7 @@ namespace ams::kern { constexpr KSession *GetParent() const { return m_parent; } Result SendSyncRequest(uintptr_t address, size_t size); - Result SendAsyncRequest(KWritableEvent *event, uintptr_t address, size_t size); + Result SendAsyncRequest(KEvent *event, uintptr_t address, size_t size); void OnServerClosed(); }; diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_event.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_event.hpp index 4a3167784..8f0d98e4c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_event.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_event.hpp @@ -18,7 +18,6 @@ #include #include #include -#include namespace ams::kern { @@ -26,12 +25,12 @@ namespace ams::kern { MESOSPHERE_AUTOOBJECT_TRAITS(KEvent, KAutoObject); private: KReadableEvent m_readable_event; - KWritableEvent m_writable_event; KProcess *m_owner; bool m_initialized; + bool m_readable_event_destroyed; public: constexpr KEvent() - : m_readable_event(), m_writable_event(), m_owner(), m_initialized() + : m_readable_event(), m_owner(), m_initialized(), m_readable_event_destroyed() { /* ... */ } @@ -47,7 +46,11 @@ namespace ams::kern { virtual KProcess *GetOwner() const override { return m_owner; } KReadableEvent &GetReadableEvent() { return m_readable_event; } - KWritableEvent &GetWritableEvent() { return m_writable_event; } + + Result Signal(); + Result Clear(); + + ALWAYS_INLINE void OnReadableEventDestroyed() { m_readable_event_destroyed = true; } }; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_readable_event.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_readable_event.hpp index 8889ccd22..48dce81b9 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_readable_event.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_readable_event.hpp @@ -29,19 +29,15 @@ namespace ams::kern { public: constexpr explicit KReadableEvent() : KSynchronizationObject(), m_is_signaled(), m_parent() { MESOSPHERE_ASSERT_THIS(); } - constexpr void Initialize(KEvent *parent) { - MESOSPHERE_ASSERT_THIS(); - m_is_signaled = false; - m_parent = parent; - } + void Initialize(KEvent *parent); constexpr KEvent *GetParent() const { return m_parent; } + Result Signal(); + Result Clear(); + virtual bool IsSignaled() const override; virtual void Destroy() override; - - virtual Result Signal(); - virtual Result Clear(); virtual Result Reset(); }; diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_session_request.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_session_request.hpp index 08572933d..3707e1372 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_session_request.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_session_request.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -126,7 +126,7 @@ namespace ams::kern { SessionMappings m_mappings; KThread *m_thread; KProcess *m_server; - KWritableEvent *m_event; + KEvent *m_event; uintptr_t m_address; size_t m_size; public: @@ -145,7 +145,7 @@ namespace ams::kern { KSessionRequest::Free(this); } - void Initialize(KWritableEvent *event, uintptr_t address, size_t size) { + void Initialize(KEvent *event, uintptr_t address, size_t size) { m_mappings.Initialize(); m_thread = std::addressof(GetCurrentThread()); @@ -176,7 +176,7 @@ namespace ams::kern { static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ } constexpr ALWAYS_INLINE KThread *GetThread() const { return m_thread; } - constexpr ALWAYS_INLINE KWritableEvent *GetEvent() const { return m_event; } + constexpr ALWAYS_INLINE KEvent *GetEvent() const { return m_event; } constexpr ALWAYS_INLINE uintptr_t GetAddress() const { return m_address; } constexpr ALWAYS_INLINE size_t GetSize() const { return m_size; } constexpr ALWAYS_INLINE KProcess *GetServerProcess() const { return m_server; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_writable_event.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_writable_event.hpp deleted file mode 100644 index bcb6db6bd..000000000 --- a/libraries/libmesosphere/include/mesosphere/kern_k_writable_event.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018-2020 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once -#include -#include -#include - -namespace ams::kern { - - class KEvent; - - class KWritableEvent final : public KAutoObjectWithSlabHeapAndContainer { - MESOSPHERE_AUTOOBJECT_TRAITS(KWritableEvent, KAutoObject); - private: - KEvent *m_parent; - public: - constexpr explicit KWritableEvent() : m_parent(nullptr) { /* ... */ } - - virtual void Destroy() override; - - static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ } - - void Initialize(KEvent *p); - Result Signal(); - Result Clear(); - - constexpr KEvent *GetParent() const { return m_parent; } - }; - -} diff --git a/libraries/libmesosphere/source/kern_k_class_token.cpp b/libraries/libmesosphere/source/kern_k_class_token.cpp index 531f6412c..2d2f8d0e3 100644 --- a/libraries/libmesosphere/source/kern_k_class_token.cpp +++ b/libraries/libmesosphere/source/kern_k_class_token.cpp @@ -37,13 +37,12 @@ namespace ams::kern { static_assert(ClassToken == 0b00011001'00000000); static_assert(ClassToken == 0b00101001'00000000); static_assert(ClassToken == 0b01001001'00000000); - static_assert(ClassToken == 0b10001001'00000000); - static_assert(ClassToken == 0b00110001'00000000); - static_assert(ClassToken == 0b01010001'00000000); - static_assert(ClassToken == 0b10010001'00000000); - static_assert(ClassToken == 0b01100001'00000000); - static_assert(ClassToken == 0b10100001'00000000); - static_assert(ClassToken == 0b11000001'00000000); + static_assert(ClassToken == 0b10001001'00000000); + static_assert(ClassToken == 0b00110001'00000000); + static_assert(ClassToken == 0b01010001'00000000); + static_assert(ClassToken == 0b10010001'00000000); + static_assert(ClassToken == 0b01100001'00000000); + static_assert(ClassToken == 0b10100001'00000000); /* Ensure that the token hierarchy is correct. */ @@ -67,13 +66,12 @@ namespace ams::kern { static_assert(ClassToken == ((0b00011001 << 8) | ClassToken)); static_assert(ClassToken == ((0b00101001 << 8) | ClassToken)); static_assert(ClassToken == ((0b01001001 << 8) | ClassToken)); - static_assert(ClassToken == ((0b10001001 << 8) | ClassToken)); - static_assert(ClassToken == ((0b00110001 << 8) | ClassToken)); - static_assert(ClassToken == ((0b01010001 << 8) | ClassToken)); - static_assert(ClassToken == ((0b10010001 << 8) | ClassToken)); - static_assert(ClassToken == ((0b01100001 << 8) | ClassToken)); - static_assert(ClassToken == ((0b10100001 << 8) | ClassToken)); - static_assert(ClassToken == ((0b11000001 << 8) | ClassToken)); + static_assert(ClassToken == ((0b10001001 << 8) | ClassToken)); + static_assert(ClassToken == ((0b00110001 << 8) | ClassToken)); + static_assert(ClassToken == ((0b01010001 << 8) | ClassToken)); + static_assert(ClassToken == ((0b10010001 << 8) | ClassToken)); + static_assert(ClassToken == ((0b01100001 << 8) | ClassToken)); + static_assert(ClassToken == ((0b10100001 << 8) | ClassToken)); /* Ensure that the token hierarchy reflects the class hierarchy. */ @@ -96,7 +94,6 @@ namespace ams::kern { static_assert(std::is_final::value && std::is_base_of::value); static_assert(std::is_final::value && std::is_base_of::value); static_assert(std::is_final::value && std::is_base_of::value); - static_assert(std::is_final::value && std::is_base_of::value); static_assert(std::is_final::value && std::is_base_of::value); static_assert(std::is_final::value && std::is_base_of::value); static_assert(std::is_final::value && std::is_base_of::value); diff --git a/libraries/libmesosphere/source/kern_k_client_session.cpp b/libraries/libmesosphere/source/kern_k_client_session.cpp index 569d9ac29..5ee779fd3 100644 --- a/libraries/libmesosphere/source/kern_k_client_session.cpp +++ b/libraries/libmesosphere/source/kern_k_client_session.cpp @@ -53,7 +53,7 @@ namespace ams::kern { return GetCurrentThread().GetWaitResult(std::addressof(dummy)); } - Result KClientSession::SendAsyncRequest(KWritableEvent *event, uintptr_t address, size_t size) { + Result KClientSession::SendAsyncRequest(KEvent *event, uintptr_t address, size_t size) { MESOSPHERE_ASSERT_THIS(); /* Create a session request. */ diff --git a/libraries/libmesosphere/source/kern_k_dump_object.cpp b/libraries/libmesosphere/source/kern_k_dump_object.cpp index a5f7eb125..73e7af37a 100644 --- a/libraries/libmesosphere/source/kern_k_dump_object.cpp +++ b/libraries/libmesosphere/source/kern_k_dump_object.cpp @@ -99,15 +99,11 @@ namespace ams::kern::KDumpObject { MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s OwnerPID=%d (%s) OwnerAddress=%lx Size=%zu KB\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), static_cast(target_owner->GetId()), target_owner->GetName(), GetInteger(target->GetSourceAddress()), target->GetSize() / 1_KB); } else if (auto *target = obj->DynamicCast(); target != nullptr) { MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s irq=%d\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), target->GetInterruptId()); - } else if (auto *target = obj->DynamicCast(); target != nullptr) { - if (KEvent *event = target->GetParent(); event != nullptr) { - MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s Pair=%p\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), std::addressof(event->GetReadableEvent())); - } else { - MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName()); - } + } else if (auto *target = obj->DynamicCast(); target != nullptr) { + MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName()); } else if (auto *target = obj->DynamicCast(); target != nullptr) { if (KEvent *event = target->GetParent(); event != nullptr) { - MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s Pair=%p\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), std::addressof(event->GetWritableEvent())); + MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s Parent=%p\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), event); } else { MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName()); } diff --git a/libraries/libmesosphere/source/kern_k_event.cpp b/libraries/libmesosphere/source/kern_k_event.cpp index 189e1be94..7ff862a74 100644 --- a/libraries/libmesosphere/source/kern_k_event.cpp +++ b/libraries/libmesosphere/source/kern_k_event.cpp @@ -20,19 +20,11 @@ namespace ams::kern { void KEvent::Initialize() { MESOSPHERE_ASSERT_THIS(); - /* Increment reference count. */ - /* Because reference count is one on creation, this will result */ - /* in a reference count of two. Thus, when both readable and */ - /* writable events are closed this object will be destroyed. */ - this->Open(); - - /* Create our sub events. */ + /* Create our readable event. */ KAutoObject::Create(std::addressof(m_readable_event)); - KAutoObject::Create(std::addressof(m_writable_event)); - /* Initialize our sub sessions. */ + /* Initialize our readable event. */ m_readable_event.Initialize(this); - m_writable_event.Initialize(this); /* Set our owner process. */ m_owner = GetCurrentProcessPointer(); @@ -48,6 +40,22 @@ namespace ams::kern { KAutoObjectWithSlabHeapAndContainer::Finalize(); } + Result KEvent::Signal() { + KScopedSchedulerLock sl; + + R_SUCCEED_IF(m_readable_event_destroyed); + + return m_readable_event.Signal(); + } + + Result KEvent::Clear() { + KScopedSchedulerLock sl; + + R_SUCCEED_IF(m_readable_event_destroyed); + + return m_readable_event.Clear(); + } + void KEvent::PostDestroy(uintptr_t arg) { /* Release the event count resource the owner process holds. */ KProcess *owner = reinterpret_cast(arg); diff --git a/libraries/libmesosphere/source/kern_k_readable_event.cpp b/libraries/libmesosphere/source/kern_k_readable_event.cpp index e3e2878e9..644b2a5da 100644 --- a/libraries/libmesosphere/source/kern_k_readable_event.cpp +++ b/libraries/libmesosphere/source/kern_k_readable_event.cpp @@ -17,6 +17,16 @@ namespace ams::kern { + void KReadableEvent::Initialize(KEvent *parent) { + MESOSPHERE_ASSERT_THIS(); + m_is_signaled = false; + m_parent = parent; + + if (m_parent != nullptr) { + m_parent->Open(); + } + } + bool KReadableEvent::IsSignaled() const { MESOSPHERE_ASSERT_THIS(); MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread()); @@ -27,6 +37,11 @@ namespace ams::kern { void KReadableEvent::Destroy() { MESOSPHERE_ASSERT_THIS(); if (m_parent) { + { + KScopedSchedulerLock sl; + m_parent->OnReadableEventDestroyed(); + } + m_parent->Close(); } } diff --git a/libraries/libmesosphere/source/kern_k_server_session.cpp b/libraries/libmesosphere/source/kern_k_server_session.cpp index 1cd5a1a8d..f4d32b0d4 100644 --- a/libraries/libmesosphere/source/kern_k_server_session.cpp +++ b/libraries/libmesosphere/source/kern_k_server_session.cpp @@ -1025,7 +1025,7 @@ namespace ams::kern { ON_SCOPE_EXIT { request->Close(); }; /* Get the event to check whether the request is async. */ - if (KWritableEvent *event = request->GetEvent(); event != nullptr) { + if (KEvent *event = request->GetEvent(); event != nullptr) { /* The client sent an async request. */ KProcess *client = client_thread->GetOwnerProcess(); auto &client_pt = client->GetPageTable(); @@ -1091,7 +1091,7 @@ namespace ams::kern { const uintptr_t client_message = request->GetAddress(); const size_t client_buffer_size = request->GetSize(); KThread *client_thread = request->GetThread(); - KWritableEvent *event = request->GetEvent(); + KEvent *event = request->GetEvent(); /* Check whether we're closed. */ const bool closed = (client_thread == nullptr || m_parent->IsClientClosed()); @@ -1242,7 +1242,7 @@ namespace ams::kern { const uintptr_t client_message = request->GetAddress(); const size_t client_buffer_size = request->GetSize(); KThread *client_thread = request->GetThread(); - KWritableEvent *event = request->GetEvent(); + KEvent *event = request->GetEvent(); KProcess *server_process = request->GetServerProcess(); KProcess *client_process = (client_thread != nullptr) ? client_thread->GetOwnerProcess() : nullptr; @@ -1285,7 +1285,7 @@ namespace ams::kern { while (true) { /* Declare variables for processing the request. */ KSessionRequest *request = nullptr; - KWritableEvent *event = nullptr; + KEvent *event = nullptr; KThread *thread = nullptr; bool cur_request = false; bool terminate = false; diff --git a/libraries/libmesosphere/source/kern_k_writable_event.cpp b/libraries/libmesosphere/source/kern_k_writable_event.cpp deleted file mode 100644 index 6dbd5ba51..000000000 --- a/libraries/libmesosphere/source/kern_k_writable_event.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2018-2020 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include - -namespace ams::kern { - - void KWritableEvent::Initialize(KEvent *p) { - /* Set parent, open a reference to the readable event. */ - m_parent = p; - m_parent->GetReadableEvent().Open(); - } - - Result KWritableEvent::Signal() { - return m_parent->GetReadableEvent().Signal(); - } - - Result KWritableEvent::Clear() { - return m_parent->GetReadableEvent().Clear(); - } - - void KWritableEvent::Destroy() { - /* Close our references. */ - m_parent->GetReadableEvent().Close(); - m_parent->Close(); - } - -} diff --git a/libraries/libmesosphere/source/svc/kern_svc_event.cpp b/libraries/libmesosphere/source/svc/kern_svc_event.cpp index fc34ddb7c..7ab2780ce 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_event.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_event.cpp @@ -26,10 +26,10 @@ namespace ams::kern::svc { auto &handle_table = GetCurrentProcess().GetHandleTable(); /* Get the writable event. */ - KScopedAutoObject writable_event = handle_table.GetObject(event_handle); - R_UNLESS(writable_event.IsNotNull(), svc::ResultInvalidHandle()); + KScopedAutoObject event = handle_table.GetObject(event_handle); + R_UNLESS(event.IsNotNull(), svc::ResultInvalidHandle()); - return writable_event->Signal(); + return event->Signal(); } Result ClearEvent(ams::svc::Handle event_handle) { @@ -38,9 +38,9 @@ namespace ams::kern::svc { /* Try to clear the writable event. */ { - KScopedAutoObject writable_event = handle_table.GetObject(event_handle); - if (writable_event.IsNotNull()) { - return writable_event->Clear(); + KScopedAutoObject event = handle_table.GetObject(event_handle); + if (event.IsNotNull()) { + return event->Clear(); } } @@ -76,15 +76,15 @@ namespace ams::kern::svc { /* Ensure that we clean up the event (and its only references are handle table) on function end. */ ON_SCOPE_EXIT { - event->GetWritableEvent().Close(); event->GetReadableEvent().Close(); + event->Close(); }; /* Register the event. */ KEvent::Register(event); - /* Add the writable event to the handle table. */ - R_TRY(handle_table.Add(out_write, std::addressof(event->GetWritableEvent()))); + /* Add the event to the handle table. */ + R_TRY(handle_table.Add(out_write, event)); /* Ensure that we maintaing a clean handle state on exit. */ auto handle_guard = SCOPE_GUARD { handle_table.Remove(*out_write); }; diff --git a/libraries/libmesosphere/source/svc/kern_svc_ipc.cpp b/libraries/libmesosphere/source/svc/kern_svc_ipc.cpp index 673dfe702..a6a3e4366 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_ipc.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_ipc.cpp @@ -191,7 +191,7 @@ namespace ams::kern::svc { /* At end of scope, kill the standing references to the sub events. */ ON_SCOPE_EXIT { event->GetReadableEvent().Close(); - event->GetWritableEvent().Close(); + event->Close(); }; /* Register the event. */ @@ -204,7 +204,7 @@ namespace ams::kern::svc { auto read_guard = SCOPE_GUARD { handle_table.Remove(*out_event_handle); }; /* Send the async request. */ - R_TRY(session->SendAsyncRequest(std::addressof(event->GetWritableEvent()), message, buffer_size)); + R_TRY(session->SendAsyncRequest(event, message, buffer_size)); /* We succeeded. */ read_guard.Cancel();