From 1213a298df9e130bdb453707939e6709d1689a91 Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Fri, 12 Oct 2018 19:00:16 -0400
Subject: [PATCH] Kernel: pass ref to port

---
 src/core/core.cpp                   |  2 +-
 src/core/hle/kernel/client_port.cpp |  2 +-
 src/core/hle/kernel/client_port.h   |  4 +++-
 src/core/hle/kernel/kernel.h        | 12 ++++++++++++
 src/core/hle/kernel/server_port.cpp |  8 ++++----
 src/core/hle/kernel/server_port.h   | 14 +++-----------
 src/core/hle/kernel/svc.cpp         |  2 +-
 src/core/hle/service/err_f.cpp      |  2 +-
 src/core/hle/service/service.cpp    |  4 ++--
 src/core/hle/service/service.h      |  3 ++-
 src/core/hle/service/sm/sm.cpp      |  6 ++++--
 src/core/hle/service/sm/sm.h        |  3 +++
 12 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/src/core/core.cpp b/src/core/core.cpp
index 6ae8345d4..6212347e2 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -191,7 +191,7 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) {
     rpc_server = std::make_unique<RPC::RPCServer>();
 #endif
 
-    service_manager = std::make_shared<Service::SM::ServiceManager>();
+    service_manager = std::make_shared<Service::SM::ServiceManager>(*this);
     shared_page_handler = std::make_shared<SharedPage::Handler>();
     archive_manager = std::make_unique<Service::FS::ArchiveManager>();
 
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index e45494db2..f70b84ae2 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -13,7 +13,7 @@
 
 namespace Kernel {
 
-ClientPort::ClientPort() = default;
+ClientPort::ClientPort(KernelSystem& kernel) {}
 ClientPort::~ClientPort() = default;
 
 ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 46227347e..2dda05f15 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -48,13 +48,15 @@ public:
     void ConnectionClosed();
 
 private:
-    ClientPort();
+    explicit ClientPort(KernelSystem& kernel);
     ~ClientPort() override;
 
     SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
     u32 max_sessions = 0;    ///< Maximum number of simultaneous sessions the port can have
     u32 active_sessions = 0; ///< Number of currently open sessions to this port
     std::string name;        ///< Name of client port (optional)
+
+    friend class KernelSystem;
 };
 
 } // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index fbf1c338c..79b939c07 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -19,6 +19,8 @@ class Process;
 class Thread;
 class Semaphore;
 class Timer;
+class ClientPort;
+class ServerPort;
 
 enum class ResetType {
     OneShot,
@@ -93,6 +95,16 @@ public:
      * @return The created Timer
      */
     SharedPtr<Timer> CreateTimer(ResetType reset_type, std::string name = "Unknown");
+
+    /**
+     * Creates a pair of ServerPort and an associated ClientPort.
+     *
+     * @param max_sessions Maximum number of sessions to the port
+     * @param name Optional name of the ports
+     * @return The created port tuple
+     */
+    std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
+        u32 max_sessions, std::string name = "UnknownPort");
 };
 
 } // namespace Kernel
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index 7b6211fd8..44a5ca841 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -13,7 +13,7 @@
 
 namespace Kernel {
 
-ServerPort::ServerPort() {}
+ServerPort::ServerPort(KernelSystem& kernel) {}
 ServerPort::~ServerPort() {}
 
 ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {
@@ -35,11 +35,11 @@ void ServerPort::Acquire(Thread* thread) {
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
 }
 
-std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
+std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> KernelSystem::CreatePortPair(
     u32 max_sessions, std::string name) {
 
-    SharedPtr<ServerPort> server_port(new ServerPort);
-    SharedPtr<ClientPort> client_port(new ClientPort);
+    SharedPtr<ServerPort> server_port(new ServerPort(*this));
+    SharedPtr<ClientPort> client_port(new ClientPort(*this));
 
     server_port->name = name + "_Server";
     client_port->name = name + "_Client";
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index 6d458b188..ee09efba1 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -20,16 +20,6 @@ class SessionRequestHandler;
 
 class ServerPort final : public WaitObject {
 public:
-    /**
-     * Creates a pair of ServerPort and an associated ClientPort.
-     *
-     * @param max_sessions Maximum number of sessions to the port
-     * @param name Optional name of the ports
-     * @return The created port tuple
-     */
-    static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
-        u32 max_sessions, std::string name = "UnknownPort");
-
     std::string GetTypeName() const override {
         return "ServerPort";
     }
@@ -69,8 +59,10 @@ public:
     void Acquire(Thread* thread) override;
 
 private:
-    ServerPort();
+    explicit ServerPort(KernelSystem& kernel);
     ~ServerPort() override;
+
+    friend class KernelSystem;
 };
 
 } // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 99df081b2..0c2e0c160 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1119,7 +1119,7 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr nam
     // TODO(Subv): Implement named ports.
     ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented");
 
-    auto ports = ServerPort::CreatePortPair(max_sessions);
+    auto ports = Core::System::GetInstance().Kernel().CreatePortPair(max_sessions);
     CASCADE_RESULT(*client_port,
                    g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports))));
     // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 9a914ee7b..13b2c7e46 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -244,7 +244,7 @@ ERR_F::~ERR_F() = default;
 
 void InstallInterfaces(Core::System& system) {
     auto errf = std::make_shared<ERR_F>(system);
-    errf->InstallAsNamedPort();
+    errf->InstallAsNamedPort(system.Kernel());
 }
 
 } // namespace Service::ERR
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 459629975..6bdafd0e8 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -143,11 +143,11 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)
     port->SetHleHandler(shared_from_this());
 }
 
