diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index d70dc2978f..73b3e3a540 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -18,20 +18,15 @@ namespace Service { -/** - * Creates a function string for logging, complete with the name (or header code, depending - * on what's passed in) the port name, and all the cmd_buff arguments. - */ -[[maybe_unused]] static std::string MakeFunctionString(std::string_view name, - std::string_view port_name, - const u32* cmd_buff) { +/// @brief Creates a function string for logging, complete with the name (or header code, depending +/// on what's passed in) the port name, and all the cmd_buff arguments. +[[maybe_unused]] static std::string MakeFunctionString(std::string_view name, std::string_view port_name, const u32* cmd_buff) { // Number of params == bits 0-5 + bits 6-11 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); std::string function_string = fmt::format("function '{}': port={}", name, port_name); - for (int i = 1; i <= num_params; ++i) { + for (int i = 1; i <= num_params; ++i) function_string += fmt::format(", cmd_buff[{}]={:#X}", i, cmd_buff[i]); - } return function_string; } @@ -46,21 +41,17 @@ ServiceFrameworkBase::~ServiceFrameworkBase() { } void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { + // Usually this array is sorted by id already, so hint to insert at the end handlers.reserve(handlers.size() + n); - for (std::size_t i = 0; i < n; ++i) { - // Usually this array is sorted by id already, so hint to insert at the end + for (std::size_t i = 0; i < n; ++i) handlers.emplace_hint(handlers.cend(), functions[i].expected_header, functions[i]); - } } -void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, - std::size_t n) { +void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n) { + // Usually this array is sorted by id already, so hint to insert at the end handlers_tipc.reserve(handlers_tipc.size() + n); - for (std::size_t i = 0; i < n; ++i) { - // Usually this array is sorted by id already, so hint to insert at the end - handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, - functions[i]); - } + for (std::size_t i = 0; i < n; ++i) + handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, functions[i]); } void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx, @@ -69,15 +60,12 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx, std::string function_name = info == nullptr ? "" : info->name; fmt::memory_buffer buf; - fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}", - ctx.GetCommand(), function_name, service_name, cmd_buf[0]); - for (int i = 1; i <= 8; ++i) { + fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}", ctx.GetCommand(), function_name, service_name, cmd_buf[0]); + for (int i = 1; i <= 8; ++i) fmt::format_to(std::back_inserter(buf), ", [{}]={:#X}", i, cmd_buf[i]); - } buf.push_back('}'); - system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, - service_name); + system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, service_name); UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf)); if (Settings::values.use_auto_stub) { LOG_WARNING(Service, "Using auto stub fallback!"); @@ -87,26 +75,19 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx, } void ServiceFrameworkBase::InvokeRequest(HLERequestContext& ctx) { - auto itr = handlers.find(ctx.GetCommand()); - const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second; - if (info == nullptr || info->handler_callback == nullptr) { + auto it = handlers.find(ctx.GetCommand()); + FunctionInfoBase const* info = it == handlers.end() ? nullptr : std::adressof(it->second); + if (info == nullptr || info->handler_callback == nullptr) return ReportUnimplementedFunction(ctx, info); - } - LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer())); handler_invoker(this, info->handler_callback, ctx); } void ServiceFrameworkBase::InvokeRequestTipc(HLERequestContext& ctx) { - boost::container::flat_map::iterator itr; - - itr = handlers_tipc.find(ctx.GetCommand()); - - const FunctionInfoBase* info = itr == handlers_tipc.end() ? nullptr : &itr->second; - if (info == nullptr || info->handler_callback == nullptr) { + auto it = handlers_tipc.find(ctx.GetCommand()); + FunctionInfoBase const* info = it == handlers_tipc.end() ? nullptr : std::adressof(it->second); + if (info == nullptr || info->handler_callback == nullptr) return ReportUnimplementedFunction(ctx, info); - } - LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer())); handler_invoker(this, info->handler_callback, ctx); } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 36aae1c79d..a138361dd7 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -47,25 +50,23 @@ static_assert(ServerSessionCountMax == 0x40, class ServiceFrameworkBase : public SessionRequestHandler { public: /// Returns the string identifier used to connect to the service. - std::string GetServiceName() const { + [[nodiscard]] std::string_view GetServiceName() const noexcept { return service_name; } - /** - * Returns the maximum number of sessions that can be connected to this service at the same - * time. - */ - u32 GetMaxSessions() const { + /// @brief Returns the maximum number of sessions that can be connected to this service at the same + /// time. + u32 GetMaxSessions() const noexcept { return max_sessions; } - /// Invokes a service request routine using the HIPC protocol. + /// @brief Invokes a service request routine using the HIPC protocol. void InvokeRequest(HLERequestContext& ctx); - /// Invokes a service request routine using the HIPC protocol. + /// @brief Invokes a service request routine using the HIPC protocol. void InvokeRequestTipc(HLERequestContext& ctx); - /// Handles a synchronization request for the service. + /// @brief Handles a synchronization request for the service. Result HandleSyncRequest(Kernel::KServerSession& session, HLERequestContext& context) override; protected: @@ -74,7 +75,7 @@ protected: using HandlerFnP = void (Self::*)(HLERequestContext&); /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. - [[nodiscard]] virtual std::unique_lock LockService() { + [[nodiscard]] virtual std::unique_lock LockService() noexcept { return std::unique_lock{lock_service}; } @@ -105,20 +106,17 @@ private: void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n); void ReportUnimplementedFunction(HLERequestContext& ctx, const FunctionInfoBase* info); + boost::container::flat_map handlers; + boost::container::flat_map handlers_tipc; + /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. + std::mutex lock_service; + /// Function used to safely up-cast pointers to the derived class before invoking a handler. + InvokerFn* handler_invoker; /// Maximum number of concurrent sessions that this service can handle. u32 max_sessions; - /// Flag to store if a port was already create/installed to detect multiple install attempts, /// which is not supported. bool service_registered = false; - - /// Function used to safely up-cast pointers to the derived class before invoking a handler. - InvokerFn* handler_invoker; - boost::container::flat_map handlers; - boost::container::flat_map handlers_tipc; - - /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. - std::mutex lock_service; }; /** @@ -142,20 +140,12 @@ protected: // TODO(yuriks): This function could be constexpr, but clang is the only compiler that // doesn't emit an ICE or a wrong diagnostic because of the static_cast. - /** - * Constructs a FunctionInfo for a function. - * - * @param expected_header_ request header in the command buffer which will trigger dispatch - * to this handler - * @param handler_callback_ member function in this service which will be called to handle - * the request - * @param name_ human-friendly name for the request. Used mostly for logging purposes. - */ - FunctionInfoTyped(u32 expected_header_, HandlerFnP handler_callback_, const char* name_) - : FunctionInfoBase{ - expected_header_, - // Type-erase member function pointer by casting it down to the base class. - static_cast>(handler_callback_), name_} {} + /// @brief Constructs a FunctionInfo for a function. + /// @param expected_header_ request header in the command buffer which will trigger dispatch to this handler + /// @param handler_callback_ member function in this service which will be called to handle the request + /// @param name_ human-friendly name for the request. Used mostly for logging purposes. + constexpr FunctionInfoTyped(u32 expected_header_, HandlerFnP handler_callback_, const char* name_) + : FunctionInfoBase{expected_header_, HandlerFnP(handler_callback_), name_} {} }; using FunctionInfo = FunctionInfoTyped; diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index ccc6a7d7f2..69d643ec11 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -188,7 +188,7 @@ private: Network::RoomMember::CallbackHandle proxy_packet_received; protected: - virtual std::unique_lock LockService() override; + virtual std::unique_lock LockService() noexcept override; }; class BSDCFG final : public ServiceFramework {