From 659a612368c98002037d904d511473d8da8e69e4 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Fri, 20 Apr 2018 19:29:04 -0400
Subject: [PATCH] core: Relocate g_service_manager to the System class

Converts the service manager from a global into an instance-based
variable.
---
 src/core/core.cpp                | 28 ++++++++++++++----
 src/core/core.h                  | 12 ++++++++
 src/core/hle/service/service.cpp | 50 +++++++++++++++-----------------
 src/core/hle/service/service.h   |  2 +-
 src/core/hle/service/sm/sm.cpp   |  4 ++-
 src/core/hle/service/sm/sm.h     |  6 ++--
 6 files changed, 65 insertions(+), 37 deletions(-)

diff --git a/src/core/core.cpp b/src/core/core.cpp
index 9f5507a654..ee4af4dcc7 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -12,10 +12,13 @@
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/gdbstub/gdbstub.h"
+#include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/service/service.h"
+#include "core/hle/service/sm/controller.h"
+#include "core/hle/service/sm/sm.h"
 #include "core/hw/hw.h"
 #include "core/loader/loader.h"
 #include "core/memory_setup.h"
@@ -26,6 +29,8 @@ namespace Core {
 
 /*static*/ System System::s_instance;
 
+System::~System() = default;
+
 System::ResultStatus System::RunLoop(bool tight_loop) {
     status = ResultStatus::Success;
     if (!cpu_core) {
@@ -167,10 +172,12 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
 
     telemetry_session = std::make_unique<Core::TelemetrySession>();
 
+    service_manager = std::make_shared<Service::SM::ServiceManager>();
+
     HW::Init();
     Kernel::Init(system_mode);
     scheduler = std::make_unique<Kernel::Scheduler>(cpu_core.get());
-    Service::Init();
+    Service::Init(service_manager);
     GDBStub::Init();
 
     if (!VideoCore::Init(emu_window)) {
@@ -200,17 +207,26 @@ void System::Shutdown() {
     VideoCore::Shutdown();
     GDBStub::Shutdown();
     Service::Shutdown();
-    scheduler = nullptr;
+    scheduler.reset();
     Kernel::Shutdown();
     HW::Shutdown();
-    telemetry_session = nullptr;
-    gpu_core = nullptr;
-    cpu_core = nullptr;
+    service_manager.reset();
+    telemetry_session.reset();
+    gpu_core.reset();
+    cpu_core.reset();
     CoreTiming::Shutdown();
 
-    app_loader = nullptr;
+    app_loader.reset();
 
     LOG_DEBUG(Core, "Shutdown OK");
 }
 
+Service::SM::ServiceManager& System::ServiceManager() {
+    return *service_manager;
+}
+
+const Service::SM::ServiceManager& System::ServiceManager() const {
+    return *service_manager;
+}
+
 } // namespace Core
diff --git a/src/core/core.h b/src/core/core.h
index f497dc022b..f81cbfb3cc 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -19,10 +19,16 @@
 class EmuWindow;
 class ARM_Interface;
 
+namespace Service::SM {
+class ServiceManager;
+}
+
 namespace Core {
 
 class System {
 public:
+    ~System();
+
     /**
      * Gets the instance of the System singleton class.
      * @returns Reference to the instance of the System singleton class.
@@ -137,6 +143,9 @@ public:
         return *app_loader;
     }
 
+    Service::SM::ServiceManager& ServiceManager();
+    const Service::SM::ServiceManager& ServiceManager() const;
+
     void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) {
         debug_context = std::move(context);
     }
@@ -171,6 +180,9 @@ private:
     /// When true, signals that a reschedule should happen
     bool reschedule_pending{};
 
+    /// Service manager
+    std::shared_ptr<Service::SM::ServiceManager> service_manager;
+
     /// Telemetry session for this emulation session
     std::unique_ptr<Core::TelemetrySession> telemetry_session;
 
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index c5490c1ae0..08ce296772 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -145,7 +145,7 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
         return ResultCode(ErrorModule::HIPC, ErrorDescription::RemoteProcessDead);
     }
     case IPC::CommandType::Control: {
-        SM::g_service_manager->InvokeControlRequest(context);
+        Core::System::GetInstance().ServiceManager().InvokeControlRequest(context);
         break;
     }
     case IPC::CommandType::Request: {
@@ -170,42 +170,40 @@ void AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
 }
 
 /// Initialize ServiceManager
-void Init() {
+void Init(std::shared_ptr<SM::ServiceManager>& sm) {
     // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
     // here and pass it into the respective InstallInterfaces functions.
     auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>();
 
-    SM::g_service_manager = std::make_shared<SM::ServiceManager>();
-    SM::ServiceManager::InstallInterfaces(SM::g_service_manager);
+    SM::ServiceManager::InstallInterfaces(sm);
 
-    Account::InstallInterfaces(*SM::g_service_manager);
-    AM::InstallInterfaces(*SM::g_service_manager, nv_flinger);
-    AOC::InstallInterfaces(*SM::g_service_manager);
-    APM::InstallInterfaces(*SM::g_service_manager);
-    Audio::InstallInterfaces(*SM::g_service_manager);
-    Fatal::InstallInterfaces(*SM::g_service_manager);
-    FileSystem::InstallInterfaces(*SM::g_service_manager);
-    Friend::InstallInterfaces(*SM::g_service_manager);
-    HID::InstallInterfaces(*SM::g_service_manager);
-    LM::InstallInterfaces(*SM::g_service_manager);
-    NFP::InstallInterfaces(*SM::g_service_manager);
-    NIFM::InstallInterfaces(*SM::g_service_manager);
-    NS::InstallInterfaces(*SM::g_service_manager);
-    Nvidia::InstallInterfaces(*SM::g_service_manager);
-    PCTL::InstallInterfaces(*SM::g_service_manager);
-    Sockets::InstallInterfaces(*SM::g_service_manager);
-    SPL::InstallInterfaces(*SM::g_service_manager);
-    SSL::InstallInterfaces(*SM::g_service_manager);
-    Time::InstallInterfaces(*SM::g_service_manager);
-    VI::InstallInterfaces(*SM::g_service_manager, nv_flinger);
-    Set::InstallInterfaces(*SM::g_service_manager);
+    Account::InstallInterfaces(*sm);
+    AM::InstallInterfaces(*sm, nv_flinger);
+    AOC::InstallInterfaces(*sm);
+    APM::InstallInterfaces(*sm);
+    Audio::InstallInterfaces(*sm);
+    Fatal::InstallInterfaces(*sm);
+    FileSystem::InstallInterfaces(*sm);
+    Friend::InstallInterfaces(*sm);
+    HID::InstallInterfaces(*sm);
+    LM::InstallInterfaces(*sm);
+    NFP::InstallInterfaces(*sm);
+    NIFM::InstallInterfaces(*sm);
+    NS::InstallInterfaces(*sm);
+    Nvidia::InstallInterfaces(*sm);
+    PCTL::InstallInterfaces(*sm);
+    Sockets::InstallInterfaces(*sm);
+    SPL::InstallInterfaces(*sm);
+    SSL::InstallInterfaces(*sm);
+    Time::InstallInterfaces(*sm);
+    VI::InstallInterfaces(*sm, nv_flinger);
+    Set::InstallInterfaces(*sm);
 
     LOG_DEBUG(Service, "initialized OK");
 }
 
 /// Shutdown ServiceManager
 void Shutdown() {
-    SM::g_service_manager = nullptr;
     g_kernel_named_ports.clear();
     LOG_DEBUG(Service, "shutdown OK");
 }
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 9c2e826da5..fee841d464 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -178,7 +178,7 @@ private:
 };
 
 /// Initialize ServiceManager
-void Init();
+void Init(std::shared_ptr<SM::ServiceManager>& sm);
 
 /// Shutdown ServiceManager
 void Shutdown();
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 297a4f2c69..4578fc05f9 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -14,6 +14,8 @@
 
 namespace Service::SM {
 
+ServiceManager::~ServiceManager() = default;
+
 void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
     controller_interface->InvokeRequest(context);
 }
@@ -72,7 +74,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ServiceManager::ConnectToSer
     return client_port->Connect();
 }
 
-std::shared_ptr<ServiceManager> g_service_manager;
+SM::~SM() = default;
 
 /**
  * SM::Initialize service function
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index 40421cfd58..13f5c4c28f 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -23,7 +23,7 @@ namespace Service::SM {
 class SM final : public ServiceFramework<SM> {
 public:
     SM(std::shared_ptr<ServiceManager> service_manager);
-    ~SM() = default;
+    ~SM() override;
 
 private:
     void Initialize(Kernel::HLERequestContext& ctx);
@@ -44,6 +44,8 @@ class ServiceManager {
 public:
     static void InstallInterfaces(std::shared_ptr<ServiceManager> self);
 
+    ~ServiceManager();
+
     ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name,
                                                                      unsigned int max_sessions);
     ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> GetServicePort(const std::string& name);
@@ -59,6 +61,4 @@ private:
     std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> registered_services;
 };
 
-extern std::shared_ptr<ServiceManager> g_service_manager;
-
 } // namespace Service::SM