svc_session.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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_process.h"
  6. #include "core/hle/kernel/k_scoped_resource_reservation.h"
  7. #include "core/hle/kernel/k_session.h"
  8. #include "core/hle/kernel/svc.h"
  9. namespace Kernel::Svc {
  10. namespace {
  11. template <typename T>
  12. Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u64 name) {
  13. auto& process = GetCurrentProcess(system.Kernel());
  14. auto& handle_table = process.GetHandleTable();
  15. // Declare the session we're going to allocate.
  16. T* session;
  17. // Reserve a new session from the process resource limit.
  18. // FIXME: LimitableResource_SessionCountMax
  19. KScopedResourceReservation session_reservation(&process, LimitableResource::SessionCountMax);
  20. if (session_reservation.Succeeded()) {
  21. session = T::Create(system.Kernel());
  22. } else {
  23. return ResultLimitReached;
  24. // // We couldn't reserve a session. Check that we support dynamically expanding the
  25. // // resource limit.
  26. // R_UNLESS(process.GetResourceLimit() ==
  27. // &system.Kernel().GetSystemResourceLimit(), ResultLimitReached);
  28. // R_UNLESS(KTargetSystem::IsDynamicResourceLimitsEnabled(), ResultLimitReached());
  29. // // Try to allocate a session from unused slab memory.
  30. // session = T::CreateFromUnusedSlabMemory();
  31. // R_UNLESS(session != nullptr, ResultLimitReached);
  32. // ON_RESULT_FAILURE { session->Close(); };
  33. // // If we're creating a KSession, we want to add two KSessionRequests to the heap, to
  34. // // prevent request exhaustion.
  35. // // NOTE: Nintendo checks if session->DynamicCast<KSession *>() != nullptr, but there's
  36. // // no reason to not do this statically.
  37. // if constexpr (std::same_as<T, KSession>) {
  38. // for (size_t i = 0; i < 2; i++) {
  39. // KSessionRequest* request = KSessionRequest::CreateFromUnusedSlabMemory();
  40. // R_UNLESS(request != nullptr, ResultLimitReached);
  41. // request->Close();
  42. // }
  43. // }
  44. // We successfully allocated a session, so add the object we allocated to the resource
  45. // limit.
  46. // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::SessionCountMax, 1);
  47. }
  48. // Check that we successfully created a session.
  49. R_UNLESS(session != nullptr, ResultOutOfResource);
  50. // Initialize the session.
  51. session->Initialize(nullptr, fmt::format("{}", name));
  52. // Commit the session reservation.
  53. session_reservation.Commit();
  54. // Ensure that we clean up the session (and its only references are handle table) on function
  55. // end.
  56. SCOPE_EXIT({
  57. session->GetClientSession().Close();
  58. session->GetServerSession().Close();
  59. });
  60. // Register the session.
  61. T::Register(system.Kernel(), session);
  62. // Add the server session to the handle table.
  63. R_TRY(handle_table.Add(out_server, &session->GetServerSession()));
  64. // Add the client session to the handle table.
  65. const auto result = handle_table.Add(out_client, &session->GetClientSession());
  66. if (!R_SUCCEEDED(result)) {
  67. // Ensure that we maintain a clean handle state on exit.
  68. handle_table.Remove(*out_server);
  69. }
  70. return result;
  71. }
  72. } // namespace
  73. Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, bool is_light,
  74. u64 name) {
  75. if (is_light) {
  76. // return CreateSession<KLightSession>(system, out_server, out_client, name);
  77. return ResultNotImplemented;
  78. } else {
  79. return CreateSession<KSession>(system, out_server, out_client, name);
  80. }
  81. }
  82. Result AcceptSession(Core::System& system, Handle* out_handle, Handle port_handle) {
  83. UNIMPLEMENTED();
  84. R_THROW(ResultNotImplemented);
  85. }
  86. Result CreateSession64(Core::System& system, Handle* out_server_session_handle,
  87. Handle* out_client_session_handle, bool is_light, uint64_t name) {
  88. R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
  89. name));
  90. }
  91. Result AcceptSession64(Core::System& system, Handle* out_handle, Handle port) {
  92. R_RETURN(AcceptSession(system, out_handle, port));
  93. }
  94. Result CreateSession64From32(Core::System& system, Handle* out_server_session_handle,
  95. Handle* out_client_session_handle, bool is_light, uint32_t name) {
  96. R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
  97. name));
  98. }
  99. Result AcceptSession64From32(Core::System& system, Handle* out_handle, Handle port) {
  100. R_RETURN(AcceptSession(system, out_handle, port));
  101. }
  102. } // namespace Kernel::Svc