server_manager.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  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. constexpr size_t MaximumWaitObjects = 0x40;
  20. enum HandleType {
  21. Port,
  22. Session,
  23. DeferEvent,
  24. Event,
  25. };
  26. ServerManager::ServerManager(Core::System& system) : m_system{system}, m_serve_mutex{system} {
  27. // Initialize event.
  28. m_event = Kernel::KEvent::Create(system.Kernel());
  29. m_event->Initialize(nullptr);
  30. // Register event.
  31. Kernel::KEvent::Register(system.Kernel(), m_event);
  32. }
  33. ServerManager::~ServerManager() {
  34. // Signal stop.
  35. m_stop_source.request_stop();
  36. m_event->Signal();
  37. // Wait for processing to stop.
  38. m_stopped.Wait();
  39. m_threads.clear();
  40. // Clean up server ports.
  41. for (const auto& [port, handler] : m_ports) {
  42. port->Close();
  43. }
  44. // Clean up sessions.
  45. for (const auto& [session, manager] : m_sessions) {
  46. session->Close();
  47. }
  48. for (const auto& request : m_deferrals) {
  49. request.session->Close();
  50. }
  51. // Close event.
  52. m_event->GetReadableEvent().Close();
  53. m_event->Close();
  54. if (m_deferral_event) {
  55. m_deferral_event->GetReadableEvent().Close();
  56. // Write event is owned by ServiceManager
  57. }
  58. }
  59. void ServerManager::RunServer(std::unique_ptr<ServerManager>&& server_manager) {
  60. server_manager->m_system.RunServer(std::move(server_manager));
  61. }
  62. Result ServerManager::RegisterSession(Kernel::KServerSession* session,
  63. std::shared_ptr<SessionRequestManager> manager) {
  64. ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects);
  65. // We are taking ownership of the server session, so don't open it.
  66. // Begin tracking the server session.
  67. {
  68. std::scoped_lock ll{m_list_mutex};
  69. m_sessions.emplace(session, std::move(manager));
  70. }
  71. // Signal the wakeup event.
  72. m_event->Signal();
  73. R_SUCCEED();
  74. }
  75. Result ServerManager::RegisterNamedService(const std::string& service_name,
  76. SessionRequestHandlerFactory&& handler_factory,
  77. u32 max_sessions) {
  78. ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects);
  79. // Add the new server to sm: and get the moved server port.
  80. Kernel::KServerPort* server_port{};
  81. R_ASSERT(m_system.ServiceManager().RegisterService(std::addressof(server_port), service_name,
  82. max_sessions, handler_factory));
  83. // Begin tracking the server port.
  84. {
  85. std::scoped_lock ll{m_list_mutex};
  86. m_ports.emplace(server_port, std::move(handler_factory));
  87. }
  88. // Signal the wakeup event.
  89. m_event->Signal();
  90. R_SUCCEED();
  91. }
  92. Result ServerManager::RegisterNamedService(const std::string& service_name,
  93. std::shared_ptr<SessionRequestHandler>&& handler,
  94. u32 max_sessions) {
  95. // Make the factory.
  96. const auto HandlerFactory = [handler]() { return handler; };
  97. // Register the service with the new factory.
  98. R_RETURN(this->RegisterNamedService(service_name, std::move(HandlerFactory), max_sessions));
  99. }
  100. Result ServerManager::ManageNamedPort(const std::string& service_name,
  101. SessionRequestHandlerFactory&& handler_factory,
  102. u32 max_sessions) {
  103. ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects);
  104. // Create a new port.
  105. auto* port = Kernel::KPort::Create(m_system.Kernel());
  106. port->Initialize(max_sessions, false, 0);
  107. // Register the port.
  108. Kernel::KPort::Register(m_system.Kernel(), port);
  109. // Ensure that our reference to the port is closed if we fail to register it.
  110. SCOPE_EXIT({
  111. port->GetClientPort().Close();
  112. port->GetServerPort().Close();
  113. });
  114. // Register the object name with the kernel.
  115. R_TRY(Kernel::KObjectName::NewFromName(m_system.Kernel(), std::addressof(port->GetClientPort()),
  116. service_name.c_str()));
  117. // Open a new reference to the server port.
  118. port->GetServerPort().Open();
  119. // Begin tracking the server port.
  120. {
  121. std::scoped_lock ll{m_list_mutex};
  122. m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler_factory));
  123. }
  124. // We succeeded.
  125. R_SUCCEED();
  126. }
  127. Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) {
  128. // Create a new event.
  129. m_deferral_event = Kernel::KEvent::Create(m_system.Kernel());
  130. ASSERT(m_deferral_event != nullptr);
  131. // Initialize the event.
  132. m_deferral_event->Initialize(nullptr);
  133. // Register the event.
  134. Kernel::KEvent::Register(m_system.Kernel(), m_deferral_event);
  135. // Set the output.
  136. *out_event = m_deferral_event;
  137. // We succeeded.
  138. R_SUCCEED();
  139. }
  140. void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_threads) {
  141. for (size_t i = 0; i < num_threads; i++) {
  142. auto thread_name = fmt::format("{}:{}", name, i + 1);
  143. m_threads.emplace_back(m_system.Kernel().RunOnHostCoreThread(
  144. std::move(thread_name), [&] { this->LoopProcessImpl(); }));
  145. }
  146. }
  147. Result ServerManager::LoopProcess() {
  148. SCOPE_EXIT({ m_stopped.Set(); });
  149. R_RETURN(this->LoopProcessImpl());
  150. }
  151. Result ServerManager::LoopProcessImpl() {
  152. while (!m_stop_source.stop_requested()) {
  153. R_TRY(this->WaitAndProcessImpl());
  154. }
  155. R_SUCCEED();
  156. }
  157. Result ServerManager::WaitAndProcessImpl() {
  158. Kernel::KScopedAutoObject<Kernel::KSynchronizationObject> wait_obj;
  159. HandleType wait_type{};
  160. // Ensure we are the only thread waiting for this server.
  161. std::unique_lock sl{m_serve_mutex};
  162. // If we're done, return before we start waiting.
  163. R_SUCCEED_IF(m_stop_source.stop_requested());
  164. // Wait for a tracked object to become signaled.
  165. {
  166. s32 num_objs{};
  167. std::array<HandleType, MaximumWaitObjects> wait_types{};
  168. std::array<Kernel::KSynchronizationObject*, MaximumWaitObjects> wait_objs{};
  169. const auto AddWaiter{
  170. [&](Kernel::KSynchronizationObject* synchronization_object, HandleType type) {
  171. // Open a new reference to the object.
  172. synchronization_object->Open();
  173. // Insert into the list.
  174. wait_types[num_objs] = type;
  175. wait_objs[num_objs++] = synchronization_object;
  176. }};
  177. {
  178. std::scoped_lock ll{m_list_mutex};
  179. // Add all of our ports.
  180. for (const auto& [port, handler] : m_ports) {
  181. AddWaiter(port, HandleType::Port);
  182. }
  183. // Add all of our sessions.
  184. for (const auto& [session, manager] : m_sessions) {
  185. AddWaiter(session, HandleType::Session);
  186. }
  187. }
  188. // Add the deferral wakeup event.
  189. if (m_deferral_event != nullptr) {
  190. AddWaiter(std::addressof(m_deferral_event->GetReadableEvent()), HandleType::DeferEvent);
  191. }
  192. // Add the wakeup event.
  193. AddWaiter(std::addressof(m_event->GetReadableEvent()), HandleType::Event);
  194. // Clean up extra references on exit.
  195. SCOPE_EXIT({
  196. for (s32 i = 0; i < num_objs; i++) {
  197. wait_objs[i]->Close();
  198. }
  199. });
  200. // Wait for a signal.
  201. s32 out_index{-1};
  202. R_TRY_CATCH(Kernel::KSynchronizationObject::Wait(m_system.Kernel(), &out_index,
  203. wait_objs.data(), num_objs, -1)) {
  204. R_CATCH(Kernel::ResultSessionClosed) {
  205. // On session closed, index is updated and we don't want to return an error.
  206. }
  207. }
  208. R_END_TRY_CATCH;
  209. ASSERT(out_index >= 0 && out_index < num_objs);
  210. // Set the output index.
  211. wait_obj = wait_objs[out_index];
  212. wait_type = wait_types[out_index];
  213. }
  214. // Process what we just received, temporarily removing the object so it is
  215. // not processed concurrently by another thread.
  216. {
  217. switch (wait_type) {
  218. case HandleType::Port: {
  219. // Port signaled.
  220. auto* port = wait_obj->DynamicCast<Kernel::KServerPort*>();
  221. SessionRequestHandlerFactory handler_factory;
  222. // Remove from tracking.
  223. {
  224. std::scoped_lock ll{m_list_mutex};
  225. ASSERT(m_ports.contains(port));
  226. m_ports.at(port).swap(handler_factory);
  227. m_ports.erase(port);
  228. }
  229. // Allow other threads to serve.
  230. sl.unlock();
  231. // Finish.
  232. R_RETURN(this->OnPortEvent(port, std::move(handler_factory)));
  233. }
  234. case HandleType::Session: {
  235. // Session signaled.
  236. auto* session = wait_obj->DynamicCast<Kernel::KServerSession*>();
  237. std::shared_ptr<SessionRequestManager> manager;
  238. // Remove from tracking.
  239. {
  240. std::scoped_lock ll{m_list_mutex};
  241. ASSERT(m_sessions.contains(session));
  242. m_sessions.at(session).swap(manager);
  243. m_sessions.erase(session);
  244. }
  245. // Allow other threads to serve.
  246. sl.unlock();
  247. // Finish.
  248. R_RETURN(this->OnSessionEvent(session, std::move(manager)));
  249. }
  250. case HandleType::DeferEvent: {
  251. // Clear event.
  252. ASSERT(R_SUCCEEDED(m_deferral_event->Clear()));
  253. // Drain the list of deferrals while we process.
  254. std::list<RequestState> deferrals;
  255. {
  256. std::scoped_lock ll{m_list_mutex};
  257. m_deferrals.swap(deferrals);
  258. }
  259. // Allow other threads to serve.
  260. sl.unlock();
  261. // Finish.
  262. R_RETURN(this->OnDeferralEvent(std::move(deferrals)));
  263. }
  264. case HandleType::Event: {
  265. // Clear event and finish.
  266. R_RETURN(m_event->Clear());
  267. }
  268. default: {
  269. UNREACHABLE();
  270. }
  271. }
  272. }
  273. }
  274. Result ServerManager::OnPortEvent(Kernel::KServerPort* port,
  275. SessionRequestHandlerFactory&& handler_factory) {
  276. // Accept a new server session.
  277. Kernel::KServerSession* session = port->AcceptSession();
  278. ASSERT(session != nullptr);
  279. // Create the session manager and install the handler.
  280. auto manager = std::make_shared<SessionRequestManager>(m_system.Kernel(), *this);
  281. manager->SetSessionHandler(handler_factory());
  282. // Track the server session.
  283. {
  284. std::scoped_lock ll{m_list_mutex};
  285. m_ports.emplace(port, std::move(handler_factory));
  286. m_sessions.emplace(session, std::move(manager));
  287. }
  288. // Signal the wakeup event.
  289. m_event->Signal();
  290. // We succeeded.
  291. R_SUCCEED();
  292. }
  293. Result ServerManager::OnSessionEvent(Kernel::KServerSession* session,
  294. std::shared_ptr<SessionRequestManager>&& manager) {
  295. Result rc{ResultSuccess};
  296. // Try to receive a message.
  297. std::shared_ptr<HLERequestContext> context;
  298. rc = session->ReceiveRequestHLE(&context, manager);
  299. // If the session has been closed, we're done.
  300. if (rc == Kernel::ResultSessionClosed) {
  301. // Close the session.
  302. session->Close();
  303. // Finish.
  304. R_SUCCEED();
  305. }
  306. ASSERT(R_SUCCEEDED(rc));
  307. RequestState request{
  308. .session = session,
  309. .context = std::move(context),
  310. .manager = std::move(manager),
  311. };
  312. // Complete the sync request with deferral handling.
  313. R_RETURN(this->CompleteSyncRequest(std::move(request)));
  314. }
  315. Result ServerManager::CompleteSyncRequest(RequestState&& request) {
  316. Result rc{ResultSuccess};
  317. Result service_rc{ResultSuccess};
  318. // Mark the request as not deferred.
  319. request.context->SetIsDeferred(false);
  320. // Complete the request. We have exclusive access to this session.
  321. service_rc = request.manager->CompleteSyncRequest(request.session, *request.context);
  322. // If we've been deferred, we're done.
  323. if (request.context->GetIsDeferred()) {
  324. // Insert into deferral list.
  325. std::scoped_lock ll{m_list_mutex};
  326. m_deferrals.emplace_back(std::move(request));
  327. // Finish.
  328. R_SUCCEED();
  329. }
  330. // Send the reply.
  331. rc = request.session->SendReplyHLE();
  332. // If the session has been closed, we're done.
  333. if (rc == Kernel::ResultSessionClosed || service_rc == IPC::ResultSessionClosed) {
  334. // Close the session.
  335. request.session->Close();
  336. // Finish.
  337. R_SUCCEED();
  338. }
  339. ASSERT(R_SUCCEEDED(rc));
  340. ASSERT(R_SUCCEEDED(service_rc));
  341. // Reinsert the session.
  342. {
  343. std::scoped_lock ll{m_list_mutex};
  344. m_sessions.emplace(request.session, std::move(request.manager));
  345. }
  346. // Signal the wakeup event.
  347. m_event->Signal();
  348. // We succeeded.
  349. R_SUCCEED();
  350. }
  351. Result ServerManager::OnDeferralEvent(std::list<RequestState>&& deferrals) {
  352. ON_RESULT_FAILURE {
  353. std::scoped_lock ll{m_list_mutex};
  354. m_deferrals.splice(m_deferrals.end(), deferrals);
  355. };
  356. while (!deferrals.empty()) {
  357. RequestState request = deferrals.front();
  358. deferrals.pop_front();
  359. // Try again to complete the request.
  360. R_TRY(this->CompleteSyncRequest(std::move(request)));
  361. }
  362. R_SUCCEED();
  363. }
  364. } // namespace Service