summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/sm
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/sm')
-rw-r--r--src/core/hle/service/sm/sm.cpp29
-rw-r--r--src/core/hle/service/sm/sm.h5
2 files changed, 31 insertions, 3 deletions
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 0de32b05d..6eba48f03 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -32,6 +32,10 @@ ServiceManager::~ServiceManager() {
port->GetClientPort().Close();
port->GetServerPort().Close();
}
+
+ if (deferral_event) {
+ deferral_event->Close();
+ }
}
void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
@@ -62,6 +66,9 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
service_ports.emplace(name, port);
registered_services.emplace(name, handler);
+ if (deferral_event) {
+ deferral_event->Signal();
+ }
return ResultSuccess;
}
@@ -88,7 +95,7 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name
std::scoped_lock lk{lock};
auto it = service_ports.find(name);
if (it == service_ports.end()) {
- LOG_ERROR(Service_SM, "Server is not registered! service={}", name);
+ LOG_WARNING(Service_SM, "Server is not registered! service={}", name);
return ERR_SERVICE_NOT_REGISTERED;
}
@@ -113,6 +120,11 @@ void SM::Initialize(Kernel::HLERequestContext& ctx) {
void SM::GetService(Kernel::HLERequestContext& ctx) {
auto result = GetServiceImpl(ctx);
+ if (ctx.GetIsDeferred()) {
+ // Don't overwrite the command buffer.
+ return;
+ }
+
if (result.Succeeded()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(result.Code());
@@ -125,6 +137,11 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
void SM::GetServiceTipc(Kernel::HLERequestContext& ctx) {
auto result = GetServiceImpl(ctx);
+ if (ctx.GetIsDeferred()) {
+ // Don't overwrite the command buffer.
+ return;
+ }
+
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(result.Code());
rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr);
@@ -152,8 +169,9 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
// Find the named port.
auto port_result = service_manager.GetServicePort(name);
if (port_result.Failed()) {
- LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw);
- return port_result.Code();
+ LOG_INFO(Service_SM, "Waiting for service {} to become available", name);
+ ctx.SetIsDeferred();
+ return ERR_SERVICE_NOT_REGISTERED;
}
auto& port = port_result.Unwrap();
@@ -228,8 +246,13 @@ SM::SM(ServiceManager& service_manager_, Core::System& system_)
SM::~SM() = default;
void LoopProcess(Core::System& system) {
+ auto& service_manager = system.ServiceManager();
auto server_manager = std::make_unique<ServerManager>(system);
+ Kernel::KEvent* deferral_event{};
+ server_manager->ManageDeferral(&deferral_event);
+ service_manager.SetDeferralEvent(deferral_event);
+
server_manager->ManageNamedPort("sm:", std::make_shared<SM>(system.ServiceManager(), system));
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 22ca720f8..b7eeafdd6 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -71,6 +71,10 @@ public:
void InvokeControlRequest(Kernel::HLERequestContext& context);
+ void SetDeferralEvent(Kernel::KEvent* deferral_event_) {
+ deferral_event = deferral_event_;
+ }
+
private:
std::shared_ptr<SM> sm_interface;
std::unique_ptr<Controller> controller_interface;
@@ -82,6 +86,7 @@ private:
/// Kernel context
Kernel::KernelCore& kernel;
+ Kernel::KEvent* deferral_event{};
};
/// Runs SM services.