From 58776f5ba842285a432a64f09bdcb32e62451aee Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 9 Apr 2021 15:31:02 -0700 Subject: [PATCH] tipc: server processor fixes (compiles!) --- .../stratosphere/tipc/tipc_server_manager.hpp | 45 ++++++++++--------- .../source/_test/test_tipc_serializer.cpp | 19 +++++++- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/tipc/tipc_server_manager.hpp b/libraries/libstratosphere/include/stratosphere/tipc/tipc_server_manager.hpp index ce218e2b5..52418507f 100644 --- a/libraries/libstratosphere/include/stratosphere/tipc/tipc_server_manager.hpp +++ b/libraries/libstratosphere/include/stratosphere/tipc/tipc_server_manager.hpp @@ -282,6 +282,9 @@ namespace ams::tipc { /* Acquire exclusive server manager access. */ std::scoped_lock lk(m_server_manager->GetMutex()); + /* Increment our session count. */ + ++m_num_sessions; + /* Send information about the session as a message. */ os::SendMessageQueue(std::addressof(m_message_queue), static_cast(MessageType_AddSession) | (static_cast(session_handle) << BITSIZEOF(u32))); os::SendMessageQueue(std::addressof(m_message_queue), static_cast(port_index)); @@ -335,7 +338,7 @@ namespace ams::tipc { using PortManagerTuple = decltype([](std::index_sequence) { return std::tuple...>{}; - }(std::make_index_sequence(NumPorts))); + }(std::make_index_sequence())); using PortAllocatorTuple = std::tuple; private: @@ -369,7 +372,7 @@ namespace ams::tipc { template void InitializePortThread(s32 priority) { /* Create the thread. */ - R_ABORT_UNLESS(os::CreateThread(m_port_threads + Ix, LoopAutoForPortThreadFunction, this, m_port_stacks + Ix, ThreadStackSize, priority)); + R_ABORT_UNLESS(os::CreateThread(m_port_threads + Ix, &LoopAutoForPortThreadFunction, this, m_port_stacks + Ix, ThreadStackSize, priority)); /* Start the thread. */ os::StartThread(m_port_threads + Ix); @@ -390,7 +393,7 @@ namespace ams::tipc { /* Initialize our port managers. */ [this](std::index_sequence) ALWAYS_INLINE_LAMBDA { (this->GetPortManager().Initialize(static_cast(Ix), this), ...); - }(std::make_index_sequence(NumPorts)); + }(std::make_index_sequence()); } template @@ -406,7 +409,7 @@ namespace ams::tipc { [thread_priority, this](std::index_sequence) ALWAYS_INLINE_LAMBDA { /* Create all threads. */ (this->InitializePortThread(thread_priority), ...); - }(std::make_index_sequence(NumPorts - 1)); + }(std::make_index_sequence()); } /* Process for the last port. */ @@ -419,7 +422,7 @@ namespace ams::tipc { /* Try to allocate from each port, in turn. */ tipc::ServiceObjectBase *allocated = nullptr; - return [this, port_index, &allocated](std::index_sequence) ALWAYS_INLINE_LAMBDA { + [this, port_index, &allocated](std::index_sequence) ALWAYS_INLINE_LAMBDA { (this->TryAllocateObject(port_index, allocated), ...); }(std::make_index_sequence()); @@ -466,7 +469,7 @@ namespace ams::tipc { R_TRY_CATCH(port_manager.ReplyAndReceive(std::addressof(signaled_holder), std::addressof(signaled_object), reply_target)) { R_CATCH(os::ResultSessionClosedForReceive, os::ResultReceiveListBroken) { /* Close the object and continue. */ - port_manager.CloseObject(signaled_object); + port_manager.CloseSession(signaled_object); /* We have nothing to reply to. */ reply_target = svc::InvalidHandle; @@ -523,7 +526,7 @@ namespace ams::tipc { } } else { /* Our message queue was signaled. */ - port_manager.ProcessMessages(this); + port_manager.ProcessMessages(); /* We have nothing to reply to. */ reply_target = svc::InvalidHandle; @@ -538,7 +541,7 @@ namespace ams::tipc { /* Select the best port manager. */ PortManagerBase *best_manager = nullptr; s32 best_sessions = -1; - const auto session_counts = [this, &best_manager, &best_sessions](std::index_sequence) ALWAYS_INLINE_LAMBDA { + [this, &best_manager, &best_sessions](std::index_sequence) ALWAYS_INLINE_LAMBDA { (this->TrySelectBetterPort(best_manager, best_sessions), ...); }(std::make_index_sequence()); @@ -548,22 +551,20 @@ namespace ams::tipc { template requires (Ix < NumPorts) void TrySelectBetterPort(PortManagerBase *&best_manager, s32 &best_sessions) { + auto &cur_manager = this->GetPortManager(); + const auto cur_sessions = cur_manager.GetSessionCount(); + + /* NOTE: It's unknown how nintendo handles the case where the last manager has more sessions (to cover the remainder). */ + /* Our algorithm diverges from theirs (it does not do std::min bounds capping), to accommodate remainder ports. */ + /* If we learn how they handle this edge case, we can change our ways to match theirs. */ + if constexpr (Ix == 0) { - best_manager = std::addressof(this->GetPortManager()); - best_sessions = std::min(best_manager->GetSessionCount(), static_cast(SessionsPerPortManager)); - } else if constexpr (Ix < NumPorts - 1) { - auto &cur_manager = this->GetPortManager(); - const auto cur_sessions = std::min(cur_manager.GetSessionCount(), static_cast(SessionsPerPortManager)); - - if (cur_sessions < best_sessions) { - best_manager = std::addressof(cur_manager); - best_sessions = cur_sessions; - } + best_manager = std::addressof(cur_manager); + best_sessions = cur_sessions; } else { - auto &cur_manager = this->GetPortManager(); - const auto cur_sessions = cur_manager.GetSessionCount(); - - if (cur_sessions < best_sessions) { + static_assert(SessionsPerPortManager == SessionsPerPortManager<0>); + static_assert(SessionsPerPortManager <= SessionsPerPortManager); + if (cur_sessions < best_sessions || best_sessions >= static_cast(SessionsPerPortManager)) { best_manager = std::addressof(cur_manager); best_sessions = cur_sessions; } diff --git a/libraries/libstratosphere/source/_test/test_tipc_serializer.cpp b/libraries/libstratosphere/source/_test/test_tipc_serializer.cpp index 7675990d7..62daba4de 100644 --- a/libraries/libstratosphere/source/_test/test_tipc_serializer.cpp +++ b/libraries/libstratosphere/source/_test/test_tipc_serializer.cpp @@ -52,15 +52,30 @@ namespace ams::_test { using UserInterfaceObject = ::ams::tipc::ServiceObject; + using ManagerInterfaceObject = ::ams::tipc::ServiceObject; + Result TestAutomaticDispatch(UserInterfaceObject *object) { return object->ProcessRequest(); } - using ManagerInterfaceObject = ::ams::tipc::ServiceObject; - Result TestManagerDispatch(ManagerInterfaceObject *object) { return object->ProcessRequest(); } + using UserPortMeta = tipc::PortMeta<69, impl::IUserInterface, UserInterfaceFacade, tipc::SlabAllocator>; + using ManagerPortMeta = tipc::PortMeta< 1, impl::IManagerInterface, ManagerInterfaceFacade, tipc::SingletonAllocator>; + + using TestServerManager = tipc::ServerManager; + + namespace { + + TestServerManager g_test_server_manager; + + } + + void TestLoop() { + g_test_server_manager.LoopAuto(); + } + } \ No newline at end of file