-void ServiceFrameworkBase::InstallAsNamedPort() {
+void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelSystem& kernel) {
     ASSERT(port == nullptr);
     SharedPtr<ServerPort> server_port;
     SharedPtr<ClientPort> client_port;
-    std::tie(server_port, client_port) = ServerPort::CreatePortPair(max_sessions, service_name);
+    std::tie(server_port, client_port) = kernel.CreatePortPair(max_sessions, service_name);
     server_port->SetHleHandler(shared_from_this());
     AddNamedPort(service_name, std::move(client_port));
 }
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index dbe6e207c..5cb4fbf23 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -20,6 +20,7 @@ class System;
 }
 
 namespace Kernel {
+class KernelSystem;
 class ClientPort;
 class ServerPort;
 class ServerSession;
@@ -59,7 +60,7 @@ public:
     /// Creates a port pair and registers this service with the given ServiceManager.
     void InstallAsService(SM::ServiceManager& service_manager);
     /// Creates a port pair and registers it on the kernel's global port registry.
-    void InstallAsNamedPort();
+    void InstallAsNamedPort(Kernel::KernelSystem& kernel);
 
     void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override;
 
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index cd3b4ee30..81819c9bd 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -22,11 +22,13 @@ static ResultCode ValidateServiceName(const std::string& name) {
     return RESULT_SUCCESS;
 }
 
+ServiceManager::ServiceManager(Core::System& system) : system(system) {}
+
 void ServiceManager::InstallInterfaces(Core::System& system) {
     ASSERT(system.ServiceManager().srv_interface.expired());
 
     auto srv = std::make_shared<SRV>(system);
-    srv->InstallAsNamedPort();
+    srv->InstallAsNamedPort(system.Kernel());
     system.ServiceManager().srv_interface = srv;
 }
 
@@ -40,7 +42,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService
 
     Kernel::SharedPtr<Kernel::ServerPort> server_port;
     Kernel::SharedPtr<Kernel::ClientPort> client_port;
-    std::tie(server_port, client_port) = Kernel::ServerPort::CreatePortPair(max_sessions, name);
+    std::tie(server_port, client_port) = system.Kernel().CreatePortPair(max_sessions, name);
 
     registered_services.emplace(std::move(name), std::move(client_port));
     return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port));
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index c0666aeec..f3cf40756 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -45,6 +45,8 @@ class ServiceManager {
 public:
     static void InstallInterfaces(Core::System& system);
 
+    explicit ServiceManager(Core::System& system);
+
     ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name,
                                                                      unsigned int max_sessions);
     ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> GetServicePort(const std::string& name);
@@ -67,6 +69,7 @@ public:
     }
 
 private:
+    Core::System& system;
     std::weak_ptr<SRV> srv_interface;
 
     /// Map of registered services, retrieved using GetServicePort or ConnectToService.