diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h index ad5259a5c..4436f4f83 100644 --- a/src/core/hle/service/hle_ipc.h +++ b/src/core/hle/service/hle_ipc.h @@ -75,6 +75,7 @@ protected: using SessionRequestHandlerWeakPtr = std::weak_ptr; using SessionRequestHandlerPtr = std::shared_ptr; +using SessionRequestHandlerFactory = std::function; /** * Manages the underlying HLE requests for a session, and whether (or not) the session should be diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index e2e399534..6808247a9 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp @@ -93,13 +93,13 @@ Result ServerManager::RegisterSession(Kernel::KServerSession* session, } Result ServerManager::RegisterNamedService(const std::string& service_name, - std::shared_ptr&& handler, + SessionRequestHandlerFactory&& handler_factory, u32 max_sessions) { ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects); // Add the new server to sm:. ASSERT(R_SUCCEEDED( - m_system.ServiceManager().RegisterService(service_name, max_sessions, handler))); + m_system.ServiceManager().RegisterService(service_name, max_sessions, handler_factory))); // Get the registered port. Kernel::KPort* port{}; @@ -112,7 +112,7 @@ Result ServerManager::RegisterNamedService(const std::string& service_name, // Begin tracking the server port. { std::scoped_lock ll{m_list_mutex}; - m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler)); + m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler_factory)); } // Signal the wakeup event. @@ -121,8 +121,18 @@ Result ServerManager::RegisterNamedService(const std::string& service_name, R_SUCCEED(); } +Result ServerManager::RegisterNamedService(const std::string& service_name, + std::shared_ptr&& handler, + u32 max_sessions) { + // Make the factory. + const auto HandlerFactory = [handler]() { return handler; }; + + // Register the service with the new factory. + R_RETURN(this->RegisterNamedService(service_name, std::move(HandlerFactory), max_sessions)); +} + Result ServerManager::ManageNamedPort(const std::string& service_name, - std::shared_ptr&& handler, + SessionRequestHandlerFactory&& handler_factory, u32 max_sessions) { ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects); @@ -149,7 +159,7 @@ Result ServerManager::ManageNamedPort(const std::string& service_name, // Begin tracking the server port. { std::scoped_lock ll{m_list_mutex}; - m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler)); + m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler_factory)); } // We succeeded. @@ -269,13 +279,13 @@ Result ServerManager::WaitAndProcessImpl() { case HandleType::Port: { // Port signaled. auto* port = wait_obj->DynamicCast(); - std::shared_ptr handler; + SessionRequestHandlerFactory handler_factory; // Remove from tracking. { std::scoped_lock ll{m_list_mutex}; ASSERT(m_ports.contains(port)); - m_ports.at(port).swap(handler); + m_ports.at(port).swap(handler_factory); m_ports.erase(port); } @@ -283,7 +293,7 @@ Result ServerManager::WaitAndProcessImpl() { sl.unlock(); // Finish. - R_RETURN(this->OnPortEvent(port, std::move(handler))); + R_RETURN(this->OnPortEvent(port, std::move(handler_factory))); } case HandleType::Session: { // Session signaled. @@ -333,19 +343,19 @@ Result ServerManager::WaitAndProcessImpl() { } Result ServerManager::OnPortEvent(Kernel::KServerPort* port, - std::shared_ptr&& handler) { + SessionRequestHandlerFactory&& handler_factory) { // Accept a new server session. Kernel::KServerSession* session = port->AcceptSession(); ASSERT(session != nullptr); // Create the session manager and install the handler. auto manager = std::make_shared(m_system.Kernel(), *this); - manager->SetSessionHandler(std::shared_ptr(handler)); + manager->SetSessionHandler(handler_factory()); // Track the server session. { std::scoped_lock ll{m_list_mutex}; - m_ports.emplace(port, std::move(handler)); + m_ports.emplace(port, std::move(handler_factory)); m_sessions.emplace(session, std::move(manager)); } diff --git a/src/core/hle/service/server_manager.h b/src/core/hle/service/server_manager.h index 58b0a0832..c4bc07262 100644 --- a/src/core/hle/service/server_manager.h +++ b/src/core/hle/service/server_manager.h @@ -13,6 +13,7 @@ #include "common/polyfill_thread.h" #include "common/thread.h" #include "core/hle/result.h" +#include "core/hle/service/hle_ipc.h" #include "core/hle/service/mutex.h" namespace Core { @@ -28,10 +29,6 @@ class KSynchronizationObject; namespace Service { -class HLERequestContext; -class SessionRequestHandler; -class SessionRequestManager; - class ServerManager { public: explicit ServerManager(Core::System& system); @@ -39,11 +36,14 @@ public: Result RegisterSession(Kernel::KServerSession* session, std::shared_ptr manager); + Result RegisterNamedService(const std::string& service_name, + SessionRequestHandlerFactory&& handler_factory, + u32 max_sessions = 64); Result RegisterNamedService(const std::string& service_name, std::shared_ptr&& handler, u32 max_sessions = 64); Result ManageNamedPort(const std::string& service_name, - std::shared_ptr&& handler, u32 max_sessions = 64); + SessionRequestHandlerFactory&& handler_factory, u32 max_sessions = 64); Result ManageDeferral(Kernel::KEvent** out_event); Result LoopProcess(); @@ -56,7 +56,7 @@ private: Result LoopProcessImpl(); Result WaitAndProcessImpl(); - Result OnPortEvent(Kernel::KServerPort* port, std::shared_ptr&& handler); + Result OnPortEvent(Kernel::KServerPort* port, SessionRequestHandlerFactory&& handler_factory); Result OnSessionEvent(Kernel::KServerSession* session, std::shared_ptr&& manager); Result OnDeferralEvent(std::list&& deferrals); @@ -68,7 +68,7 @@ private: std::mutex m_list_mutex; // Guest state tracking - std::map> m_ports{}; + std::map m_ports{}; std::map> m_sessions{}; Kernel::KEvent* m_event{}; Kernel::KEvent* m_deferral_event{}; diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 9ab718e0a..53209537f 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -51,7 +51,7 @@ static Result ValidateServiceName(const std::string& name) { } Result ServiceManager::RegisterService(std::string name, u32 max_sessions, - SessionRequestHandlerPtr handler) { + SessionRequestHandlerFactory handler) { R_TRY(ValidateServiceName(name)); std::scoped_lock lk{lock}; @@ -264,7 +264,9 @@ void LoopProcess(Core::System& system) { server_manager->ManageDeferral(&deferral_event); service_manager.SetDeferralEvent(deferral_event); - server_manager->ManageNamedPort("sm:", std::make_shared(system.ServiceManager(), system)); + auto sm_service = std::make_shared(system.ServiceManager(), system); + server_manager->ManageNamedPort("sm:", [sm_service] { return sm_service; }); + ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 14bfaf8c2..cf102c339 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -53,7 +53,8 @@ public: explicit ServiceManager(Kernel::KernelCore& kernel_); ~ServiceManager(); - Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler); + Result RegisterService(std::string name, u32 max_sessions, + SessionRequestHandlerFactory handler_factory); Result UnregisterService(const std::string& name); Result GetServicePort(Kernel::KPort** out_port, const std::string& name); @@ -64,7 +65,7 @@ public: LOG_DEBUG(Service, "Can't find service: {}", service_name); return nullptr; } - return std::static_pointer_cast(service->second); + return std::static_pointer_cast(service->second()); } void InvokeControlRequest(HLERequestContext& context); @@ -79,7 +80,7 @@ private: /// Map of registered services, retrieved using GetServicePort. std::mutex lock; - std::unordered_map registered_services; + std::unordered_map registered_services; std::unordered_map service_ports; /// Kernel context