From 7444963bbb300cff269e410948de7fa577f5ff16 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Apr 2021 17:48:37 -0700 Subject: hle: kernel: Migrate KSession, KClientSession, and KServerSession to KAutoObject. --- src/core/CMakeLists.txt | 12 +- src/core/hle/ipc_helpers.h | 12 +- src/core/hle/kernel/client_port.cpp | 14 +-- src/core/hle/kernel/client_port.h | 4 +- src/core/hle/kernel/client_session.cpp | 52 --------- src/core/hle/kernel/client_session.h | 68 ----------- src/core/hle/kernel/handle_table.cpp | 5 +- src/core/hle/kernel/hle_ipc.cpp | 23 ++-- src/core/hle/kernel/hle_ipc.h | 18 ++- src/core/hle/kernel/init/init_slab_setup.cpp | 4 +- src/core/hle/kernel/k_client_session.cpp | 31 +++++ src/core/hle/kernel/k_client_session.h | 80 +++++++++++++ src/core/hle/kernel/k_server_session.cpp | 164 +++++++++++++++++++++++++++ src/core/hle/kernel/k_server_session.h | 148 ++++++++++++++++++++++++ src/core/hle/kernel/k_session.cpp | 67 +++++++++++ src/core/hle/kernel/k_session.h | 108 ++++++++++++++++++ src/core/hle/kernel/kernel.h | 8 ++ src/core/hle/kernel/server_port.cpp | 10 +- src/core/hle/kernel/server_port.h | 8 +- src/core/hle/kernel/server_session.cpp | 157 ------------------------- src/core/hle/kernel/server_session.h | 161 -------------------------- src/core/hle/kernel/service_thread.cpp | 29 +++-- src/core/hle/kernel/service_thread.h | 4 +- src/core/hle/kernel/session.cpp | 41 ------- src/core/hle/kernel/session.h | 64 ----------- src/core/hle/kernel/svc.cpp | 18 ++- src/core/hle/service/am/applets/applets.cpp | 1 - src/core/hle/service/hid/hid.cpp | 1 - src/core/hle/service/mm/mm_u.cpp | 1 - src/core/hle/service/service.h | 5 +- src/core/hle/service/sm/controller.cpp | 8 +- src/core/hle/service/sm/sm.cpp | 22 ++-- src/core/hle/service/sm/sm.h | 5 +- src/core/hle/service/time/time.cpp | 1 - 34 files changed, 705 insertions(+), 649 deletions(-) delete mode 100644 src/core/hle/kernel/client_session.cpp delete mode 100644 src/core/hle/kernel/client_session.h create mode 100644 src/core/hle/kernel/k_client_session.cpp create mode 100644 src/core/hle/kernel/k_client_session.h create mode 100644 src/core/hle/kernel/k_server_session.cpp create mode 100644 src/core/hle/kernel/k_server_session.h create mode 100644 src/core/hle/kernel/k_session.cpp create mode 100644 src/core/hle/kernel/k_session.h delete mode 100644 src/core/hle/kernel/server_session.cpp delete mode 100644 src/core/hle/kernel/server_session.h delete mode 100644 src/core/hle/kernel/session.cpp delete mode 100644 src/core/hle/kernel/session.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 569b4802e..e30a30823 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -146,8 +146,6 @@ add_library(core STATIC hle/kernel/board/nintendo/nx/secure_monitor.h hle/kernel/client_port.cpp hle/kernel/client_port.h - hle/kernel/client_session.cpp - hle/kernel/client_session.h hle/kernel/code_set.cpp hle/kernel/code_set.h hle/kernel/svc_results.h @@ -170,6 +168,8 @@ add_library(core STATIC hle/kernel/k_affinity_mask.h hle/kernel/k_class_token.cpp hle/kernel/k_class_token.h + hle/kernel/k_client_session.cpp + hle/kernel/k_client_session.h hle/kernel/k_condition_variable.cpp hle/kernel/k_condition_variable.h hle/kernel/k_event.cpp @@ -205,6 +205,10 @@ add_library(core STATIC hle/kernel/k_scoped_lock.h hle/kernel/k_scoped_resource_reservation.h hle/kernel/k_scoped_scheduler_lock_and_sleep.h + hle/kernel/k_server_session.cpp + hle/kernel/k_server_session.h + hle/kernel/k_session.cpp + hle/kernel/k_session.h hle/kernel/k_shared_memory.cpp hle/kernel/k_shared_memory.h hle/kernel/k_slab_heap.h @@ -233,12 +237,8 @@ add_library(core STATIC hle/kernel/process_capability.h hle/kernel/server_port.cpp hle/kernel/server_port.h - hle/kernel/server_session.cpp - hle/kernel/server_session.h hle/kernel/service_thread.cpp hle/kernel/service_thread.h - hle/kernel/session.cpp - hle/kernel/session.h hle/kernel/slab_helpers.h hle/kernel/svc.cpp hle/kernel/svc.h diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 8f12616bd..99b7d3d82 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -14,11 +14,9 @@ #include "common/common_types.h" #include "core/hle/ipc.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/k_session.h" #include "core/hle/kernel/object.h" -#include "core/hle/kernel/server_session.h" -#include "core/hle/kernel/session.h" #include "core/hle/result.h" namespace IPC { @@ -137,9 +135,11 @@ public: if (context->Session()->IsDomain()) { context->AddDomainObject(std::move(iface)); } else { - auto [client, server] = Kernel::Session::Create(kernel, iface->GetServiceName()); - context->AddMoveObject(client.get()); - iface->ClientConnected(std::move(client), std::move(server)); + auto* session = Kernel::KSession::Create(kernel); + session->Initialize(iface->GetServiceName()); + + context->AddMoveObject(&session->GetClientSession()); + iface->ClientConnected(session); } } diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index d856b83e3..ce88da1c3 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -3,11 +3,10 @@ // Refer to the license.txt file included. #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/k_session.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/server_port.h" -#include "core/hle/kernel/session.h" #include "core/hle/kernel/svc_results.h" namespace Kernel { @@ -19,21 +18,22 @@ std::shared_ptr ClientPort::GetServerPort() const { return server_port; } -ResultVal> ClientPort::Connect() { +ResultVal ClientPort::Connect() { if (active_sessions >= max_sessions) { return ResultOutOfSessions; } active_sessions++; - auto [client, server] = Kernel::Session::Create(kernel, name); + auto* session = Kernel::KSession::Create(kernel); + session->Initialize(name + ":ClientPort"); if (server_port->HasHLEHandler()) { - server_port->GetHLEHandler()->ClientConnected(client, std::move(server)); + server_port->GetHLEHandler()->ClientConnected(session); } else { - server_port->AppendPendingSession(std::move(server)); + server_port->AppendPendingSession(std::addressof(session->GetServerSession())); } - return MakeResult(std::move(client)); + return MakeResult(std::addressof(session->GetClientSession())); } void ClientPort::ConnectionClosed() { diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index 77559ebf9..0b20fef40 100644 --- a/src/core/hle/kernel/client_port.h +++ b/src/core/hle/kernel/client_port.h @@ -13,7 +13,7 @@ namespace Kernel { -class ClientSession; +class KClientSession; class KernelCore; class ServerPort; @@ -43,7 +43,7 @@ public: * waiting on it to awake. * @returns ClientSession The client endpoint of the created Session pair, or error code. */ - ResultVal> Connect(); + ResultVal Connect(); /** * Signifies that a previously active connection has been closed, diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp deleted file mode 100644 index fa9cad498..000000000 --- a/src/core/hle/kernel/client_session.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2019 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/kernel/client_session.h" -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/kernel/server_session.h" -#include "core/hle/kernel/session.h" -#include "core/hle/kernel/svc_results.h" -#include "core/hle/result.h" - -namespace Kernel { - -ClientSession::ClientSession(KernelCore& kernel) : KSynchronizationObject{kernel} {} - -ClientSession::~ClientSession() { - // This destructor will be called automatically when the last ClientSession handle is closed by - // the emulated application. - if (parent->Server()) { - parent->Server()->ClientDisconnected(); - } -} - -bool ClientSession::IsSignaled() const { - UNIMPLEMENTED(); - return true; -} - -ResultVal> ClientSession::Create(KernelCore& kernel, - std::shared_ptr parent, - std::string name) { - std::shared_ptr client_session{std::make_shared(kernel)}; - - client_session->name = std::move(name); - client_session->parent = std::move(parent); - - return MakeResult(std::move(client_session)); -} - -ResultCode ClientSession::SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, - Core::Timing::CoreTiming& core_timing) { - // Keep ServerSession alive until we're done working with it. - if (!parent->Server()) { - return ResultSessionClosed; - } - - // Signal the server session that new data is available - return parent->Server()->HandleSyncRequest(std::move(thread), memory, core_timing); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h deleted file mode 100644 index 7a1d15d0c..000000000 --- a/src/core/hle/kernel/client_session.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2019 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include - -#include "core/hle/kernel/k_synchronization_object.h" -#include "core/hle/result.h" - -union ResultCode; - -namespace Core::Memory { -class Memory; -} - -namespace Core::Timing { -class CoreTiming; -} - -namespace Kernel { - -class KernelCore; -class Session; -class KThread; - -class ClientSession final : public KSynchronizationObject { -public: - explicit ClientSession(KernelCore& kernel); - ~ClientSession() override; - - friend class Session; - - std::string GetTypeName() const override { - return "ClientSession"; - } - - std::string GetName() const override { - return name; - } - - static constexpr HandleType HANDLE_TYPE = HandleType::ClientSession; - HandleType GetHandleType() const override { - return HANDLE_TYPE; - } - - ResultCode SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, - Core::Timing::CoreTiming& core_timing); - - bool IsSignaled() const override; - - void Finalize() override {} - -private: - static ResultVal> Create(KernelCore& kernel, - std::shared_ptr parent, - std::string name = "Unknown"); - - /// The parent session, which links to the server endpoint. - std::shared_ptr parent; - - /// Name of the client session (optional) - std::string name; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index adfcd3c5b..ddb1e6fb2 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -56,7 +56,10 @@ ResultVal HandleTable::Create(Object* obj) { case HandleType::Event: case HandleType::Process: case HandleType::ReadableEvent: - case HandleType::WritableEvent: { + case HandleType::WritableEvent: + case HandleType::ClientSession: + case HandleType::ServerSession: + case HandleType::Session: { Handle handle{}; Add(&handle, reinterpret_cast(obj), {}); return MakeResult(handle); diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 1e831aaca..d647d9dd3 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -19,12 +19,12 @@ #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" +#include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_writable_event.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/process.h" -#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/time_manager.h" #include "core/memory.h" @@ -35,24 +35,19 @@ SessionRequestHandler::SessionRequestHandler() = default; SessionRequestHandler::~SessionRequestHandler() = default; -void SessionRequestHandler::ClientConnected(std::shared_ptr client_session, - std::shared_ptr server_session) { - server_session->SetHleHandler(shared_from_this()); - client_sessions.push_back(std::move(client_session)); - server_sessions.push_back(std::move(server_session)); +void SessionRequestHandler::ClientConnected(KSession* session) { + session->GetServerSession().SetHleHandler(shared_from_this()); + sessions.push_back(session); } -void SessionRequestHandler::ClientDisconnected( - const std::shared_ptr& server_session) { - server_session->SetHleHandler(nullptr); - boost::range::remove_erase(server_sessions, server_session); +void SessionRequestHandler::ClientDisconnected(KSession* session) { + session->GetServerSession().SetHleHandler(nullptr); + boost::range::remove_erase(sessions, session); } HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, - std::shared_ptr server_session_, - KThread* thread_) - : server_session(std::move(server_session_)), - thread(thread_), kernel{kernel_}, memory{memory_} { + KServerSession* server_session_, KThread* thread_) + : server_session(server_session_), thread(thread_), kernel{kernel_}, memory{memory_} { cmd_buf[0] = 0; } diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 74a95bc76..dc5c3b47d 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -39,10 +39,10 @@ class HandleTable; class HLERequestContext; class KernelCore; class Process; -class ClientSession; -class ServerSession; +class KServerSession; class KThread; class KReadableEvent; +class KSession; class KWritableEvent; enum class ThreadWakeupReason; @@ -72,22 +72,20 @@ public: * associated ServerSession alive for the duration of the connection. * @param server_session Owning pointer to the ServerSession associated with the connection. */ - void ClientConnected( - std::shared_ptr client_session, std::shared_ptr server_session); + void ClientConnected(KSession* session); /** * Signals that a client has just disconnected from this HLE handler and releases the * associated ServerSession. * @param server_session ServerSession associated with the connection. */ - void ClientDisconnected(const std::shared_ptr& server_session); + void ClientDisconnected(KSession* session); protected: /// List of sessions that are connected to this handler. /// A ServerSession whose server endpoint is an HLE implementation is kept alive by this list /// for the duration of the connection. - std::vector> client_sessions; - std::vector> server_sessions; + std::vector sessions; }; /** @@ -112,7 +110,7 @@ protected: class HLERequestContext { public: explicit HLERequestContext(KernelCore& kernel, Core::Memory::Memory& memory, - std::shared_ptr session, KThread* thread); + KServerSession* session, KThread* thread); ~HLERequestContext(); /// Returns a pointer to the IPC command buffer for this request. @@ -124,7 +122,7 @@ public: * Returns the session through which this request was made. This can be used as a map key to * access per-client data on services. */ - const std::shared_ptr& Session() const { + Kernel::KServerSession* Session() { return server_session; } @@ -288,7 +286,7 @@ private: void ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming); std::array cmd_buf; - std::shared_ptr server_session; + Kernel::KServerSession* server_session{}; KThread* thread; // TODO(yuriks): Check common usage of this and optimize size accordingly diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index b292f7db2..84d509d52 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -12,6 +12,7 @@ #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_memory_manager.h" +#include "core/hle/kernel/k_session.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_system_control.h" #include "core/hle/kernel/k_thread.h" @@ -27,7 +28,8 @@ namespace Kernel::Init { HANDLER(Process, (SLAB_COUNT(Process)), ##__VA_ARGS__) \ HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \ HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \ - HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) + HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ + HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) namespace { diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp new file mode 100644 index 000000000..0618dc246 --- /dev/null +++ b/src/core/hle/kernel/k_client_session.cpp @@ -0,0 +1,31 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_server_session.h" +#include "core/hle/kernel/k_session.h" +#include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/svc_results.h" +#include "core/hle/result.h" + +namespace Kernel { + +KClientSession::KClientSession(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} +KClientSession::~KClientSession() = default; + +void KClientSession::Destroy() { + parent->OnClientClosed(); + parent->Close(); +} + +void KClientSession::OnServerClosed() {} + +ResultCode KClientSession::SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, + Core::Timing::CoreTiming& core_timing) { + // Signal the server session that new data is available + return parent->GetServerSession().HandleSyncRequest(thread, memory, core_timing); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h new file mode 100644 index 000000000..c4b193773 --- /dev/null +++ b/src/core/hle/kernel/k_client_session.h @@ -0,0 +1,80 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "core/hle/kernel/k_auto_object.h" +#include "core/hle/kernel/k_synchronization_object.h" +#include "core/hle/kernel/slab_helpers.h" +#include "core/hle/result.h" + +union ResultCode; + +namespace Core::Memory { +class Memory; +} + +namespace Core::Timing { +class CoreTiming; +} + +namespace Kernel { + +class KernelCore; +class KSession; +class KThread; + +class KClientSession final + : public KAutoObjectWithSlabHeapAndContainer { + KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject); + +public: + explicit KClientSession(KernelCore& kernel); + virtual ~KClientSession(); + + void Initialize(KSession* parent_, std::string&& name_) { + // Set member variables. + parent = parent_; + name = std::move(name_); + } + + virtual void Destroy() override; + static void PostDestroy([[maybe_unused]] uintptr_t arg) {} + + constexpr KSession* GetParent() const { + return parent; + } + + ResultCode SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, + Core::Timing::CoreTiming& core_timing); + + void OnServerClosed(); + + // DEPRECATED + + static constexpr HandleType HANDLE_TYPE = HandleType::ClientSession; + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } + + std::string GetTypeName() const override { + return "ClientSession"; + } + + std::string GetName() const override { + return name; + } + +private: + /// The parent session, which links to the server endpoint. + KSession* parent{}; + + /// Name of the client session (optional) + std::string name; +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp new file mode 100644 index 000000000..8cd2c283c --- /dev/null +++ b/src/core/hle/kernel/k_server_session.cpp @@ -0,0 +1,164 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include + +#include "common/assert.h" +#include "common/common_types.h" +#include "common/logging/log.h" +#include "core/core_timing.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/handle_table.h" +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/k_server_session.h" +#include "core/hle/kernel/k_session.h" +#include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/process.h" +#include "core/memory.h" + +namespace Kernel { + +KServerSession::KServerSession(KernelCore& kernel) : KSynchronizationObject{kernel} {} + +KServerSession::~KServerSession() { + kernel.ReleaseServiceThread(service_thread); +} + +void KServerSession::Initialize(KSession* parent_, std::string&& name_) { + // Set member variables. + parent = parent_; + name = std::move(name_); + service_thread = kernel.CreateServiceThread(name); +} + +void KServerSession::Destroy() { + parent->OnServerClosed(); + + parent->Close(); +} + +void KServerSession::OnClientClosed() { + // We keep a shared pointer to the hle handler to keep it alive throughout + // the call to ClientDisconnected, as ClientDisconnected invalidates the + // hle_handler member itself during the course of the function executing. + std::shared_ptr handler = hle_handler; + if (handler) { + // Note that after this returns, this server session's hle_handler is + // invalidated (set to null). + handler->ClientDisconnected(parent); + } +} + +bool KServerSession::IsSignaled() const { + ASSERT(kernel.GlobalSchedulerContext().IsLocked()); + + // If the client is closed, we're always signaled. + if (parent->IsClientClosed()) { + return true; + } + + // Otherwise, we're signaled if we have a request and aren't handling one. + return false; +} + +void KServerSession::AppendDomainRequestHandler(std::shared_ptr handler) { + domain_request_handlers.push_back(std::move(handler)); +} + +std::size_t KServerSession::NumDomainRequestHandlers() const { + return domain_request_handlers.size(); +} + +ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { + if (!context.HasDomainMessageHeader()) { + return RESULT_SUCCESS; + } + + // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs + context.SetDomainRequestHandlers(domain_request_handlers); + + // If there is a DomainMessageHeader, then this is CommandType "Request" + const auto& domain_message_header = context.GetDomainMessageHeader(); + const u32 object_id{domain_message_header.object_id}; + switch (domain_message_header.command) { + case IPC::DomainMessageHeader::CommandType::SendMessage: + if (object_id > domain_request_handlers.size()) { + LOG_CRITICAL(IPC, + "object_id {} is too big! This probably means a recent service call " + "to {} needed to return a new interface!", + object_id, name); + UNREACHABLE(); + return RESULT_SUCCESS; // Ignore error if asserts are off + } + return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); + + case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { + LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); + + domain_request_handlers[object_id - 1] = nullptr; + + IPC::ResponseBuilder rb{context, 2}; + rb.Push(RESULT_SUCCESS); + return RESULT_SUCCESS; + } + } + + LOG_CRITICAL(IPC, "Unknown domain command={}", domain_message_header.command.Value()); + ASSERT(false); + return RESULT_SUCCESS; +} + +ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) { + u32* cmd_buf{reinterpret_cast(memory.GetPointer(thread->GetTLSAddress()))}; + auto context = std::make_shared(kernel, memory, this, thread); + + context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); + + if (auto strong_ptr = service_thread.lock()) { + strong_ptr->QueueSyncRequest(*parent, std::move(context)); + return RESULT_SUCCESS; + } + + return RESULT_SUCCESS; +} + +ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { + ResultCode result = RESULT_SUCCESS; + // If the session has been converted to a domain, handle the domain request + if (IsDomain() && context.HasDomainMessageHeader()) { + result = HandleDomainSyncRequest(context); + // If there is no domain header, the regular session handler is used + } else if (hle_handler != nullptr) { + // If this ServerSession has an associated HLE handler, forward the request to it. + result = hle_handler->HandleSyncRequest(context); + } + + if (convert_to_domain) { + ASSERT_MSG(IsSession(), "ServerSession is already a domain instance."); + domain_request_handlers = {hle_handler}; + convert_to_domain = false; + } + + // Some service requests require the thread to block + { + KScopedSchedulerLock lock(kernel); + if (!context.IsThreadWaiting()) { + context.GetThread().Wakeup(); + context.GetThread().SetSyncedObject(nullptr, result); + } + } + + return result; +} + +ResultCode KServerSession::HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, + Core::Timing::CoreTiming& core_timing) { + return QueueSyncRequest(thread, memory); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h new file mode 100644 index 000000000..ef81c4e30 --- /dev/null +++ b/src/core/hle/kernel/k_server_session.h @@ -0,0 +1,148 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include + +#include "common/threadsafe_queue.h" +#include "core/hle/kernel/k_synchronization_object.h" +#include "core/hle/kernel/service_thread.h" +#include "core/hle/result.h" + +namespace Core::Memory { +class Memory; +} + +namespace Core::Timing { +class CoreTiming; +struct EventType; +} // namespace Core::Timing + +namespace Kernel { + +class HLERequestContext; +class KernelCore; +class KSession; +class SessionRequestHandler; +class KThread; + +class KServerSession final : public KSynchronizationObject { + KERNEL_AUTOOBJECT_TRAITS(KServerSession, KSynchronizationObject); + + friend class ServiceThread; + +public: + explicit KServerSession(KernelCore& kernel); + virtual ~KServerSession() override; + + virtual void Destroy() override; + + void Initialize(KSession* parent_, std::string&& name_); + + constexpr KSession* GetParent() { + return parent; + } + + constexpr const KSession* GetParent() const { + return parent; + } + + virtual bool IsSignaled() const override; + + void OnClientClosed(); + + /** + * Sets the HLE handler for the session. This handler will be called to service IPC requests + * instead of the regular IPC machinery. (The regular IPC machinery is currently not + * implemented.) + */ + void SetHleHandler(std::shared_ptr hle_handler_) { + hle_handler = std::move(hle_handler_); + } + + /** + * Handle a sync request from the emulated application. + * + * @param thread Thread that initiated the request. + * @param memory Memory context to handle the sync request under. + * @param core_timing Core timing context to schedule the request event under. + * + * @returns ResultCode from the operation. + */ + ResultCode HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, + Core::Timing::CoreTiming& core_timing); + + /// Adds a new domain request handler to the collection of request handlers within + /// this ServerSession instance. + void AppendDomainRequestHandler(std::shared_ptr handler); + + /// Retrieves the total number of domain request handlers that have been + /// appended to this ServerSession instance. + std::size_t NumDomainRequestHandlers() const; + + /// Returns true if the session has been converted to a domain, otherwise False + bool IsDomain() const { + return !IsSession(); + } + + /// Returns true if this session has not been converted to a domain, otherwise false. + bool IsSession() const { + return domain_request_handlers.empty(); + } + + /// Converts the session to a domain at the end of the current command + void ConvertToDomain() { + convert_to_domain = true; + } + + // DEPRECATED + + std::string GetTypeName() const override { + return "ServerSession"; + } + + std::string GetName() const override { + return name; + } + + static constexpr HandleType HANDLE_TYPE = HandleType::ServerSession; + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } + +private: + /// Queues a sync request from the emulated application. + ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); + + /// Completes a sync request from the emulated application. + ResultCode CompleteSyncRequest(HLERequestContext& context); + + /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an + /// object handle. + ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); + + /// This session's HLE request handler (applicable when not a domain) + std::shared_ptr hle_handler; + + /// This is the list of domain request handlers (after conversion to a domain) + std::vector> domain_request_handlers; + + /// When set to True, converts the session to a domain at the end of the command + bool convert_to_domain{}; + + /// The name of this session (optional) + std::string name; + + /// Thread to dispatch service requests + std::weak_ptr service_thread; + + /// KSession that owns this KServerSession + KSession* parent{}; +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp new file mode 100644 index 000000000..ca1cf18cd --- /dev/null +++ b/src/core/hle/kernel/k_session.cpp @@ -0,0 +1,67 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_scoped_resource_reservation.h" +#include "core/hle/kernel/k_server_session.h" +#include "core/hle/kernel/k_session.h" + +namespace Kernel { + +KSession::KSession(KernelCore& kernel) + : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {} +KSession::~KSession() = default; + +void KSession::Initialize(std::string&& name_) { + // Increment reference count. + // Because reference count is one on creation, this will result + // in a reference count of two. Thus, when both server and client are closed + // this object will be destroyed. + Open(); + + // Create our sub sessions. + KAutoObject::Create(std::addressof(server)); + KAutoObject::Create(std::addressof(client)); + + // Initialize our sub sessions. + server.Initialize(this, name_ + ":Server"); + client.Initialize(this, name_ + ":Client"); + + // Set state and name. + SetState(State::Normal); + name = std::move(name_); + + // Set our owner process. + process = kernel.CurrentProcess(); + process->Open(); + + // Mark initialized. + initialized = true; +} + +void KSession::Finalize() {} + +void KSession::OnServerClosed() { + if (GetState() == State::Normal) { + SetState(State::ServerClosed); + client.OnServerClosed(); + } +} + +void KSession::OnClientClosed() { + if (GetState() == State::Normal) { + SetState(State::ClientClosed); + server.OnClientClosed(); + } +} + +void KSession::PostDestroy(uintptr_t arg) { + // Release the session count resource the owner process holds. + Process* owner = reinterpret_cast(arg); + owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1); + owner->Close(); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h new file mode 100644 index 000000000..1d24e80cd --- /dev/null +++ b/src/core/hle/kernel/k_session.h @@ -0,0 +1,108 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_server_session.h" +#include "core/hle/kernel/slab_helpers.h" + +namespace Kernel { + +class KSession final : public KAutoObjectWithSlabHeapAndContainer { + KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject); + +private: + enum class State : u8 { + Invalid = 0, + Normal = 1, + ClientClosed = 2, + ServerClosed = 3, + }; + +public: + explicit KSession(KernelCore& kernel); + virtual ~KSession() override; + + void Initialize(std::string&& name_); + + virtual void Finalize() override; + + virtual bool IsInitialized() const override { + return initialized; + } + + virtual uintptr_t GetPostDestroyArgument() const override { + return reinterpret_cast(process); + } + + static void PostDestroy(uintptr_t arg); + + void OnServerClosed(); + + void OnClientClosed(); + + bool IsServerClosed() const { + return this->GetState() != State::Normal; + } + + bool IsClientClosed() const { + return this->GetState() != State::Normal; + } + + KClientSession& GetClientSession() { + return client; + } + + KServerSession& GetServerSession() { + return server; + } + + const KClientSession& GetClientSession() const { + return client; + } + + const KServerSession& GetServerSession() const { + return server; + } + + const ClientPort* GetParent() const { + return port; + } + + // DEPRECATED + + std::string GetName() const override { + return name; + } + + static constexpr HandleType HANDLE_TYPE = HandleType::Session; + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } + +private: + void SetState(State state) { + atomic_state = static_cast(state); + } + + State GetState() const { + return static_cast(atomic_state.load()); + } + +private: + KServerSession server; + KClientSession client; + std::atomic::type> atomic_state{ + static_cast::type>(State::Invalid)}; + ClientPort* port{}; + std::string name; + Process* process{}; + bool initialized{}; +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 850436eb3..ecced1034 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -33,11 +33,13 @@ class ClientPort; class GlobalSchedulerContext; class HandleTable; class KAutoObjectWithListContainer; +class KClientSession; class KEvent; class KLinkedListNode; class KMemoryManager; class KResourceLimit; class KScheduler; +class KSession; class KSharedMemory; class KThread; class KWritableEvent; @@ -272,6 +274,10 @@ public: return slab_heap_container->linked_list_node; } else if constexpr (std::is_same_v) { return slab_heap_container->writeable_event; + } else if constexpr (std::is_same_v) { + return slab_heap_container->client_session; + } else if constexpr (std::is_same_v) { + return slab_heap_container->session; } } @@ -312,6 +318,8 @@ private: KSlabHeap shared_memory; KSlabHeap linked_list_node; KSlabHeap writeable_event; + KSlabHeap client_session; + KSlabHeap session; }; std::unique_ptr slab_heap_container; diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index 5d17346ad..8626b56fd 100644 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp @@ -5,10 +5,10 @@ #include #include "common/assert.h" #include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/server_port.h" -#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/svc_results.h" namespace Kernel { @@ -16,17 +16,17 @@ namespace Kernel { ServerPort::ServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} ServerPort::~ServerPort() = default; -ResultVal> ServerPort::Accept() { +ResultVal ServerPort::Accept() { if (pending_sessions.empty()) { return ResultNotFound; } - auto session = std::move(pending_sessions.back()); + auto* session = pending_sessions.back(); pending_sessions.pop_back(); - return MakeResult(std::move(session)); + return MakeResult(session); } -void ServerPort::AppendPendingSession(std::shared_ptr pending_session) { +void ServerPort::AppendPendingSession(KServerSession* pending_session) { pending_sessions.push_back(std::move(pending_session)); if (pending_sessions.size() == 1) { NotifyAvailable(); diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h index 29b4f2509..eebceaa2a 100644 --- a/src/core/hle/kernel/server_port.h +++ b/src/core/hle/kernel/server_port.h @@ -17,7 +17,7 @@ namespace Kernel { class ClientPort; class KernelCore; -class ServerSession; +class KServerSession; class SessionRequestHandler; class ServerPort final : public KSynchronizationObject { @@ -55,7 +55,7 @@ public: * Accepts a pending incoming connection on this port. If there are no pending sessions, will * return ERR_NO_PENDING_SESSIONS. */ - ResultVal> Accept(); + ResultVal Accept(); /// Whether or not this server port has an HLE handler available. bool HasHLEHandler() const { @@ -77,7 +77,7 @@ public: /// Appends a ServerSession to the collection of ServerSessions /// waiting to be accepted by this port. - void AppendPendingSession(std::shared_ptr pending_session); + void AppendPendingSession(KServerSession* pending_session); bool IsSignaled() const override; @@ -85,7 +85,7 @@ public: private: /// ServerSessions waiting to be accepted by the port - std::vector> pending_sessions; + std::vector pending_sessions; /// This session's HLE request handler template (optional) /// ServerSessions created from this port inherit a reference to this handler. diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp deleted file mode 100644 index bb247959c..000000000 --- a/src/core/hle/kernel/server_session.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2019 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include - -#include "common/assert.h" -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/core_timing.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" -#include "core/hle/kernel/handle_table.h" -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/process.h" -#include "core/hle/kernel/server_session.h" -#include "core/hle/kernel/session.h" -#include "core/memory.h" - -namespace Kernel { - -ServerSession::ServerSession(KernelCore& kernel) : KSynchronizationObject{kernel} {} - -ServerSession::~ServerSession() { - kernel.ReleaseServiceThread(service_thread); -} - -ResultVal> ServerSession::Create(KernelCore& kernel, - std::shared_ptr parent, - std::string name) { - std::shared_ptr session{std::make_shared(kernel)}; - - session->name = std::move(name); - session->parent = std::move(parent); - session->service_thread = kernel.CreateServiceThread(session->name); - - return MakeResult(std::move(session)); -} - -bool ServerSession::IsSignaled() const { - // Closed sessions should never wait, an error will be returned from svcReplyAndReceive. - return !parent->Client(); -} - -void ServerSession::ClientDisconnected() { - // We keep a shared pointer to the hle handler to keep it alive throughout - // the call to ClientDisconnected, as ClientDisconnected invalidates the - // hle_handler member itself during the course of the function executing. - std::shared_ptr handler = hle_handler; - if (handler) { - // Note that after this returns, this server session's hle_handler is - // invalidated (set to null). - handler->ClientDisconnected(SharedFrom(this)); - } -} - -void ServerSession::AppendDomainRequestHandler(std::shared_ptr handler) { - domain_request_handlers.push_back(std::move(handler)); -} - -std::size_t ServerSession::NumDomainRequestHandlers() const { - return domain_request_handlers.size(); -} - -ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { - if (!context.HasDomainMessageHeader()) { - return RESULT_SUCCESS; - } - - // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs - context.SetDomainRequestHandlers(domain_request_handlers); - - // If there is a DomainMessageHeader, then this is CommandType "Request" - const auto& domain_message_header = context.GetDomainMessageHeader(); - const u32 object_id{domain_message_header.object_id}; - switch (domain_message_header.command) { - case IPC::DomainMessageHeader::CommandType::SendMessage: - if (object_id > domain_request_handlers.size()) { - LOG_CRITICAL(IPC, - "object_id {} is too big! This probably means a recent service call " - "to {} needed to return a new interface!", - object_id, name); - UNREACHABLE(); - return RESULT_SUCCESS; // Ignore error if asserts are off - } - return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); - - case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { - LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); - - domain_request_handlers[object_id - 1] = nullptr; - - IPC::ResponseBuilder rb{context, 2}; - rb.Push(RESULT_SUCCESS); - return RESULT_SUCCESS; - } - } - - LOG_CRITICAL(IPC, "Unknown domain command={}", domain_message_header.command.Value()); - ASSERT(false); - return RESULT_SUCCESS; -} - -ResultCode ServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) { - u32* cmd_buf{reinterpret_cast(memory.GetPointer(thread->GetTLSAddress()))}; - auto context = std::make_shared(kernel, memory, SharedFrom(this), thread); - - context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); - - if (auto strong_ptr = service_thread.lock()) { - strong_ptr->QueueSyncRequest(*this, std::move(context)); - return RESULT_SUCCESS; - } - - return RESULT_SUCCESS; -} - -ResultCode ServerSession::CompleteSyncRequest(HLERequestContext& context) { - ResultCode result = RESULT_SUCCESS; - // If the session has been converted to a domain, handle the domain request - if (IsDomain() && context.HasDomainMessageHeader()) { - result = HandleDomainSyncRequest(context); - // If there is no domain header, the regular session handler is used - } else if (hle_handler != nullptr) { - // If this ServerSession has an associated HLE handler, forward the request to it. - result = hle_handler->HandleSyncRequest(context); - } - - if (convert_to_domain) { - ASSERT_MSG(IsSession(), "ServerSession is already a domain instance."); - domain_request_handlers = {hle_handler}; - convert_to_domain = false; - } - - // Some service requests require the thread to block - { - KScopedSchedulerLock lock(kernel); - if (!context.IsThreadWaiting()) { - context.GetThread().Wakeup(); - context.GetThread().SetSyncedObject(nullptr, result); - } - } - - return result; -} - -ResultCode ServerSession::HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, - Core::Timing::CoreTiming& core_timing) { - return QueueSyncRequest(thread, memory); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h deleted file mode 100644 index 77ed18c60..000000000 --- a/src/core/hle/kernel/server_session.h +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2019 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include - -#include "common/threadsafe_queue.h" -#include "core/hle/kernel/k_synchronization_object.h" -#include "core/hle/kernel/service_thread.h" -#include "core/hle/result.h" - -namespace Core::Memory { -class Memory; -} - -namespace Core::Timing { -class CoreTiming; -struct EventType; -} // namespace Core::Timing - -namespace Kernel { - -class HLERequestContext; -class KernelCore; -class Session; -class SessionRequestHandler; -class KThread; - -/** - * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS - * primitive for communication between different processes, and are used to implement service calls - * to the various system services. - * - * To make a service call, the client must write the command header and parameters to the buffer - * located at offset 0x80 of the TLS (Thread-Local Storage) area, then execute a SendSyncRequest - * SVC call with its ClientSession handle. The kernel will read the command header, using it to - * marshall the parameters to the process at the server endpoint of the session. - * After the server replies to the request, the response is marshalled back to the caller's - * TLS buffer and control is transferred back to it. - */ -class ServerSession final : public KSynchronizationObject { - friend class ServiceThread; - -public: - explicit ServerSession(KernelCore& kernel); - ~ServerSession() override; - - friend class Session; - - static ResultVal> Create(KernelCore& kernel, - std::shared_ptr parent, - std::string name = "Unknown"); - - std::string GetTypeName() const override { - return "ServerSession"; - } - - std::string GetName() const override { - return name; - } - - static constexpr HandleType HANDLE_TYPE = HandleType::ServerSession; - HandleType GetHandleType() const override { - return HANDLE_TYPE; - } - - Session* GetParent() { - return parent.get(); - } - - const Session* GetParent() const { - return parent.get(); - } - - /** - * Sets the HLE handler for the session. This handler will be called to service IPC requests - * instead of the regular IPC machinery. (The regular IPC machinery is currently not - * implemented.) - */ - void SetHleHandler(std::shared_ptr hle_handler_) { - hle_handler = std::move(hle_handler_); - } - - /** - * Handle a sync request from the emulated application. - * - * @param thread Thread that initiated the request. - * @param memory Memory context to handle the sync request under. - * @param core_timing Core timing context to schedule the request event under. - * - * @returns ResultCode from the operation. - */ - ResultCode HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, - Core::Timing::CoreTiming& core_timing); - - /// Called when a client disconnection occurs. - void ClientDisconnected(); - - /// Adds a new domain request handler to the collection of request handlers within - /// this ServerSession instance. - void AppendDomainRequestHandler(std::shared_ptr handler); - - /// Retrieves the total number of domain request handlers that have been - /// appended to this ServerSession instance. - std::size_t NumDomainRequestHandlers() const; - - /// Returns true if the session has been converted to a domain, otherwise False - bool IsDomain() const { - return !IsSession(); - } - - /// Returns true if this session has not been converted to a domain, otherwise false. - bool IsSession() const { - return domain_request_handlers.empty(); - } - - /// Converts the session to a domain at the end of the current command - void ConvertToDomain() { - convert_to_domain = true; - } - - bool IsSignaled() const override; - - void Finalize() override {} - -private: - /// Queues a sync request from the emulated application. - ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); - - /// Completes a sync request from the emulated application. - ResultCode CompleteSyncRequest(HLERequestContext& context); - - /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an - /// object handle. - ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); - - /// The parent session, which links to the client endpoint. - std::shared_ptr parent; - - /// This session's HLE request handler (applicable when not a domain) - std::shared_ptr hle_handler; - - /// This is the list of domain request handlers (after conversion to a domain) - std::vector> domain_request_handlers; - - /// When set to True, converts the session to a domain at the end of the command - bool convert_to_domain{}; - - /// The name of this session (optional) - std::string name; - - /// Thread to dispatch service requests - std::weak_ptr service_thread; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index ee46f3e21..04be8a502 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp @@ -13,8 +13,8 @@ #include "common/scope_exit.h" #include "common/thread.h" #include "core/core.h" +#include "core/hle/kernel/k_session.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/service_thread.h" #include "core/hle/lock.h" #include "video_core/renderer_base.h" @@ -26,7 +26,7 @@ public: explicit Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name); ~Impl(); - void QueueSyncRequest(ServerSession& session, std::shared_ptr&& context); + void QueueSyncRequest(KSession& session, std::shared_ptr&& context); private: std::vector threads; @@ -69,18 +69,27 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std }); } -void ServiceThread::Impl::QueueSyncRequest(ServerSession& session, +void ServiceThread::Impl::QueueSyncRequest(KSession& session, std::shared_ptr&& context) { { std::unique_lock lock{queue_mutex}; - // ServerSession owns the service thread, so we cannot caption a strong pointer here in the - // event that the ServerSession is terminated. - std::weak_ptr weak_ptr{SharedFrom(&session)}; - requests.emplace([weak_ptr, context{std::move(context)}]() { - if (auto strong_ptr = weak_ptr.lock()) { - strong_ptr->CompleteSyncRequest(*context); + // Open a reference to the session to ensure it is not closes while the service request + // completes asynchronously. + session.Open(); + + requests.emplace([session_ptr{&session}, context{std::move(context)}]() { + // Close the reference. + SCOPE_EXIT({ session_ptr->Close(); }); + + // If the session has been closed, we are done. + if (session_ptr->IsServerClosed()) { + return; } + + // Complete the service request. + KScopedAutoObject server_session{&session_ptr->GetServerSession()}; + server_session->CompleteSyncRequest(*context); }); } condition.notify_one(); @@ -102,7 +111,7 @@ ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads, const ServiceThread::~ServiceThread() = default; -void ServiceThread::QueueSyncRequest(ServerSession& session, +void ServiceThread::QueueSyncRequest(KSession& session, std::shared_ptr&& context) { impl->QueueSyncRequest(session, std::move(context)); } diff --git a/src/core/hle/kernel/service_thread.h b/src/core/hle/kernel/service_thread.h index 025ab8fb5..6a7fd7c56 100644 --- a/src/core/hle/kernel/service_thread.h +++ b/src/core/hle/kernel/service_thread.h @@ -11,14 +11,14 @@ namespace Kernel { class HLERequestContext; class KernelCore; -class ServerSession; +class KSession; class ServiceThread final { public: explicit ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name); ~ServiceThread(); - void QueueSyncRequest(ServerSession& session, std::shared_ptr&& context); + void QueueSyncRequest(KSession& session, std::shared_ptr&& context); private: class Impl; diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp deleted file mode 100644 index 8830d4e91..000000000 --- a/src/core/hle/kernel/session.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2019 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/assert.h" -#include "core/hle/kernel/client_session.h" -#include "core/hle/kernel/k_scoped_resource_reservation.h" -#include "core/hle/kernel/server_session.h" -#include "core/hle/kernel/session.h" - -namespace Kernel { - -Session::Session(KernelCore& kernel) : KSynchronizationObject{kernel} {} -Session::~Session() { - // Release reserved resource when the Session pair was created. - kernel.GetSystemResourceLimit()->Release(LimitableResource::Sessions, 1); -} - -Session::SessionPair Session::Create(KernelCore& kernel, std::string name) { - // Reserve a new session from the resource limit. - KScopedResourceReservation session_reservation(kernel.GetSystemResourceLimit(), - LimitableResource::Sessions); - ASSERT(session_reservation.Succeeded()); - auto session{std::make_shared(kernel)}; - auto client_session{Kernel::ClientSession::Create(kernel, session, name + "_Client").Unwrap()}; - auto server_session{Kernel::ServerSession::Create(kernel, session, name + "_Server").Unwrap()}; - - session->name = std::move(name); - session->client = client_session; - session->server = server_session; - - session_reservation.Commit(); - return std::make_pair(std::move(client_session), std::move(server_session)); -} - -bool Session::IsSignaled() const { - UNIMPLEMENTED(); - return true; -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h deleted file mode 100644 index fa3c5651a..000000000 --- a/src/core/hle/kernel/session.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2019 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include - -#include "core/hle/kernel/k_synchronization_object.h" - -namespace Kernel { - -class ClientSession; -class ServerSession; - -/** - * Parent structure to link the client and server endpoints of a session with their associated - * client port. - */ -class Session final : public KSynchronizationObject { -public: - explicit Session(KernelCore& kernel); - ~Session() override; - - using SessionPair = std::pair, std::shared_ptr>; - - static SessionPair Create(KernelCore& kernel, std::string name = "Unknown"); - - std::string GetName() const override { - return name; - } - - static constexpr HandleType HANDLE_TYPE = HandleType::Session; - HandleType GetHandleType() const override { - return HANDLE_TYPE; - } - - bool IsSignaled() const override; - - void Finalize() override {} - - std::shared_ptr Client() { - if (auto result{client.lock()}) { - return result; - } - return {}; - } - - std::shared_ptr Server() { - if (auto result{server.lock()}) { - return result; - } - return {}; - } - -private: - std::string name; - std::weak_ptr client; - std::weak_ptr server; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index b83ee3e69..28c45e8a3 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -22,9 +22,9 @@ #include "core/core_timing_util.h" #include "core/cpu_manager.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_address_arbiter.h" +#include "core/hle/kernel/k_client_session.h" #include "core/hle/kernel/k_condition_variable.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_memory_block.h" @@ -323,12 +323,12 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, auto client_port = it->second; - std::shared_ptr client_session; + KClientSession* client_session{}; CASCADE_RESULT(client_session, client_port->Connect()); // Return the client session auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - CASCADE_RESULT(*out_handle, handle_table.Create(client_session.get())); + CASCADE_RESULT(*out_handle, handle_table.Create(client_session)); return RESULT_SUCCESS; } @@ -340,15 +340,13 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, /// Makes a blocking IPC call to an OS service. static ResultCode SendSyncRequest(Core::System& system, Handle handle) { + LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); + auto& kernel = system.Kernel(); - const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - auto session = handle_table.Get(handle); - if (!session) { - LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); - return ResultInvalidHandle; - } - LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); + KScopedAutoObject session = + kernel.CurrentProcess()->GetHandleTable().GetObject(handle); + R_UNLESS(session.IsNotNull(), ResultInvalidHandle); auto thread = kernel.CurrentScheduler()->GetCurrentThread(); { diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index cf8ad7598..ae995df6b 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -14,7 +14,6 @@ #include "core/frontend/applets/web_browser.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_writable_event.h" -#include "core/hle/kernel/server_session.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_oe.h" diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 49c1db42a..6b3ebeb8f 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -14,7 +14,6 @@ #include "core/hardware_properties.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_writable_event.h" diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp index b0cb07d24..c8519e2db 100644 --- a/src/core/hle/service/mm/mm_u.cpp +++ b/src/core/hle/service/mm/mm_u.cpp @@ -4,7 +4,6 @@ #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/service/mm/mm_u.h" #include "core/hle/service/sm/sm.h" diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 916445517..076f50b0b 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -21,11 +21,8 @@ class System; } namespace Kernel { -class ClientPort; -class ServerPort; -class ServerSession; class HLERequestContext; -} // namespace Kernel +} namespace Service { diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index b34fe4bc2..cb397fcc7 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp @@ -5,9 +5,9 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/client_session.h" -#include "core/hle/kernel/server_session.h" -#include "core/hle/kernel/session.h" +#include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_server_session.h" +#include "core/hle/kernel/k_session.h" #include "core/hle/service/sm/controller.h" namespace Service::SM { @@ -30,7 +30,7 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; rb.Push(RESULT_SUCCESS); - rb.PushMoveObjects(ctx.Session()->GetParent()->Client().get()); + rb.PushMoveObjects(ctx.Session()->GetParent()->GetClientSession()); } void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 62f7a5358..66e41277f 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -7,7 +7,9 @@ #include "core/core.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" +#include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_server_session.h" +#include "core/hle/kernel/k_session.h" #include "core/hle/kernel/server_port.h" #include "core/hle/result.h" #include "core/hle/service/sm/controller.h" @@ -89,13 +91,6 @@ ResultVal> ServiceManager::GetServicePort( return MakeResult(it->second); } -ResultVal> ServiceManager::ConnectToService( - const std::string& name) { - - CASCADE_RESULT(auto client_port, GetServicePort(name)); - return client_port->Connect(); -} - SM::~SM() = default; /** @@ -130,19 +125,20 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { return; } - auto [client, server] = Kernel::Session::Create(kernel, name); + auto* session = Kernel::KSession::Create(kernel); + session->Initialize(std::move(name)); const auto& server_port = client_port.Unwrap()->GetServerPort(); if (server_port->GetHLEHandler()) { - server_port->GetHLEHandler()->ClientConnected(client, server); + server_port->GetHLEHandler()->ClientConnected(session); } else { - server_port->AppendPendingSession(server); + server_port->AppendPendingSession(&session->GetServerSession()); } - LOG_DEBUG(Service_SM, "called service={} -> session={}", name, client->GetObjectId()); + LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetObjectId()); IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; rb.Push(RESULT_SUCCESS); - rb.PushMoveObjects(client.get()); + rb.PushMoveObjects(session->GetClientSession()); } void SM::RegisterService(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 3f46ae44f..8f6862fa9 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -22,7 +22,7 @@ class System; namespace Kernel { class ClientPort; -class ClientSession; +class KClientSession; class KernelCore; class ServerPort; class SessionRequestHandler; @@ -59,7 +59,6 @@ public: u32 max_sessions); ResultCode UnregisterService(const std::string& name); ResultVal> GetServicePort(const std::string& name); - ResultVal> ConnectToService(const std::string& name); template T> std::shared_ptr GetService(const std::string& service_name) const { @@ -81,7 +80,7 @@ private: std::weak_ptr sm_interface; std::unique_ptr controller_interface; - /// Map of registered services, retrieved using GetServicePort or ConnectToService. + /// Map of registered services, retrieved using GetServicePort. std::unordered_map> registered_services; /// Kernel context diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 30283f239..413a00ae0 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -9,7 +9,6 @@ #include "core/hardware_properties.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/kernel.h" #include "core/hle/service/time/interface.h" -- cgit v1.2.3