From b9a8de7310052721ef481c72cc3e72e420275ee7 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 17 Jun 2016 17:09:43 -0500 Subject: [PATCH] Kernel/HLE: Service::Interface no longer inherits from any Kernel object, and is now its own standalone class. Interface is now used by aggregation in ClientPort, to forward service commands to their HLE implementation if needed. --- src/core/hle/kernel/client_port.cpp | 23 +++++++++++++++++++++++ src/core/hle/kernel/client_port.h | 29 +++++++++++++++++++++-------- src/core/hle/service/service.cpp | 12 ++++-------- src/core/hle/service/service.h | 12 +++--------- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index 3676b959d..e18d0d4e8 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -8,16 +8,39 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/server_port.h" #include "core/hle/kernel/server_session.h" +#include "core/hle/service/service.h" namespace Kernel { ClientPort::ClientPort() {} ClientPort::~ClientPort() {} +Kernel::SharedPtr ClientPort::CreateForHLE(u32 max_sessions, std::unique_ptr hle_interface) { + SharedPtr client_port(new ClientPort); + client_port->max_sessions = max_sessions; + client_port->active_sessions = 0; + client_port->name = hle_interface->GetPortName(); + client_port->hle_interface = std::move(hle_interface); + + return client_port; +} + void ClientPort::AddWaitingSession(SharedPtr server_session) { + // A port that has an associated HLE interface doesn't have a server port. + if (hle_interface != nullptr) + return; + server_port->pending_sessions.push_back(server_session); // Wake the threads waiting on the ServerPort server_port->WakeupAllWaitingThreads(); } +ResultCode ClientPort::HandleSyncRequest() { + // Forward the request to the associated HLE interface if it exists + if (hle_interface != nullptr) + return hle_interface->HandleSyncRequest(); + + return RESULT_SUCCESS; +} + } // namespace diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index 7cfb4dcb0..1c7c7513d 100644 --- a/src/core/hle/kernel/client_port.h +++ b/src/core/hle/kernel/client_port.h @@ -5,20 +5,33 @@ #pragma once #include +#include #include "common/common_types.h" #include "core/hle/kernel/kernel.h" +namespace Service { +class Interface; +} + namespace Kernel { class ServerPort; class ServerSession; -class ClientPort : public Object { +class ClientPort final : public Object { public: friend class ServerPort; + /** + * Creates a serverless ClientPort that represents a bridge between the HLE implementation of a service/port and the emulated application. + * @param max_sessions Maximum number of sessions that this port is able to handle concurrently. + * @param hle_interface Interface object that implements the commands of the service. + * @returns ClientPort for the given HLE interface. + */ + static Kernel::SharedPtr CreateForHLE(u32 max_sessions, std::unique_ptr hle_interface); + /** * Adds the specified server session to the queue of pending sessions of the associated ServerPort * @param server_session Server session to add to the queue @@ -27,10 +40,9 @@ public: /** * Handle a sync request from the emulated application. - * Only HLE services should override this function. * @returns ResultCode from the operation. */ - virtual ResultCode HandleSyncRequest() { return RESULT_SUCCESS; } + ResultCode HandleSyncRequest(); std::string GetTypeName() const override { return "ClientPort"; } std::string GetName() const override { return name; } @@ -38,12 +50,13 @@ public: static const HandleType HANDLE_TYPE = HandleType::ClientPort; HandleType GetHandleType() const override { return HANDLE_TYPE; } - SharedPtr server_port; ///< ServerPort associated with this client port. - u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have - u32 active_sessions; ///< Number of currently open sessions to this port - std::string name; ///< Name of client port (optional) + SharedPtr server_port = nullptr; ///< ServerPort associated with this client port. + u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have + u32 active_sessions; ///< Number of currently open sessions to this port + std::string name; ///< Name of client port (optional) + std::unique_ptr hle_interface = nullptr; ///< HLE implementation of this port's request handler -protected: +private: ClientPort(); ~ClientPort() override; }; diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 7325485d1..93b33f021 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -92,17 +92,13 @@ void Interface::Register(const FunctionInfo* functions, size_t n) { // Module interface static void AddNamedPort(Interface* interface_) { - interface_->name = interface_->GetPortName(); - interface_->active_sessions = 0; - interface_->max_sessions = interface_->GetMaxSessions(); - g_kernel_named_ports.emplace(interface_->GetPortName(), interface_); + auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::unique_ptr(interface_)); + g_kernel_named_ports.emplace(interface_->GetPortName(), client_port); } void AddService(Interface* interface_) { - interface_->name = interface_->GetPortName(); - interface_->active_sessions = 0; - interface_->max_sessions = interface_->GetMaxSessions(); - g_srv_services.emplace(interface_->GetPortName(), interface_); + auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::unique_ptr(interface_)); + g_srv_services.emplace(interface_->GetPortName(), client_port); } /// Initialize ServiceManager diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index f0f6cf8ee..4d6356e2a 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -25,12 +25,9 @@ static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 character static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE port /// Interface to a CTROS service -class Interface : public Kernel::ClientPort { - // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be - // just something that encapsulates a session and acts as a helper to implement service - // processes. +class Interface { public: - std::string GetName() const override { return GetPortName(); } + virtual ~Interface() {} /** * Gets the maximum allowed number of sessions that can be connected to this port at the same time. @@ -39,8 +36,6 @@ public: */ virtual u32 GetMaxSessions() const { return DefaultMaxSessions; } - void AddWaitingSession(Kernel::SharedPtr server_session) override { } - typedef void (*Function)(Interface*); struct FunctionInfo { @@ -57,10 +52,9 @@ public: return "[UNKNOWN SERVICE PORT]"; } - ResultCode HandleSyncRequest() override; + ResultCode HandleSyncRequest(); protected: - /** * Registers the functions in the service */