From cbdf33260e6d40339858867076bf75af19dd7410 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 7 Apr 2021 14:45:38 -0700 Subject: [PATCH] kern: update port/session state semantics --- .../include/mesosphere/kern_k_client_port.hpp | 1 + .../include/mesosphere/kern_k_object_name.hpp | 3 +++ .../include/mesosphere/kern_k_port.hpp | 5 +++++ .../include/mesosphere/kern_k_session.hpp | 16 ++++++++++++---- .../libmesosphere/source/kern_k_client_port.cpp | 4 ++++ .../libmesosphere/source/kern_k_server_port.cpp | 4 ++-- .../libmesosphere/source/kern_k_session.cpp | 10 +++++----- 7 files changed, 32 insertions(+), 11 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_client_port.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_client_port.hpp index d2462d0fc..a66006a9a 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_client_port.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_client_port.hpp @@ -47,6 +47,7 @@ namespace ams::kern { ALWAYS_INLINE s32 GetMaxSessions() const { return m_max_sessions; } bool IsLight() const; + bool IsServerClosed() const; /* Overridden virtual functions. */ virtual void Destroy() override; diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_object_name.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_object_name.hpp index f97a16d4b..f0bf6b8a0 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_object_name.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_object_name.hpp @@ -47,6 +47,9 @@ namespace ams::kern { Derived *derived = obj->DynamicCast(); R_UNLESS(derived != nullptr, svc::ResultNotFound()); + /* Check that the object is closed. */ + R_UNLESS(derived->IsServerClosed(), svc::ResultInvalidState()); + return Delete(obj.GetPointerUnsafe(), name); } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_port.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_port.hpp index 6182ab537..2929fad62 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_port.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_port.hpp @@ -53,6 +53,11 @@ namespace ams::kern { uintptr_t GetName() const { return m_name; } bool IsLight() const { return m_is_light; } + bool IsServerClosed() const { + KScopedSchedulerLock sl; + return m_state == State::ServerClosed; + } + Result EnqueueSession(KServerSession *session); Result EnqueueSession(KLightServerSession *session); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_session.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_session.hpp index c00b9dd63..2173c3964 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_session.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_session.hpp @@ -37,14 +37,22 @@ namespace ams::kern { private: KServerSession m_server; KClientSession m_client; - State m_state; + std::atomic::type> m_atomic_state; KClientPort *m_port; uintptr_t m_name; KProcess *m_process; bool m_initialized; + private: + ALWAYS_INLINE void SetState(State state) { + m_atomic_state = static_cast(state); + } + + ALWAYS_INLINE State GetState() const { + return static_cast(m_atomic_state.load()); + } public: constexpr KSession() - : m_server(), m_client(), m_state(State::Invalid), m_port(), m_name(), m_process(), m_initialized() + : m_server(), m_client(), m_atomic_state(static_cast::type>(State::Invalid)), m_port(), m_name(), m_process(), m_initialized() { /* ... */ } @@ -62,8 +70,8 @@ namespace ams::kern { void OnServerClosed(); void OnClientClosed(); - bool IsServerClosed() const { return m_state != State::Normal; } - bool IsClientClosed() const { return m_state != State::Normal; } + bool IsServerClosed() const { return this->GetState() != State::Normal; } + bool IsClientClosed() const { return this->GetState() != State::Normal; } Result OnRequest(KSessionRequest *request) { return m_server.OnRequest(request); } diff --git a/libraries/libmesosphere/source/kern_k_client_port.cpp b/libraries/libmesosphere/source/kern_k_client_port.cpp index 963a0bafd..76ad3a373 100644 --- a/libraries/libmesosphere/source/kern_k_client_port.cpp +++ b/libraries/libmesosphere/source/kern_k_client_port.cpp @@ -42,6 +42,10 @@ namespace ams::kern { return this->GetParent()->IsLight(); } + bool KClientPort::IsServerClosed() const { + return this->GetParent()->IsServerClosed(); + } + void KClientPort::Destroy() { /* Note with our parent that we're closed. */ m_parent->OnClientClosed(); diff --git a/libraries/libmesosphere/source/kern_k_server_port.cpp b/libraries/libmesosphere/source/kern_k_server_port.cpp index e581a257b..1e2909240 100644 --- a/libraries/libmesosphere/source/kern_k_server_port.cpp +++ b/libraries/libmesosphere/source/kern_k_server_port.cpp @@ -40,7 +40,7 @@ namespace ams::kern { KServerSession *session = nullptr; { KScopedSchedulerLock sl; - while (!m_session_list.empty()) { + if (!m_session_list.empty()) { session = std::addressof(m_session_list.front()); m_session_list.pop_front(); } @@ -60,7 +60,7 @@ namespace ams::kern { KLightServerSession *session = nullptr; { KScopedSchedulerLock sl; - while (!m_light_session_list.empty()) { + if (!m_light_session_list.empty()) { session = std::addressof(m_light_session_list.front()); m_light_session_list.pop_front(); } diff --git a/libraries/libmesosphere/source/kern_k_session.cpp b/libraries/libmesosphere/source/kern_k_session.cpp index 88906469f..801be4afc 100644 --- a/libraries/libmesosphere/source/kern_k_session.cpp +++ b/libraries/libmesosphere/source/kern_k_session.cpp @@ -35,7 +35,7 @@ namespace ams::kern { m_client.Initialize(this); /* Set state and name. */ - m_state = State::Normal; + this->SetState(State::Normal); m_name = name; /* Set our owner process. */ @@ -62,8 +62,8 @@ namespace ams::kern { void KSession::OnServerClosed() { MESOSPHERE_ASSERT_THIS(); - if (m_state == State::Normal) { - m_state = State::ServerClosed; + if (this->GetState() == State::Normal) { + this->SetState(State::ServerClosed); m_client.OnServerClosed(); } } @@ -71,8 +71,8 @@ namespace ams::kern { void KSession::OnClientClosed() { MESOSPHERE_ASSERT_THIS(); - if (m_state == State::Normal) { - m_state = State::ClientClosed; + if (this->GetState() == State::Normal) { + this->SetState(State::ClientClosed); m_server.OnClientClosed(); } }