summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/svc/svc_session.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/svc/svc_session.cpp')
-rw-r--r--src/core/hle/kernel/svc/svc_session.cpp127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/core/hle/kernel/svc/svc_session.cpp b/src/core/hle/kernel/svc/svc_session.cpp
new file mode 100644
index 000000000..01b8a52ad
--- /dev/null
+++ b/src/core/hle/kernel/svc/svc_session.cpp
@@ -0,0 +1,127 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/scope_exit.h"
+#include "core/core.h"
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_scoped_resource_reservation.h"
+#include "core/hle/kernel/k_session.h"
+#include "core/hle/kernel/svc.h"
+
+namespace Kernel::Svc {
+namespace {
+
+template <typename T>
+Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, uint64_t name) {
+ auto& process = GetCurrentProcess(system.Kernel());
+ auto& handle_table = process.GetHandleTable();
+
+ // Declare the session we're going to allocate.
+ T* session;
+
+ // Reserve a new session from the process resource limit.
+ // FIXME: LimitableResource_SessionCountMax
+ KScopedResourceReservation session_reservation(std::addressof(process),
+ LimitableResource::SessionCountMax);
+ if (session_reservation.Succeeded()) {
+ session = T::Create(system.Kernel());
+ } else {
+ R_THROW(ResultLimitReached);
+
+ // // We couldn't reserve a session. Check that we support dynamically expanding the
+ // // resource limit.
+ // R_UNLESS(process.GetResourceLimit() ==
+ // std::addressof(system.Kernel().GetSystemResourceLimit()), ResultLimitReached);
+ // R_UNLESS(KTargetSystem::IsDynamicResourceLimitsEnabled(), ResultLimitReached());
+
+ // // Try to allocate a session from unused slab memory.
+ // session = T::CreateFromUnusedSlabMemory();
+ // R_UNLESS(session != nullptr, ResultLimitReached);
+ // ON_RESULT_FAILURE { session->Close(); };
+
+ // // If we're creating a KSession, we want to add two KSessionRequests to the heap, to
+ // // prevent request exhaustion.
+ // // NOTE: Nintendo checks if session->DynamicCast<KSession *>() != nullptr, but there's
+ // // no reason to not do this statically.
+ // if constexpr (std::same_as<T, KSession>) {
+ // for (size_t i = 0; i < 2; i++) {
+ // KSessionRequest* request = KSessionRequest::CreateFromUnusedSlabMemory();
+ // R_UNLESS(request != nullptr, ResultLimitReached);
+ // request->Close();
+ // }
+ // }
+
+ // We successfully allocated a session, so add the object we allocated to the resource
+ // limit.
+ // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::SessionCountMax, 1);
+ }
+
+ // Check that we successfully created a session.
+ R_UNLESS(session != nullptr, ResultOutOfResource);
+
+ // Initialize the session.
+ session->Initialize(nullptr, name);
+
+ // Commit the session reservation.
+ session_reservation.Commit();
+
+ // Ensure that we clean up the session (and its only references are handle table) on function
+ // end.
+ SCOPE_EXIT({
+ session->GetClientSession().Close();
+ session->GetServerSession().Close();
+ });
+
+ // Register the session.
+ T::Register(system.Kernel(), session);
+
+ // Add the server session to the handle table.
+ R_TRY(handle_table.Add(out_server, std::addressof(session->GetServerSession())));
+
+ // Ensure that we maintain a clean handle state on exit.
+ ON_RESULT_FAILURE {
+ handle_table.Remove(*out_server);
+ };
+
+ // Add the client session to the handle table.
+ R_RETURN(handle_table.Add(out_client, std::addressof(session->GetClientSession())));
+}
+
+} // namespace
+
+Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, bool is_light,
+ u64 name) {
+ if (is_light) {
+ // return CreateSession<KLightSession>(system, out_server, out_client, name);
+ R_THROW(ResultNotImplemented);
+ } else {
+ R_RETURN(CreateSession<KSession>(system, out_server, out_client, name));
+ }
+}
+
+Result AcceptSession(Core::System& system, Handle* out_handle, Handle port_handle) {
+ UNIMPLEMENTED();
+ R_THROW(ResultNotImplemented);
+}
+
+Result CreateSession64(Core::System& system, Handle* out_server_session_handle,
+ Handle* out_client_session_handle, bool is_light, uint64_t name) {
+ R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
+ name));
+}
+
+Result AcceptSession64(Core::System& system, Handle* out_handle, Handle port) {
+ R_RETURN(AcceptSession(system, out_handle, port));
+}
+
+Result CreateSession64From32(Core::System& system, Handle* out_server_session_handle,
+ Handle* out_client_session_handle, bool is_light, uint32_t name) {
+ R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
+ name));
+}
+
+Result AcceptSession64From32(Core::System& system, Handle* out_handle, Handle port) {
+ R_RETURN(AcceptSession(system, out_handle, port));
+}
+
+} // namespace Kernel::Svc