server_manager.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/scope_exit.h"
  4. #include "core/core.h"
  5. #include "core/hle/kernel/k_client_port.h"
  6. #include "core/hle/kernel/k_client_session.h"
  7. #include "core/hle/kernel/k_event.h"
  8. #include "core/hle/kernel/k_object_name.h"
  9. #include "core/hle/kernel/k_port.h"
  10. #include "core/hle/kernel/k_server_port.h"
  11. #include "core/hle/kernel/k_server_session.h"
  12. #include "core/hle/kernel/k_synchronization_object.h"
  13. #include "core/hle/kernel/svc_results.h"
  14. #include "core/hle/service/hle_ipc.h"
  15. #include "core/hle/service/ipc_helpers.h"
  16. #include "core/hle/service/server_manager.h"
  17. #include "core/hle/service/sm/sm.h"
  18. namespace Service {
  19. enum class UserDataTag {
  20. Port,
  21. Session,
  22. DeferEvent,
  23. };
  24. class Port : public MultiWaitHolder, public Common::IntrusiveListBaseNode<Port> {
  25. public:
  26. explicit Port(Kernel::KServerPort* server_port, SessionRequestHandlerFactory&& handler_factory)
  27. : MultiWaitHolder(server_port), m_handler_factory(std::move(handler_factory)) {
  28. this->SetUserData(static_cast<uintptr_t>(UserDataTag::Port));
  29. }
  30. ~Port() {
  31. this->GetNativeHandle()->Close();
  32. }
  33. SessionRequestHandlerPtr CreateHandler() {
  34. return m_handler_factory();
  35. }
  36. private:
  37. const SessionRequestHandlerFactory m_handler_factory;
  38. };
  39. class Session : public MultiWaitHolder, public Common::IntrusiveListBaseNode<Session> {
  40. public:
  41. explicit Session(Kernel::KServerSession* server_session,
  42. std::shared_ptr<SessionRequestManager>&& manager)
  43. : MultiWaitHolder(server_session), m_manager(std::move(manager)) {
  44. this->SetUserData(static_cast<uintptr_t>(UserDataTag::Session));
  45. }
  46. ~Session() {
  47. this->GetNativeHandle()->Close();
  48. }
  49. std::shared_ptr<SessionRequestManager>& GetManager() {
  50. return m_manager;
  51. }
  52. std::shared_ptr<HLERequestContext>& GetContext() {
  53. return m_context;
  54. }
  55. private:
  56. std::shared_ptr<SessionRequestManager> m_manager;
  57. std::shared_ptr<HLERequestContext> m_context;
  58. };
  59. ServerManager::ServerManager(Core::System& system) : m_system{system}, m_selection_mutex{system} {
  60. // Initialize event.
  61. m_wakeup_event = Kernel::KEvent::Create(system.Kernel());
  62. m_wakeup_event->Initialize(nullptr);
  63. // Register event.
  64. Kernel::KEvent::Register(system.Kernel(), m_wakeup_event);
  65. // Link to holder.
  66. m_wakeup_holder.emplace(std::addressof(m_wakeup_event->GetReadableEvent()));
  67. m_wakeup_holder->LinkToMultiWait(std::addressof(m_deferred_list));
  68. }
  69. ServerManager::~ServerManager() {
  70. // Signal stop.
  71. m_stop_source.request_stop();
  72. m_wakeup_event->Signal();
  73. // Wait for processing to stop.
  74. m_stopped.Wait();
  75. m_threads.clear();
  76. // Clean up ports.
  77. auto port_it = m_servers.begin();
  78. while (port_it != m_servers.end()) {
  79. auto* const port = std::addressof(*port_it);
  80. port_it = m_servers.erase(port_it);
  81. delete port;
  82. }
  83. // Clean up sessions.
  84. auto session_it = m_sessions.begin();
  85. while (session_it != m_sessions.end()) {
  86. auto* const session = std::addressof(*session_it);
  87. session_it = m_sessions.erase(session_it);
  88. delete session;
  89. }
  90. // Close wakeup event.
  91. m_wakeup_event->GetReadableEvent().Close();
  92. m_wakeup_event->Close();
  93. if (m_deferral_event) {
  94. m_deferral_event->GetReadableEvent().Close();
  95. // Write event is owned by ServiceManager
  96. }
  97. }
  98. void ServerManager::RunServer(std::unique_ptr<ServerManager>&& server_manager) {
  99. server_manager->m_system.RunServer(std::move(server_manager));
  100. }
  101. Result ServerManager::RegisterSession(Kernel::KServerSession* server_session,
  102. std::shared_ptr<SessionRequestManager> manager) {
  103. // We are taking ownership of the server session, so don't open it.
  104. auto* session = new Session(server_session, std::move(manager));
  105. // Begin tracking the server session.
  106. {
  107. std::scoped_lock ll{m_deferred_list_mutex};
  108. m_sessions.push_back(*session);
  109. }
  110. // Register to wait on the session.
  111. this->LinkToDeferredList(session);
  112. R_SUCCEED();
  113. }
  114. Result ServerManager::RegisterNamedService(const std::string& service_name,
  115. SessionRequestHandlerFactory&& handler_factory,
  116. u32 max_sessions) {
  117. // Add the new server to sm: and get the moved server port.
  118. Kernel::KServerPort* server_port{};
  119. R_ASSERT(m_system.ServiceManager().RegisterService(std::addressof(server_port), service_name,
  120. max_sessions, handler_factory));
  121. // We are taking ownership of the server port, so don't open it.
  122. auto* server = new Port(server_port, std::move(handler_factory));
  123. // Begin tracking the server port.
  124. {
  125. std::scoped_lock ll{m_deferred_list_mutex};
  126. m_servers.push_back(*server);
  127. }
  128. // Register to wait on the server port.
  129. this->LinkToDeferredList(server);
  130. R_SUCCEED();
  131. }
  132. Result ServerManager::RegisterNamedService(const std::string& service_name,
  133. std::shared_ptr<SessionRequestHandler>&& handler,
  134. u32 max_sessions) {
  135. // Make the factory.
  136. const auto HandlerFactory = [handler]() { return handler; };
  137. // Register the service with the new factory.
  138. R_RETURN(this->RegisterNamedService(service_name, std::move(HandlerFactory), max_sessions));
  139. }
  140. Result ServerManager::ManageNamedPort(const std::string& service_name,
  141. SessionRequestHandlerFactory&& handler_factory,
  142. u32 max_sessions) {
  143. // Create a new port.
  144. auto* port = Kernel::KPort::Create(m_system.Kernel());
  145. port->Initialize(max_sessions, false, 0);
  146. // Register the port.
  147. Kernel::KPort::Register(m_system.Kernel(), port);
  148. // Ensure that our reference to the port is closed if we fail to register it.
  149. SCOPE_EXIT {
  150. port->GetClientPort().Close();
  151. port->GetServerPort().Close();
  152. };
  153. // Register the object name with the kernel.
  154. R_TRY(Kernel::KObjectName::NewFromName(m_system.Kernel(), std::addressof(port->GetClientPort()),
  155. service_name.c_str()));
  156. // Open a new reference to the server port.
  157. port->GetServerPort().Open();
  158. // Transfer ownership into a new port object.
  159. auto* server = new Port(std::addressof(port->GetServerPort()), std::move(handler_factory));
  160. // Begin tracking the port.
  161. {
  162. std::scoped_lock ll{m_deferred_list_mutex};
  163. m_servers.push_back(*server);
  164. }
  165. // Register to wait on the port.
  166. this->LinkToDeferredList(server);
  167. // We succeeded.
  168. R_SUCCEED();
  169. }
  170. Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) {
  171. // Create a new event.
  172. m_deferral_event = Kernel::KEvent::Create(m_system.Kernel());
  173. ASSERT(m_deferral_event != nullptr);
  174. // Initialize the event.
  175. m_deferral_event->Initialize(nullptr);
  176. // Register the event.
  177. Kernel::KEvent::Register(m_system.Kernel(), m_deferral_event);
  178. // Set the output.
  179. *out_event = m_deferral_event;
  180. // Register to wait on the event.
  181. m_deferral_holder.emplace(std::addressof(m_deferral_event->GetReadableEvent()));
  182. m_deferral_holder->SetUserData(static_cast<uintptr_t>(UserDataTag::DeferEvent));
  183. this->LinkToDeferredList(std::addressof(*m_deferral_holder));
  184. // We succeeded.
  185. R_SUCCEED();
  186. }
  187. void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_threads) {
  188. for (size_t i = 0; i < num_threads; i++) {
  189. auto thread_name = fmt::format("{}:{}", name, i + 1);
  190. m_threads.emplace_back(m_system.Kernel().RunOnHostCoreThread(
  191. std::move(thread_name), [&] { this->LoopProcessImpl(); }));
  192. }
  193. }
  194. Result ServerManager::LoopProcess() {
  195. SCOPE_EXIT {
  196. m_stopped.Set();
  197. };
  198. R_RETURN(this->LoopProcessImpl());
  199. }
  200. void ServerManager::LinkToDeferredList(MultiWaitHolder* holder) {
  201. // Link.
  202. {
  203. std::scoped_lock lk{m_deferred_list_mutex};
  204. holder->LinkToMultiWait(std::addressof(m_deferred_list));
  205. }
  206. // Signal the wakeup event.
  207. m_wakeup_event->Signal();
  208. }
  209. void ServerManager::LinkDeferred() {
  210. std::scoped_lock lk{m_deferred_list_mutex};
  211. m_multi_wait.MoveAll(std::addressof(m_deferred_list));
  212. }
  213. MultiWaitHolder* ServerManager::WaitSignaled() {
  214. // Ensure we are the only thread waiting for this server.
  215. std::scoped_lock lk{m_selection_mutex};
  216. while (true) {
  217. this->LinkDeferred();
  218. // If we're done, return before we start waiting.
  219. if (m_stop_source.stop_requested()) {
  220. return nullptr;
  221. }
  222. auto* selected = m_multi_wait.WaitAny(m_system.Kernel());
  223. if (selected == std::addressof(*m_wakeup_holder)) {
  224. // Clear and restart if we were woken up.
  225. m_wakeup_event->Clear();
  226. } else {
  227. // Unlink and handle the event.
  228. selected->UnlinkFromMultiWait();
  229. return selected;
  230. }
  231. }
  232. }
  233. Result ServerManager::Process(MultiWaitHolder* holder) {
  234. switch (static_cast<UserDataTag>(holder->GetUserData())) {
  235. case UserDataTag::Session:
  236. R_RETURN(this->OnSessionEvent(static_cast<Session*>(holder)));
  237. case UserDataTag::Port:
  238. R_RETURN(this->OnPortEvent(static_cast<Port*>(holder)));
  239. case UserDataTag::DeferEvent:
  240. R_RETURN(this->OnDeferralEvent());
  241. default:
  242. UNREACHABLE();
  243. }
  244. }
  245. bool ServerManager::WaitAndProcessImpl() {
  246. if (auto* signaled_holder = this->WaitSignaled(); signaled_holder != nullptr) {
  247. R_ASSERT(this->Process(signaled_holder));
  248. return true;
  249. } else {
  250. return false;
  251. }
  252. }
  253. Result ServerManager::LoopProcessImpl() {
  254. while (!m_stop_source.stop_requested()) {
  255. this->WaitAndProcessImpl();
  256. }
  257. R_SUCCEED();
  258. }
  259. Result ServerManager::OnPortEvent(Port* server) {
  260. // Accept a new server session.
  261. auto* server_port = static_cast<Kernel::KServerPort*>(server->GetNativeHandle());
  262. Kernel::KServerSession* server_session = server_port->AcceptSession();
  263. ASSERT(server_session != nullptr);
  264. // Create the session manager and install the handler.
  265. auto manager = std::make_shared<SessionRequestManager>(m_system.Kernel(), *this);
  266. manager->SetSessionHandler(server->CreateHandler());
  267. // Create and register the new session.
  268. this->RegisterSession(server_session, std::move(manager));
  269. // Resume tracking the port.
  270. this->LinkToDeferredList(server);
  271. // We succeeded.
  272. R_SUCCEED();
  273. }
  274. Result ServerManager::OnSessionEvent(Session* session) {
  275. Result res = ResultSuccess;
  276. // Try to receive a message.
  277. auto* server_session = static_cast<Kernel::KServerSession*>(session->GetNativeHandle());
  278. res = server_session->ReceiveRequestHLE(&session->GetContext(), session->GetManager());
  279. // If the session has been closed, we're done.
  280. if (res == Kernel::ResultSessionClosed) {
  281. this->DestroySession(session);
  282. R_SUCCEED();
  283. }
  284. R_ASSERT(res);
  285. // Complete the sync request with deferral handling.
  286. R_RETURN(this->CompleteSyncRequest(session));
  287. }
  288. Result ServerManager::CompleteSyncRequest(Session* session) {
  289. Result res = ResultSuccess;
  290. Result service_res = ResultSuccess;
  291. // Mark the request as not deferred.
  292. session->GetContext()->SetIsDeferred(false);
  293. // Complete the request. We have exclusive access to this session.
  294. auto* server_session = static_cast<Kernel::KServerSession*>(session->GetNativeHandle());
  295. service_res =
  296. session->GetManager()->CompleteSyncRequest(server_session, *session->GetContext());
  297. // If we've been deferred, we're done.
  298. if (session->GetContext()->GetIsDeferred()) {
  299. // Insert into deferred session list.
  300. std::scoped_lock ll{m_deferred_list_mutex};
  301. m_deferred_sessions.push_back(session);
  302. // Finish.
  303. R_SUCCEED();
  304. }
  305. // Send the reply.
  306. res = server_session->SendReplyHLE();
  307. // If the session has been closed, we're done.
  308. if (res == Kernel::ResultSessionClosed || service_res == IPC::ResultSessionClosed) {
  309. this->DestroySession(session);
  310. R_SUCCEED();
  311. }
  312. R_ASSERT(res);
  313. R_ASSERT(service_res);
  314. // We succeeded, so we can process future messages on this session.
  315. this->LinkToDeferredList(session);
  316. R_SUCCEED();
  317. }
  318. Result ServerManager::OnDeferralEvent() {
  319. // Clear event before grabbing the list.
  320. m_deferral_event->Clear();
  321. // Get and clear list.
  322. const auto deferrals = [&] {
  323. std::scoped_lock lk{m_deferred_list_mutex};
  324. return std::move(m_deferred_sessions);
  325. }();
  326. // Relink deferral event.
  327. this->LinkToDeferredList(std::addressof(*m_deferral_holder));
  328. // For each session, try again to complete the request.
  329. for (auto* session : deferrals) {
  330. R_ASSERT(this->CompleteSyncRequest(session));
  331. }
  332. R_SUCCEED();
  333. }
  334. void ServerManager::DestroySession(Session* session) {
  335. // Unlink.
  336. {
  337. std::scoped_lock lk{m_deferred_list_mutex};
  338. m_sessions.erase(m_sessions.iterator_to(*session));
  339. }
  340. // Free the session.
  341. delete session;
  342. }
  343. } // namespace Service