diff options
| author | 2021-06-30 18:06:47 -0700 | |
|---|---|---|
| committer | 2021-07-20 18:54:55 -0700 | |
| commit | 7bd020e0307c6a870707440f99bf6bb8b513306f (patch) | |
| tree | f862958e6f47b0f8b737ddc16bdcfdf5be53e345 /src | |
| parent | hle: kernel: k_process: Close the handle table on shutdown. (diff) | |
| download | yuzu-7bd020e0307c6a870707440f99bf6bb8b513306f.tar.gz yuzu-7bd020e0307c6a870707440f99bf6bb8b513306f.tar.xz yuzu-7bd020e0307c6a870707440f99bf6bb8b513306f.zip | |
hle: service: sm: Refactor to better manage ports.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/service.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/service/service.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.cpp | 65 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.h | 14 |
4 files changed, 47 insertions, 45 deletions
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index e6fba88b2..b3e50433b 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -104,23 +104,22 @@ ServiceFrameworkBase::~ServiceFrameworkBase() { | |||
| 104 | void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) { | 104 | void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) { |
| 105 | const auto guard = LockService(); | 105 | const auto guard = LockService(); |
| 106 | 106 | ||
| 107 | ASSERT(!port_installed); | 107 | ASSERT(!service_registered); |
| 108 | 108 | ||
| 109 | auto port = service_manager.RegisterService(service_name, max_sessions).Unwrap(); | 109 | service_manager.RegisterService(service_name, max_sessions, shared_from_this()); |
| 110 | port->SetSessionHandler(shared_from_this()); | 110 | service_registered = true; |
| 111 | port_installed = true; | ||
| 112 | } | 111 | } |
| 113 | 112 | ||
| 114 | Kernel::KClientPort& ServiceFrameworkBase::CreatePort() { | 113 | Kernel::KClientPort& ServiceFrameworkBase::CreatePort() { |
| 115 | const auto guard = LockService(); | 114 | const auto guard = LockService(); |
| 116 | 115 | ||
| 117 | ASSERT(!port_installed); | 116 | ASSERT(!service_registered); |
| 118 | 117 | ||
| 119 | auto* port = Kernel::KPort::Create(kernel); | 118 | auto* port = Kernel::KPort::Create(kernel); |
| 120 | port->Initialize(max_sessions, false, service_name); | 119 | port->Initialize(max_sessions, false, service_name); |
| 121 | port->GetServerPort().SetSessionHandler(shared_from_this()); | 120 | port->GetServerPort().SetSessionHandler(shared_from_this()); |
| 122 | 121 | ||
| 123 | port_installed = true; | 122 | service_registered = true; |
| 124 | 123 | ||
| 125 | return port->GetClientPort(); | 124 | return port->GetClientPort(); |
| 126 | } | 125 | } |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 632ce9252..c9d6b879d 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -125,7 +125,7 @@ private: | |||
| 125 | 125 | ||
| 126 | /// Flag to store if a port was already create/installed to detect multiple install attempts, | 126 | /// Flag to store if a port was already create/installed to detect multiple install attempts, |
| 127 | /// which is not supported. | 127 | /// which is not supported. |
| 128 | bool port_installed = false; | 128 | bool service_registered = false; |
| 129 | 129 | ||
| 130 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. | 130 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. |
| 131 | InvokerFn* handler_invoker; | 131 | InvokerFn* handler_invoker; |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 15034abed..ae4dc4a75 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <tuple> | 5 | #include <tuple> |
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/scope_exit.h" | ||
| 7 | #include "core/core.h" | 8 | #include "core/core.h" |
| 8 | #include "core/hle/ipc_helpers.h" | 9 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/k_client_port.h" | 10 | #include "core/hle/kernel/k_client_port.h" |
| @@ -40,17 +41,13 @@ static ResultCode ValidateServiceName(const std::string& name) { | |||
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core::System& system) { | 43 | Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core::System& system) { |
| 43 | ASSERT(self.sm_interface.expired()); | 44 | self.sm_interface = std::make_shared<SM>(self, system); |
| 44 | |||
| 45 | auto sm = std::make_shared<SM>(self, system); | ||
| 46 | self.sm_interface = sm; | ||
| 47 | self.controller_interface = std::make_unique<Controller>(system); | 45 | self.controller_interface = std::make_unique<Controller>(system); |
| 48 | 46 | return self.sm_interface->CreatePort(); | |
| 49 | return sm->CreatePort(); | ||
| 50 | } | 47 | } |
| 51 | 48 | ||
| 52 | ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, | 49 | ResultCode ServiceManager::RegisterService(std::string name, u32 max_sessions, |
| 53 | u32 max_sessions) { | 50 | Kernel::SessionRequestHandlerPtr handler) { |
| 54 | 51 | ||
| 55 | CASCADE_CODE(ValidateServiceName(name)); | 52 | CASCADE_CODE(ValidateServiceName(name)); |
| 56 | 53 | ||
| @@ -59,12 +56,9 @@ ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name | |||
| 59 | return ERR_ALREADY_REGISTERED; | 56 | return ERR_ALREADY_REGISTERED; |
| 60 | } | 57 | } |
| 61 | 58 | ||
| 62 | auto* port = Kernel::KPort::Create(kernel); | 59 | registered_services.emplace(std::move(name), handler); |
| 63 | port->Initialize(max_sessions, false, name); | ||
| 64 | 60 | ||
| 65 | registered_services.emplace(std::move(name), port); | 61 | return ResultSuccess; |
| 66 | |||
| 67 | return MakeResult(&port->GetServerPort()); | ||
| 68 | } | 62 | } |
| 69 | 63 | ||
| 70 | ResultCode ServiceManager::UnregisterService(const std::string& name) { | 64 | ResultCode ServiceManager::UnregisterService(const std::string& name) { |
| @@ -76,14 +70,11 @@ ResultCode ServiceManager::UnregisterService(const std::string& name) { | |||
| 76 | return ERR_SERVICE_NOT_REGISTERED; | 70 | return ERR_SERVICE_NOT_REGISTERED; |
| 77 | } | 71 | } |
| 78 | 72 | ||
| 79 | iter->second->Close(); | ||
| 80 | |||
| 81 | registered_services.erase(iter); | 73 | registered_services.erase(iter); |
| 82 | return ResultSuccess; | 74 | return ResultSuccess; |
| 83 | } | 75 | } |
| 84 | 76 | ||
| 85 | ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) { | 77 | ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) { |
| 86 | |||
| 87 | CASCADE_CODE(ValidateServiceName(name)); | 78 | CASCADE_CODE(ValidateServiceName(name)); |
| 88 | auto it = registered_services.find(name); | 79 | auto it = registered_services.find(name); |
| 89 | if (it == registered_services.end()) { | 80 | if (it == registered_services.end()) { |
| @@ -91,10 +82,13 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name | |||
| 91 | return ERR_SERVICE_NOT_REGISTERED; | 82 | return ERR_SERVICE_NOT_REGISTERED; |
| 92 | } | 83 | } |
| 93 | 84 | ||
| 94 | return MakeResult(it->second); | 85 | auto* port = Kernel::KPort::Create(kernel); |
| 95 | } | 86 | port->Initialize(ServerSessionCountMax, false, name); |
| 87 | auto handler = it->second; | ||
| 88 | port->GetServerPort().SetSessionHandler(std::move(handler)); | ||
| 96 | 89 | ||
| 97 | SM::~SM() = default; | 90 | return MakeResult(port); |
| 91 | } | ||
| 98 | 92 | ||
| 99 | /** | 93 | /** |
| 100 | * SM::Initialize service function | 94 | * SM::Initialize service function |
| @@ -156,11 +150,15 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& | |||
| 156 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw); | 150 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw); |
| 157 | return port_result.Code(); | 151 | return port_result.Code(); |
| 158 | } | 152 | } |
| 159 | auto& port = port_result.Unwrap()->GetClientPort(); | 153 | auto& port = port_result.Unwrap(); |
| 154 | SCOPE_EXIT({ port->GetClientPort().Close(); }); | ||
| 155 | |||
| 156 | server_ports.emplace_back(&port->GetServerPort()); | ||
| 160 | 157 | ||
| 161 | // Create a new session. | 158 | // Create a new session. |
| 162 | Kernel::KClientSession* session{}; | 159 | Kernel::KClientSession* session{}; |
| 163 | if (const auto result = port.CreateSession(std::addressof(session)); result.IsError()) { | 160 | if (const auto result = port->GetClientPort().CreateSession(std::addressof(session)); |
| 161 | result.IsError()) { | ||
| 164 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); | 162 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); |
| 165 | return result; | 163 | return result; |
| 166 | } | 164 | } |
| @@ -180,20 +178,21 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) { | |||
| 180 | LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, | 178 | LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, |
| 181 | max_session_count, is_light); | 179 | max_session_count, is_light); |
| 182 | 180 | ||
| 183 | auto handle = service_manager.RegisterService(name, max_session_count); | 181 | if (const auto result = service_manager.RegisterService(name, max_session_count, nullptr); |
| 184 | if (handle.Failed()) { | 182 | result.IsError()) { |
| 185 | LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", | 183 | LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", result.raw); |
| 186 | handle.Code().raw); | ||
| 187 | IPC::ResponseBuilder rb{ctx, 2}; | 184 | IPC::ResponseBuilder rb{ctx, 2}; |
| 188 | rb.Push(handle.Code()); | 185 | rb.Push(result); |
| 189 | return; | 186 | return; |
| 190 | } | 187 | } |
| 191 | 188 | ||
| 192 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 189 | auto* port = Kernel::KPort::Create(kernel); |
| 193 | rb.Push(handle.Code()); | 190 | port->Initialize(ServerSessionCountMax, is_light, name); |
| 191 | SCOPE_EXIT({ port->GetClientPort().Close(); }); | ||
| 194 | 192 | ||
| 195 | auto server_port = handle.Unwrap(); | 193 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 196 | rb.PushMoveObjects(server_port); | 194 | rb.Push(ResultSuccess); |
| 195 | rb.PushMoveObjects(port->GetServerPort()); | ||
| 197 | } | 196 | } |
| 198 | 197 | ||
| 199 | void SM::UnregisterService(Kernel::HLERequestContext& ctx) { | 198 | void SM::UnregisterService(Kernel::HLERequestContext& ctx) { |
| @@ -225,4 +224,10 @@ SM::SM(ServiceManager& service_manager_, Core::System& system_) | |||
| 225 | }); | 224 | }); |
| 226 | } | 225 | } |
| 227 | 226 | ||
| 227 | SM::~SM() { | ||
| 228 | for (auto& server_port : server_ports) { | ||
| 229 | server_port->Close(); | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 228 | } // namespace Service::SM | 233 | } // namespace Service::SM |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index ea37f11d4..068c78588 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -49,6 +49,7 @@ private: | |||
| 49 | ServiceManager& service_manager; | 49 | ServiceManager& service_manager; |
| 50 | bool is_initialized{}; | 50 | bool is_initialized{}; |
| 51 | Kernel::KernelCore& kernel; | 51 | Kernel::KernelCore& kernel; |
| 52 | std::vector<Kernel::KServerPort*> server_ports; | ||
| 52 | }; | 53 | }; |
| 53 | 54 | ||
| 54 | class ServiceManager { | 55 | class ServiceManager { |
| @@ -58,7 +59,8 @@ public: | |||
| 58 | explicit ServiceManager(Kernel::KernelCore& kernel_); | 59 | explicit ServiceManager(Kernel::KernelCore& kernel_); |
| 59 | ~ServiceManager(); | 60 | ~ServiceManager(); |
| 60 | 61 | ||
| 61 | ResultVal<Kernel::KServerPort*> RegisterService(std::string name, u32 max_sessions); | 62 | ResultCode RegisterService(std::string name, u32 max_sessions, |
| 63 | Kernel::SessionRequestHandlerPtr handler); | ||
| 62 | ResultCode UnregisterService(const std::string& name); | 64 | ResultCode UnregisterService(const std::string& name); |
| 63 | ResultVal<Kernel::KPort*> GetServicePort(const std::string& name); | 65 | ResultVal<Kernel::KPort*> GetServicePort(const std::string& name); |
| 64 | 66 | ||
| @@ -69,21 +71,17 @@ public: | |||
| 69 | LOG_DEBUG(Service, "Can't find service: {}", service_name); | 71 | LOG_DEBUG(Service, "Can't find service: {}", service_name); |
| 70 | return nullptr; | 72 | return nullptr; |
| 71 | } | 73 | } |
| 72 | auto* port = service->second; | 74 | return std::static_pointer_cast<T>(service->second); |
| 73 | if (port == nullptr) { | ||
| 74 | return nullptr; | ||
| 75 | } | ||
| 76 | return std::static_pointer_cast<T>(port->GetServerPort().GetSessionRequestHandler()); | ||
| 77 | } | 75 | } |
| 78 | 76 | ||
| 79 | void InvokeControlRequest(Kernel::HLERequestContext& context); | 77 | void InvokeControlRequest(Kernel::HLERequestContext& context); |
| 80 | 78 | ||
| 81 | private: | 79 | private: |
| 82 | std::weak_ptr<SM> sm_interface; | 80 | std::shared_ptr<SM> sm_interface; |
| 83 | std::unique_ptr<Controller> controller_interface; | 81 | std::unique_ptr<Controller> controller_interface; |
| 84 | 82 | ||
| 85 | /// Map of registered services, retrieved using GetServicePort. | 83 | /// Map of registered services, retrieved using GetServicePort. |
| 86 | std::unordered_map<std::string, Kernel::KPort*> registered_services; | 84 | std::unordered_map<std::string, Kernel::SessionRequestHandlerPtr> registered_services; |
| 87 | 85 | ||
| 88 | /// Kernel context | 86 | /// Kernel context |
| 89 | Kernel::KernelCore& kernel; | 87 | Kernel::KernelCore& kernel; |