From 02a3b5ae2bc528f2b153a5036869a1eea7f8d550 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Wed, 8 Aug 2018 23:30:48 +0200 Subject: [PATCH 1/4] Service::SM: Wait till client is registered --- src/core/hle/service/sm/srv.cpp | 56 ++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp index f459d3784..e311e79f2 100644 --- a/src/core/hle/service/sm/srv.cpp +++ b/src/core/hle/service/sm/srv.cpp @@ -3,7 +3,7 @@ // Refer to the license.txt file included. #include - +#include #include "common/common_types.h" #include "common/logging/log.h" #include "core/hle/ipc.h" @@ -11,10 +11,12 @@ #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" #include "core/hle/kernel/errors.h" +#include "core/hle/kernel/event.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/server_port.h" #include "core/hle/kernel/server_session.h" +#include "core/hle/lock.h" #include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/srv.h" @@ -23,6 +25,9 @@ namespace SM { constexpr int MAX_PENDING_NOTIFICATIONS = 16; +static std::unordered_map> + get_service_handle_delayed_map; + /** * SRV::RegisterClient service function * Inputs: @@ -99,12 +104,47 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { // TODO(yuriks): Permission checks go here + auto get_handle = [name, this, wait_until_available](Kernel::SharedPtr thread, + Kernel::HLERequestContext& ctx, + ThreadWakeupReason reason) { + LOG_ERROR(Service_SRV, "called service={} wakeup", name); + auto client_port = service_manager->GetServicePort(name); + + auto session = client_port.Unwrap()->Connect(); + if (session.Succeeded()) { + LOG_DEBUG(Service_SRV, "called service={} -> session={}", name, + (*session)->GetObjectId()); + IPC::RequestBuilder rb(ctx, 0x5, 1, 2); + rb.Push(session.Code()); + rb.PushMoveObjects(std::move(session).Unwrap()); + } else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED && wait_until_available) { + LOG_WARNING(Service_SRV, "called service={} -> ERR_MAX_CONNECTIONS_REACHED", name); + // TODO(Subv): Put the caller guest thread to sleep until this port becomes available + // again. + UNIMPLEMENTED_MSG("Unimplemented wait until port {} is available.", name); + } else { + LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, session.Code().raw); + IPC::RequestBuilder rb(ctx, 0x5, 1, 0); + rb.Push(session.Code()); + } + }; + auto client_port = service_manager->GetServicePort(name); if (client_port.Failed()) { - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(client_port.Code()); - LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, client_port.Code().raw); - return; + if (wait_until_available) { + LOG_ERROR(Service_SRV, "called service={} delayed", name); + Kernel::SharedPtr get_service_handle_event = + ctx.SleepClientThread(Kernel::GetCurrentThread(), "GetServiceHandle", + std::chrono::nanoseconds(-1), get_handle); + get_service_handle_delayed_map[name] = get_service_handle_event; + return; + } else { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(client_port.Code()); + LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, + client_port.Code().raw); + return; + } } auto session = client_port.Unwrap()->Connect(); @@ -192,6 +232,12 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) { auto port = service_manager->RegisterService(name, max_sessions); + if (get_service_handle_delayed_map.find(name) != get_service_handle_delayed_map.end()) { + std::lock_guard lock(HLE::g_hle_lock); + get_service_handle_delayed_map.at(name)->Signal(); + get_service_handle_delayed_map.erase(name); + } + if (port.Failed()) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(port.Code()); From aa98e55a88c755759c2023e9d82d32d52d7761ea Mon Sep 17 00:00:00 2001 From: B3n30 Date: Wed, 8 Aug 2018 23:42:45 +0200 Subject: [PATCH 2/4] fixup! Service::SM: Wait till client is registered --- src/core/hle/service/sm/srv.cpp | 17 ++++++----------- src/core/hle/service/sm/srv.h | 3 +++ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp index e311e79f2..a7b494bd1 100644 --- a/src/core/hle/service/sm/srv.cpp +++ b/src/core/hle/service/sm/srv.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include -#include #include "common/common_types.h" #include "common/logging/log.h" #include "core/hle/ipc.h" @@ -25,9 +24,6 @@ namespace SM { constexpr int MAX_PENDING_NOTIFICATIONS = 16; -static std::unordered_map> - get_service_handle_delayed_map; - /** * SRV::RegisterClient service function * Inputs: @@ -136,7 +132,7 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { Kernel::SharedPtr get_service_handle_event = ctx.SleepClientThread(Kernel::GetCurrentThread(), "GetServiceHandle", std::chrono::nanoseconds(-1), get_handle); - get_service_handle_delayed_map[name] = get_service_handle_event; + get_service_handle_delayed_map[name] = std::move(get_service_handle_event); return; } else { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); @@ -232,12 +228,6 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) { auto port = service_manager->RegisterService(name, max_sessions); - if (get_service_handle_delayed_map.find(name) != get_service_handle_delayed_map.end()) { - std::lock_guard lock(HLE::g_hle_lock); - get_service_handle_delayed_map.at(name)->Signal(); - get_service_handle_delayed_map.erase(name); - } - if (port.Failed()) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(port.Code()); @@ -245,6 +235,11 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) { return; } + if (get_service_handle_delayed_map.find(name) != get_service_handle_delayed_map.end()) { + get_service_handle_delayed_map.at(name)->Signal(); + get_service_handle_delayed_map.erase(name); + } + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); rb.Push(RESULT_SUCCESS); rb.PushMoveObjects(port.Unwrap()); diff --git a/src/core/hle/service/sm/srv.h b/src/core/hle/service/sm/srv.h index ab5855620..d3525ca65 100644 --- a/src/core/hle/service/sm/srv.h +++ b/src/core/hle/service/sm/srv.h @@ -4,6 +4,7 @@ #pragma once +#include #include "core/hle/kernel/kernel.h" #include "core/hle/service/service.h" @@ -32,6 +33,8 @@ private: std::shared_ptr service_manager; Kernel::SharedPtr notification_semaphore; + std::unordered_map> + get_service_handle_delayed_map; }; } // namespace SM From ae37b404c6c5c3d971a710201cc8a0914821a536 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 2 Sep 2018 16:42:41 +0200 Subject: [PATCH 3/4] fixup! fixup! Service::SM: Wait till client is registered --- src/core/hle/service/sm/srv.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp index a7b494bd1..a7278db9c 100644 --- a/src/core/hle/service/sm/srv.cpp +++ b/src/core/hle/service/sm/srv.cpp @@ -100,7 +100,7 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { // TODO(yuriks): Permission checks go here - auto get_handle = [name, this, wait_until_available](Kernel::SharedPtr thread, + auto get_handle = [name, this](Kernel::SharedPtr thread, Kernel::HLERequestContext& ctx, ThreadWakeupReason reason) { LOG_ERROR(Service_SRV, "called service={} wakeup", name); @@ -113,11 +113,9 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb(ctx, 0x5, 1, 2); rb.Push(session.Code()); rb.PushMoveObjects(std::move(session).Unwrap()); - } else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED && wait_until_available) { - LOG_WARNING(Service_SRV, "called service={} -> ERR_MAX_CONNECTIONS_REACHED", name); - // TODO(Subv): Put the caller guest thread to sleep until this port becomes available - // again. - UNIMPLEMENTED_MSG("Unimplemented wait until port {} is available.", name); + } else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED) { + LOG_ERROR(Service_SRV, "called service={} -> ERR_MAX_CONNECTIONS_REACHED", name); + UNREACHABLE(); } else { LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, session.Code().raw); IPC::RequestBuilder rb(ctx, 0x5, 1, 0); @@ -127,8 +125,8 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { auto client_port = service_manager->GetServicePort(name); if (client_port.Failed()) { - if (wait_until_available) { - LOG_ERROR(Service_SRV, "called service={} delayed", name); + if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) { + LOG_INFO(Service_SRV, "called service={} delayed", name); Kernel::SharedPtr get_service_handle_event = ctx.SleepClientThread(Kernel::GetCurrentThread(), "GetServiceHandle", std::chrono::nanoseconds(-1), get_handle); @@ -235,9 +233,10 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) { return; } - if (get_service_handle_delayed_map.find(name) != get_service_handle_delayed_map.end()) { - get_service_handle_delayed_map.at(name)->Signal(); - get_service_handle_delayed_map.erase(name); + auto it = get_service_handle_delayed_map.find(name); + if (it != get_service_handle_delayed_map.end()) { + it->second->Signal(); + get_service_handle_delayed_map.erase(it); } IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); From cfd81be6619a02209e90cd8e95039b5b0baf3fda Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 2 Sep 2018 22:50:13 +0200 Subject: [PATCH 4/4] fixup! fixup! Service::SM: Wait till client is registered --- src/core/hle/service/sm/srv.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp index a7278db9c..babcb1f9e 100644 --- a/src/core/hle/service/sm/srv.cpp +++ b/src/core/hle/service/sm/srv.cpp @@ -101,8 +101,7 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { // TODO(yuriks): Permission checks go here auto get_handle = [name, this](Kernel::SharedPtr thread, - Kernel::HLERequestContext& ctx, - ThreadWakeupReason reason) { + Kernel::HLERequestContext& ctx, ThreadWakeupReason reason) { LOG_ERROR(Service_SRV, "called service={} wakeup", name); auto client_port = service_manager->GetServicePort(name);