summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Liam2022-10-16 01:53:56 -0400
committerGravatar Liam2022-10-31 17:44:06 -0400
commit983f2b70741f17f30fe2321451f10cabecc013d2 (patch)
treec1ac3c1033fdeefaabe76590ca204c4c1b2a98cd /src
parentMerge pull request #9159 from liamwhite/kbork (diff)
downloadyuzu-983f2b70741f17f30fe2321451f10cabecc013d2.tar.gz
yuzu-983f2b70741f17f30fe2321451f10cabecc013d2.tar.xz
yuzu-983f2b70741f17f30fe2321451f10cabecc013d2.zip
kernel: invert session request handling flow
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/ipc_helpers.h17
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp55
-rw-r--r--src/core/hle/kernel/hle_ipc.h29
-rw-r--r--src/core/hle/kernel/k_client_port.cpp5
-rw-r--r--src/core/hle/kernel/k_client_port.h3
-rw-r--r--src/core/hle/kernel/k_port.cpp6
-rw-r--r--src/core/hle/kernel/k_server_port.cpp5
-rw-r--r--src/core/hle/kernel/k_server_port.h19
-rw-r--r--src/core/hle/kernel/k_server_session.cpp187
-rw-r--r--src/core/hle/kernel/k_server_session.h37
-rw-r--r--src/core/hle/kernel/k_session.cpp5
-rw-r--r--src/core/hle/kernel/k_session.h3
-rw-r--r--src/core/hle/kernel/kernel.cpp24
-rw-r--r--src/core/hle/kernel/kernel.h9
-rw-r--r--src/core/hle/kernel/service_thread.cpp232
-rw-r--r--src/core/hle/kernel/service_thread.h6
-rw-r--r--src/core/hle/kernel/svc.cpp6
-rw-r--r--src/core/hle/service/service.cpp13
-rw-r--r--src/core/hle/service/service.h4
-rw-r--r--src/core/hle/service/sm/sm.cpp13
-rw-r--r--src/core/hle/service/sm/sm.h1
-rw-r--r--src/core/hle/service/sm/sm_controller.cpp21
22 files changed, 421 insertions, 279 deletions
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 18fde8bd6..3bb111748 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -86,13 +86,13 @@ public:
86 u32 num_domain_objects{}; 86 u32 num_domain_objects{};
87 const bool always_move_handles{ 87 const bool always_move_handles{
88 (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; 88 (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0};
89 if (!ctx.Session()->GetSessionRequestManager()->IsDomain() || always_move_handles) { 89 if (!ctx.GetManager()->IsDomain() || always_move_handles) {
90 num_handles_to_move = num_objects_to_move; 90 num_handles_to_move = num_objects_to_move;
91 } else { 91 } else {
92 num_domain_objects = num_objects_to_move; 92 num_domain_objects = num_objects_to_move;
93 } 93 }
94 94
95 if (ctx.Session()->GetSessionRequestManager()->IsDomain()) { 95 if (ctx.GetManager()->IsDomain()) {
96 raw_data_size += 96 raw_data_size +=
97 static_cast<u32>(sizeof(DomainMessageHeader) / sizeof(u32) + num_domain_objects); 97 static_cast<u32>(sizeof(DomainMessageHeader) / sizeof(u32) + num_domain_objects);
98 ctx.write_size += num_domain_objects; 98 ctx.write_size += num_domain_objects;
@@ -125,8 +125,7 @@ public:
125 if (!ctx.IsTipc()) { 125 if (!ctx.IsTipc()) {
126 AlignWithPadding(); 126 AlignWithPadding();
127 127
128 if (ctx.Session()->GetSessionRequestManager()->IsDomain() && 128 if (ctx.GetManager()->IsDomain() && ctx.HasDomainMessageHeader()) {
129 ctx.HasDomainMessageHeader()) {
130 IPC::DomainMessageHeader domain_header{}; 129 IPC::DomainMessageHeader domain_header{};
131 domain_header.num_objects = num_domain_objects; 130 domain_header.num_objects = num_domain_objects;
132 PushRaw(domain_header); 131 PushRaw(domain_header);
@@ -146,18 +145,18 @@ public:
146 145
147 template <class T> 146 template <class T>
148 void PushIpcInterface(std::shared_ptr<T> iface) { 147 void PushIpcInterface(std::shared_ptr<T> iface) {
149 if (context->Session()->GetSessionRequestManager()->IsDomain()) { 148 if (context->GetManager()->IsDomain()) {
150 context->AddDomainObject(std::move(iface)); 149 context->AddDomainObject(std::move(iface));
151 } else { 150 } else {
152 kernel.CurrentProcess()->GetResourceLimit()->Reserve( 151 kernel.CurrentProcess()->GetResourceLimit()->Reserve(
153 Kernel::LimitableResource::Sessions, 1); 152 Kernel::LimitableResource::Sessions, 1);
154 153
155 auto* session = Kernel::KSession::Create(kernel); 154 auto* session = Kernel::KSession::Create(kernel);
156 session->Initialize(nullptr, iface->GetServiceName(), 155 session->Initialize(nullptr, iface->GetServiceName());
157 std::make_shared<Kernel::SessionRequestManager>(kernel)); 156 iface->RegisterSession(&session->GetServerSession(),
157 std::make_shared<Kernel::SessionRequestManager>(kernel));
158 158
159 context->AddMoveObject(&session->GetClientSession()); 159 context->AddMoveObject(&session->GetClientSession());
160 iface->ClientConnected(&session->GetServerSession());
161 } 160 }
162 } 161 }
163 162
@@ -387,7 +386,7 @@ public:
387 386
388 template <class T> 387 template <class T>
389 std::weak_ptr<T> PopIpcInterface() { 388 std::weak_ptr<T> PopIpcInterface() {
390 ASSERT(context->Session()->GetSessionRequestManager()->IsDomain()); 389 ASSERT(context->GetManager()->IsDomain());
391 ASSERT(context->GetDomainMessageHeader().input_object_count > 0); 390 ASSERT(context->GetDomainMessageHeader().input_object_count > 0);
392 return context->GetDomainHandler<T>(Pop<u32>() - 1); 391 return context->GetDomainHandler<T>(Pop<u32>() - 1);
393 } 392 }
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index e4f43a053..fd354d484 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -16,6 +16,7 @@
16#include "core/hle/kernel/k_auto_object.h" 16#include "core/hle/kernel/k_auto_object.h"
17#include "core/hle/kernel/k_handle_table.h" 17#include "core/hle/kernel/k_handle_table.h"
18#include "core/hle/kernel/k_process.h" 18#include "core/hle/kernel/k_process.h"
19#include "core/hle/kernel/k_server_port.h"
19#include "core/hle/kernel/k_server_session.h" 20#include "core/hle/kernel/k_server_session.h"
20#include "core/hle/kernel/k_thread.h" 21#include "core/hle/kernel/k_thread.h"
21#include "core/hle/kernel/kernel.h" 22#include "core/hle/kernel/kernel.h"
@@ -35,7 +36,21 @@ SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* se
35} 36}
36 37
37SessionRequestHandler::~SessionRequestHandler() { 38SessionRequestHandler::~SessionRequestHandler() {
38 kernel.ReleaseServiceThread(service_thread); 39 kernel.ReleaseServiceThread(service_thread.lock());
40}
41
42void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
43 auto* server_session = server_port->AcceptSession();
44 ASSERT(server_session != nullptr);
45
46 RegisterSession(server_session, std::make_shared<SessionRequestManager>(kernel));
47}
48
49void SessionRequestHandler::RegisterSession(KServerSession* server_session,
50 std::shared_ptr<SessionRequestManager> manager) {
51 manager->SetSessionHandler(shared_from_this());
52 service_thread.lock()->RegisterServerSession(server_session, manager);
53 server_session->Close();
39} 54}
40 55
41SessionRequestManager::SessionRequestManager(KernelCore& kernel_) : kernel{kernel_} {} 56SessionRequestManager::SessionRequestManager(KernelCore& kernel_) : kernel{kernel_} {}
@@ -92,7 +107,7 @@ Result SessionRequestManager::HandleDomainSyncRequest(KServerSession* server_ses
92 } 107 }
93 108
94 // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs 109 // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs
95 context.SetSessionRequestManager(server_session->GetSessionRequestManager()); 110 ASSERT(context.GetManager().get() == this);
96 111
97 // If there is a DomainMessageHeader, then this is CommandType "Request" 112 // If there is a DomainMessageHeader, then this is CommandType "Request"
98 const auto& domain_message_header = context.GetDomainMessageHeader(); 113 const auto& domain_message_header = context.GetDomainMessageHeader();
@@ -130,31 +145,6 @@ Result SessionRequestManager::HandleDomainSyncRequest(KServerSession* server_ses
130 return ResultSuccess; 145 return ResultSuccess;
131} 146}
132 147
133Result SessionRequestManager::QueueSyncRequest(KSession* parent,
134 std::shared_ptr<HLERequestContext>&& context) {
135 // Ensure we have a session request handler
136 if (this->HasSessionRequestHandler(*context)) {
137 if (auto strong_ptr = this->GetServiceThread().lock()) {
138 strong_ptr->QueueSyncRequest(*parent, std::move(context));
139 } else {
140 ASSERT_MSG(false, "strong_ptr is nullptr!");
141 }
142 } else {
143 ASSERT_MSG(false, "handler is invalid!");
144 }
145
146 return ResultSuccess;
147}
148
149void SessionRequestHandler::ClientConnected(KServerSession* session) {
150 session->GetSessionRequestManager()->SetSessionHandler(shared_from_this());
151
152 // Ensure our server session is tracked globally.
153 kernel.RegisterServerObject(session);
154}
155
156void SessionRequestHandler::ClientDisconnected(KServerSession* session) {}
157
158HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, 148HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_,
159 KServerSession* server_session_, KThread* thread_) 149 KServerSession* server_session_, KThread* thread_)
160 : server_session(server_session_), thread(thread_), kernel{kernel_}, memory{memory_} { 150 : server_session(server_session_), thread(thread_), kernel{kernel_}, memory{memory_} {
@@ -214,7 +204,7 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
214 // Padding to align to 16 bytes 204 // Padding to align to 16 bytes
215 rp.AlignWithPadding(); 205 rp.AlignWithPadding();
216 206
217 if (Session()->GetSessionRequestManager()->IsDomain() && 207 if (GetManager()->IsDomain() &&
218 ((command_header->type == IPC::CommandType::Request || 208 ((command_header->type == IPC::CommandType::Request ||
219 command_header->type == IPC::CommandType::RequestWithContext) || 209 command_header->type == IPC::CommandType::RequestWithContext) ||
220 !incoming)) { 210 !incoming)) {
@@ -223,7 +213,7 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
223 if (incoming || domain_message_header) { 213 if (incoming || domain_message_header) {
224 domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); 214 domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>();
225 } else { 215 } else {
226 if (Session()->GetSessionRequestManager()->IsDomain()) { 216 if (GetManager()->IsDomain()) {
227 LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); 217 LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!");
228 } 218 }
229 } 219 }
@@ -316,12 +306,11 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_threa
316 // Write the domain objects to the command buffer, these go after the raw untranslated data. 306 // Write the domain objects to the command buffer, these go after the raw untranslated data.
317 // TODO(Subv): This completely ignores C buffers. 307 // TODO(Subv): This completely ignores C buffers.
318 308
319 if (server_session->GetSessionRequestManager()->IsDomain()) { 309 if (GetManager()->IsDomain()) {
320 current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size()); 310 current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size());
321 for (auto& object : outgoing_domain_objects) { 311 for (auto& object : outgoing_domain_objects) {
322 server_session->GetSessionRequestManager()->AppendDomainHandler(std::move(object)); 312 GetManager()->AppendDomainHandler(std::move(object));
323 cmd_buf[current_offset++] = static_cast<u32_le>( 313 cmd_buf[current_offset++] = static_cast<u32_le>(GetManager()->DomainHandlerCount());
324 server_session->GetSessionRequestManager()->DomainHandlerCount());
325 } 314 }
326 } 315 }
327 316
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 1083638a9..67da8e7e1 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -45,11 +45,13 @@ class KAutoObject;
45class KernelCore; 45class KernelCore;
46class KEvent; 46class KEvent;
47class KHandleTable; 47class KHandleTable;
48class KServerPort;
48class KProcess; 49class KProcess;
49class KServerSession; 50class KServerSession;
50class KThread; 51class KThread;
51class KReadableEvent; 52class KReadableEvent;
52class KSession; 53class KSession;
54class SessionRequestManager;
53class ServiceThread; 55class ServiceThread;
54 56
55enum class ThreadWakeupReason; 57enum class ThreadWakeupReason;
@@ -76,19 +78,9 @@ public:
76 virtual Result HandleSyncRequest(Kernel::KServerSession& session, 78 virtual Result HandleSyncRequest(Kernel::KServerSession& session,
77 Kernel::HLERequestContext& context) = 0; 79 Kernel::HLERequestContext& context) = 0;
78 80
79 /** 81 void AcceptSession(KServerPort* server_port);
80 * Signals that a client has just connected to this HLE handler and keeps the 82 void RegisterSession(KServerSession* server_session,
81 * associated ServerSession alive for the duration of the connection. 83 std::shared_ptr<SessionRequestManager> manager);
82 * @param server_session Owning pointer to the ServerSession associated with the connection.
83 */
84 void ClientConnected(KServerSession* session);
85
86 /**
87 * Signals that a client has just disconnected from this HLE handler and releases the
88 * associated ServerSession.
89 * @param server_session ServerSession associated with the connection.
90 */
91 void ClientDisconnected(KServerSession* session);
92 84
93 std::weak_ptr<ServiceThread> GetServiceThread() const { 85 std::weak_ptr<ServiceThread> GetServiceThread() const {
94 return service_thread; 86 return service_thread;
@@ -170,7 +162,6 @@ public:
170 162
171 Result HandleDomainSyncRequest(KServerSession* server_session, HLERequestContext& context); 163 Result HandleDomainSyncRequest(KServerSession* server_session, HLERequestContext& context);
172 Result CompleteSyncRequest(KServerSession* server_session, HLERequestContext& context); 164 Result CompleteSyncRequest(KServerSession* server_session, HLERequestContext& context);
173 Result QueueSyncRequest(KSession* parent, std::shared_ptr<HLERequestContext>&& context);
174 165
175private: 166private:
176 bool convert_to_domain{}; 167 bool convert_to_domain{};
@@ -350,11 +341,11 @@ public:
350 341
351 template <typename T> 342 template <typename T>
352 std::shared_ptr<T> GetDomainHandler(std::size_t index) const { 343 std::shared_ptr<T> GetDomainHandler(std::size_t index) const {
353 return std::static_pointer_cast<T>(manager.lock()->DomainHandler(index).lock()); 344 return std::static_pointer_cast<T>(GetManager()->DomainHandler(index).lock());
354 } 345 }
355 346
356 void SetSessionRequestManager(std::weak_ptr<SessionRequestManager> manager_) { 347 void SetSessionRequestManager(std::weak_ptr<SessionRequestManager> manager_) {
357 manager = std::move(manager_); 348 manager = manager_;
358 } 349 }
359 350
360 std::string Description() const; 351 std::string Description() const;
@@ -363,6 +354,10 @@ public:
363 return *thread; 354 return *thread;
364 } 355 }
365 356
357 std::shared_ptr<SessionRequestManager> GetManager() const {
358 return manager.lock();
359 }
360
366private: 361private:
367 friend class IPC::ResponseBuilder; 362 friend class IPC::ResponseBuilder;
368 363
@@ -396,7 +391,7 @@ private:
396 u32 handles_offset{}; 391 u32 handles_offset{};
397 u32 domain_offset{}; 392 u32 domain_offset{};
398 393
399 std::weak_ptr<SessionRequestManager> manager; 394 std::weak_ptr<SessionRequestManager> manager{};
400 395
401 KernelCore& kernel; 396 KernelCore& kernel;
402 Core::Memory::Memory& memory; 397 Core::Memory::Memory& memory;
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp
index 3cb22ff4d..eaa2e094c 100644
--- a/src/core/hle/kernel/k_client_port.cpp
+++ b/src/core/hle/kernel/k_client_port.cpp
@@ -58,8 +58,7 @@ bool KClientPort::IsSignaled() const {
58 return num_sessions < max_sessions; 58 return num_sessions < max_sessions;
59} 59}
60 60
61Result KClientPort::CreateSession(KClientSession** out, 61Result KClientPort::CreateSession(KClientSession** out) {
62 std::shared_ptr<SessionRequestManager> session_manager) {
63 // Reserve a new session from the resource limit. 62 // Reserve a new session from the resource limit.
64 KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), 63 KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
65 LimitableResource::Sessions); 64 LimitableResource::Sessions);
@@ -104,7 +103,7 @@ Result KClientPort::CreateSession(KClientSession** out,
104 } 103 }
105 104
106 // Initialize the session. 105 // Initialize the session.
107 session->Initialize(this, parent->GetName(), session_manager); 106 session->Initialize(this, parent->GetName());
108 107
109 // Commit the session reservation. 108 // Commit the session reservation.
110 session_reservation.Commit(); 109 session_reservation.Commit();
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h
index e17eff28f..81046fb86 100644
--- a/src/core/hle/kernel/k_client_port.h
+++ b/src/core/hle/kernel/k_client_port.h
@@ -52,8 +52,7 @@ public:
52 void Destroy() override; 52 void Destroy() override;
53 bool IsSignaled() const override; 53 bool IsSignaled() const override;
54 54
55 Result CreateSession(KClientSession** out, 55 Result CreateSession(KClientSession** out);
56 std::shared_ptr<SessionRequestManager> session_manager = nullptr);
57 56
58private: 57private:
59 std::atomic<s32> num_sessions{}; 58 std::atomic<s32> num_sessions{};
diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp
index 7a5a9dc2a..77d00ae2c 100644
--- a/src/core/hle/kernel/k_port.cpp
+++ b/src/core/hle/kernel/k_port.cpp
@@ -57,12 +57,6 @@ Result KPort::EnqueueSession(KServerSession* session) {
57 57
58 server.EnqueueSession(session); 58 server.EnqueueSession(session);
59 59
60 if (auto session_ptr = server.GetSessionRequestHandler().lock()) {
61 session_ptr->ClientConnected(server.AcceptSession());
62 } else {
63 ASSERT(false);
64 }
65
66 return ResultSuccess; 60 return ResultSuccess;
67} 61}
68 62
diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp
index e968f26ad..12e0c3ffb 100644
--- a/src/core/hle/kernel/k_server_port.cpp
+++ b/src/core/hle/kernel/k_server_port.cpp
@@ -19,6 +19,8 @@ void KServerPort::Initialize(KPort* parent_port_, std::string&& name_) {
19 // Set member variables. 19 // Set member variables.
20 parent = parent_port_; 20 parent = parent_port_;
21 name = std::move(name_); 21 name = std::move(name_);
22
23 kernel.RegisterServerObject(this);
22} 24}
23 25
24bool KServerPort::IsLight() const { 26bool KServerPort::IsLight() const {
@@ -62,9 +64,6 @@ void KServerPort::Destroy() {
62 // Close our reference to our parent. 64 // Close our reference to our parent.
63 parent->Close(); 65 parent->Close();
64 66
65 // Release host emulation members.
66 session_handler.reset();
67
68 // Ensure that the global list tracking server objects does not hold on to a reference. 67 // Ensure that the global list tracking server objects does not hold on to a reference.
69 kernel.UnregisterServerObject(this); 68 kernel.UnregisterServerObject(this);
70} 69}
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h
index fd4f4bd20..5fc7ee683 100644
--- a/src/core/hle/kernel/k_server_port.h
+++ b/src/core/hle/kernel/k_server_port.h
@@ -27,24 +27,6 @@ public:
27 27
28 void Initialize(KPort* parent_port_, std::string&& name_); 28 void Initialize(KPort* parent_port_, std::string&& name_);
29 29
30 /// Whether or not this server port has an HLE handler available.
31 bool HasSessionRequestHandler() const {
32 return !session_handler.expired();
33 }
34
35 /// Gets the HLE handler for this port.
36 SessionRequestHandlerWeakPtr GetSessionRequestHandler() const {
37 return session_handler;
38 }
39
40 /**
41 * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port
42 * will inherit a reference to this handler.
43 */
44 void SetSessionHandler(SessionRequestHandlerWeakPtr&& handler) {
45 session_handler = std::move(handler);
46 }
47
48 void EnqueueSession(KServerSession* pending_session); 30 void EnqueueSession(KServerSession* pending_session);
49 31
50 KServerSession* AcceptSession(); 32 KServerSession* AcceptSession();
@@ -65,7 +47,6 @@ private:
65 void CleanupSessions(); 47 void CleanupSessions();
66 48
67 SessionList session_list; 49 SessionList session_list;
68 SessionRequestHandlerWeakPtr session_handler;
69 KPort* parent{}; 50 KPort* parent{};
70}; 51};
71 52
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index faf03fcc8..aa1941f01 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <tuple> 4#include <tuple>
@@ -33,12 +33,10 @@ KServerSession::KServerSession(KernelCore& kernel_)
33 33
34KServerSession::~KServerSession() = default; 34KServerSession::~KServerSession() = default;
35 35
36void KServerSession::Initialize(KSession* parent_session_, std::string&& name_, 36void KServerSession::Initialize(KSession* parent_session_, std::string&& name_) {
37 std::shared_ptr<SessionRequestManager> manager_) {
38 // Set member variables. 37 // Set member variables.
39 parent = parent_session_; 38 parent = parent_session_;
40 name = std::move(name_); 39 name = std::move(name_);
41 manager = manager_;
42} 40}
43 41
44void KServerSession::Destroy() { 42void KServerSession::Destroy() {
@@ -47,18 +45,99 @@ void KServerSession::Destroy() {
47 this->CleanupRequests(); 45 this->CleanupRequests();
48 46
49 parent->Close(); 47 parent->Close();
50
51 // Release host emulation members.
52 manager.reset();
53
54 // Ensure that the global list tracking server objects does not hold on to a reference.
55 kernel.UnregisterServerObject(this);
56} 48}
57 49
58void KServerSession::OnClientClosed() { 50void KServerSession::OnClientClosed() {
59 if (manager && manager->HasSessionHandler()) { 51 KScopedLightLock lk{m_lock};
60 manager->SessionHandler().ClientDisconnected(this); 52
53 // Handle any pending requests.
54 KSessionRequest* prev_request = nullptr;
55 while (true) {
56 // Declare variables for processing the request.
57 KSessionRequest* request = nullptr;
58 KEvent* event = nullptr;
59 KThread* thread = nullptr;
60 bool cur_request = false;
61 bool terminate = false;
62
63 // Get the next request.
64 {
65 KScopedSchedulerLock sl{kernel};
66
67 if (m_current_request != nullptr && m_current_request != prev_request) {
68 // Set the request, open a reference as we process it.
69 request = m_current_request;
70 request->Open();
71 cur_request = true;
72
73 // Get thread and event for the request.
74 thread = request->GetThread();
75 event = request->GetEvent();
76
77 // If the thread is terminating, handle that.
78 if (thread->IsTerminationRequested()) {
79 request->ClearThread();
80 request->ClearEvent();
81 terminate = true;
82 }
83
84 prev_request = request;
85 } else if (!m_request_list.empty()) {
86 // Pop the request from the front of the list.
87 request = std::addressof(m_request_list.front());
88 m_request_list.pop_front();
89
90 // Get thread and event for the request.
91 thread = request->GetThread();
92 event = request->GetEvent();
93 }
94 }
95
96 // If there are no requests, we're done.
97 if (request == nullptr) {
98 break;
99 }
100
101 // All requests must have threads.
102 ASSERT(thread != nullptr);
103
104 // Ensure that we close the request when done.
105 SCOPE_EXIT({ request->Close(); });
106
107 // If we're terminating, close a reference to the thread and event.
108 if (terminate) {
109 thread->Close();
110 if (event != nullptr) {
111 event->Close();
112 }
113 }
114
115 // If we need to, reply.
116 if (event != nullptr && !cur_request) {
117 // There must be no mappings.
118 ASSERT(request->GetSendCount() == 0);
119 ASSERT(request->GetReceiveCount() == 0);
120 ASSERT(request->GetExchangeCount() == 0);
121
122 // // Get the process and page table.
123 // KProcess *client_process = thread->GetOwnerProcess();
124 // auto &client_pt = client_process->GetPageTable();
125
126 // // Reply to the request.
127 // ReplyAsyncError(client_process, request->GetAddress(), request->GetSize(),
128 // ResultSessionClosed);
129
130 // // Unlock the buffer.
131 // // NOTE: Nintendo does not check the result of this.
132 // client_pt.UnlockForIpcUserBuffer(request->GetAddress(), request->GetSize());
133
134 // Signal the event.
135 event->Signal();
136 }
61 } 137 }
138
139 // Notify.
140 this->NotifyAvailable(ResultSessionClosed);
62} 141}
63 142
64bool KServerSession::IsSignaled() const { 143bool KServerSession::IsSignaled() const {
@@ -73,24 +152,6 @@ bool KServerSession::IsSignaled() const {
73 return !m_request_list.empty() && m_current_request == nullptr; 152 return !m_request_list.empty() && m_current_request == nullptr;
74} 153}
75 154
76Result KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) {
77 u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(thread->GetTLSAddress()))};
78 auto context = std::make_shared<HLERequestContext>(kernel, memory, this, thread);
79
80 context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
81
82 return manager->QueueSyncRequest(parent, std::move(context));
83}
84
85Result KServerSession::CompleteSyncRequest(HLERequestContext& context) {
86 Result result = manager->CompleteSyncRequest(this, context);
87
88 // The calling thread is waiting for this request to complete, so wake it up.
89 context.GetThread().EndWait(result);
90
91 return result;
92}
93
94Result KServerSession::OnRequest(KSessionRequest* request) { 155Result KServerSession::OnRequest(KSessionRequest* request) {
95 // Create the wait queue. 156 // Create the wait queue.
96 ThreadQueueImplForKServerSessionRequest wait_queue{kernel}; 157 ThreadQueueImplForKServerSessionRequest wait_queue{kernel};
@@ -105,24 +166,16 @@ Result KServerSession::OnRequest(KSessionRequest* request) {
105 // Check that we're not terminating. 166 // Check that we're not terminating.
106 R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); 167 R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested);
107 168
108 if (manager) { 169 // Get whether we're empty.
109 // HLE request. 170 const bool was_empty = m_request_list.empty();
110 auto& memory{kernel.System().Memory()};
111 this->QueueSyncRequest(GetCurrentThreadPointer(kernel), memory);
112 } else {
113 // Non-HLE request.
114
115 // Get whether we're empty.
116 const bool was_empty = m_request_list.empty();
117 171
118 // Add the request to the list. 172 // Add the request to the list.
119 request->Open(); 173 request->Open();
120 m_request_list.push_back(*request); 174 m_request_list.push_back(*request);
121 175
122 // If we were empty, signal. 176 // If we were empty, signal.
123 if (was_empty) { 177 if (was_empty) {
124 this->NotifyAvailable(); 178 this->NotifyAvailable();
125 }
126 } 179 }
127 180
128 // If we have a request event, this is asynchronous, and we don't need to wait. 181 // If we have a request event, this is asynchronous, and we don't need to wait.
@@ -136,7 +189,7 @@ Result KServerSession::OnRequest(KSessionRequest* request) {
136 return GetCurrentThread(kernel).GetWaitResult(); 189 return GetCurrentThread(kernel).GetWaitResult();
137} 190}
138 191
139Result KServerSession::SendReply() { 192Result KServerSession::SendReply(bool is_hle) {
140 // Lock the session. 193 // Lock the session.
141 KScopedLightLock lk{m_lock}; 194 KScopedLightLock lk{m_lock};
142 195
@@ -171,13 +224,18 @@ Result KServerSession::SendReply() {
171 Result result = ResultSuccess; 224 Result result = ResultSuccess;
172 if (!closed) { 225 if (!closed) {
173 // If we're not closed, send the reply. 226 // If we're not closed, send the reply.
174 Core::Memory::Memory& memory{kernel.System().Memory()}; 227 if (is_hle) {
175 KThread* server_thread{GetCurrentThreadPointer(kernel)}; 228 // HLE servers write directly to a pointer to the thread command buffer. Therefore
176 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); 229 // the reply has already been written in this case.
230 } else {
231 Core::Memory::Memory& memory{kernel.System().Memory()};
232 KThread* server_thread{GetCurrentThreadPointer(kernel)};
233 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
177 234
178 auto* src_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); 235 auto* src_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress());
179 auto* dst_msg_buffer = memory.GetPointer(client_message); 236 auto* dst_msg_buffer = memory.GetPointer(client_message);
180 std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size); 237 std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
238 }
181 } else { 239 } else {
182 result = ResultSessionClosed; 240 result = ResultSessionClosed;
183 } 241 }
@@ -223,7 +281,8 @@ Result KServerSession::SendReply() {
223 return result; 281 return result;
224} 282}
225 283
226Result KServerSession::ReceiveRequest() { 284Result KServerSession::ReceiveRequest(std::shared_ptr<HLERequestContext>* out_context,
285 std::weak_ptr<SessionRequestManager> manager) {
227 // Lock the session. 286 // Lock the session.
228 KScopedLightLock lk{m_lock}; 287 KScopedLightLock lk{m_lock};
229 288
@@ -267,12 +326,22 @@ Result KServerSession::ReceiveRequest() {
267 326
268 // Receive the message. 327 // Receive the message.
269 Core::Memory::Memory& memory{kernel.System().Memory()}; 328 Core::Memory::Memory& memory{kernel.System().Memory()};
270 KThread* server_thread{GetCurrentThreadPointer(kernel)}; 329 if (out_context != nullptr) {
271 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); 330 // HLE request.
331 u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(client_message))};
332 *out_context = std::make_shared<HLERequestContext>(kernel, memory, this, client_thread);
333 (*out_context)->SetSessionRequestManager(manager);
334 (*out_context)
335 ->PopulateFromIncomingCommandBuffer(client_thread->GetOwnerProcess()->GetHandleTable(),
336 cmd_buf);
337 } else {
338 KThread* server_thread{GetCurrentThreadPointer(kernel)};
339 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
272 340
273 auto* src_msg_buffer = memory.GetPointer(client_message); 341 auto* src_msg_buffer = memory.GetPointer(client_message);
274 auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); 342 auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress());
275 std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size); 343 std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
344 }
276 345
277 // We succeeded. 346 // We succeeded.
278 return ResultSuccess; 347 return ResultSuccess;
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index 188aef4af..e4698d3f5 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
@@ -16,21 +16,11 @@
16#include "core/hle/kernel/k_synchronization_object.h" 16#include "core/hle/kernel/k_synchronization_object.h"
17#include "core/hle/result.h" 17#include "core/hle/result.h"
18 18
19namespace Core::Memory {
20class Memory;
21}
22
23namespace Core::Timing {
24class CoreTiming;
25struct EventType;
26} // namespace Core::Timing
27
28namespace Kernel { 19namespace Kernel {
29 20
30class HLERequestContext; 21class HLERequestContext;
31class KernelCore; 22class KernelCore;
32class KSession; 23class KSession;
33class SessionRequestHandler;
34class SessionRequestManager; 24class SessionRequestManager;
35class KThread; 25class KThread;
36 26
@@ -46,8 +36,7 @@ public:
46 36
47 void Destroy() override; 37 void Destroy() override;
48 38
49 void Initialize(KSession* parent_session_, std::string&& name_, 39 void Initialize(KSession* parent_session_, std::string&& name_);
50 std::shared_ptr<SessionRequestManager> manager_);
51 40
52 KSession* GetParent() { 41 KSession* GetParent() {
53 return parent; 42 return parent;
@@ -60,32 +49,16 @@ public:
60 bool IsSignaled() const override; 49 bool IsSignaled() const override;
61 void OnClientClosed(); 50 void OnClientClosed();
62 51
63 /// Gets the session request manager, which forwards requests to the underlying service
64 std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() {
65 return manager;
66 }
67
68 /// TODO: flesh these out to match the real kernel 52 /// TODO: flesh these out to match the real kernel
69 Result OnRequest(KSessionRequest* request); 53 Result OnRequest(KSessionRequest* request);
70 Result SendReply(); 54 Result SendReply(bool is_hle = false);
71 Result ReceiveRequest(); 55 Result ReceiveRequest(std::shared_ptr<HLERequestContext>* out_context = nullptr,
56 std::weak_ptr<SessionRequestManager> manager = {});
72 57
73private: 58private:
74 /// Frees up waiting client sessions when this server session is about to die 59 /// Frees up waiting client sessions when this server session is about to die
75 void CleanupRequests(); 60 void CleanupRequests();
76 61
77 /// Queues a sync request from the emulated application.
78 Result QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory);
79
80 /// Completes a sync request from the emulated application.
81 Result CompleteSyncRequest(HLERequestContext& context);
82
83 /// This session's HLE request handlers; if nullptr, this is not an HLE server
84 std::shared_ptr<SessionRequestManager> manager;
85
86 /// When set to True, converts the session to a domain at the end of the command
87 bool convert_to_domain{};
88
89 /// KSession that owns this KServerSession 62 /// KSession that owns this KServerSession
90 KSession* parent{}; 63 KSession* parent{};
91 64
diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp
index ee05aa282..7a6534ac3 100644
--- a/src/core/hle/kernel/k_session.cpp
+++ b/src/core/hle/kernel/k_session.cpp
@@ -13,8 +13,7 @@ KSession::KSession(KernelCore& kernel_)
13 : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {} 13 : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {}
14KSession::~KSession() = default; 14KSession::~KSession() = default;
15 15
16void KSession::Initialize(KClientPort* port_, const std::string& name_, 16void KSession::Initialize(KClientPort* port_, const std::string& name_) {
17 std::shared_ptr<SessionRequestManager> manager_) {
18 // Increment reference count. 17 // Increment reference count.
19 // Because reference count is one on creation, this will result 18 // Because reference count is one on creation, this will result
20 // in a reference count of two. Thus, when both server and client are closed 19 // in a reference count of two. Thus, when both server and client are closed
@@ -26,7 +25,7 @@ void KSession::Initialize(KClientPort* port_, const std::string& name_,
26 KAutoObject::Create(std::addressof(client)); 25 KAutoObject::Create(std::addressof(client));
27 26
28 // Initialize our sub sessions. 27 // Initialize our sub sessions.
29 server.Initialize(this, name_ + ":Server", manager_); 28 server.Initialize(this, name_ + ":Server");
30 client.Initialize(this, name_ + ":Client"); 29 client.Initialize(this, name_ + ":Client");
31 30
32 // Set state and name. 31 // Set state and name.
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h
index c6ead403b..93e5e6f71 100644
--- a/src/core/hle/kernel/k_session.h
+++ b/src/core/hle/kernel/k_session.h
@@ -21,8 +21,7 @@ public:
21 explicit KSession(KernelCore& kernel_); 21 explicit KSession(KernelCore& kernel_);
22 ~KSession() override; 22 ~KSession() override;
23 23
24 void Initialize(KClientPort* port_, const std::string& name_, 24 void Initialize(KClientPort* port_, const std::string& name_);
25 std::shared_ptr<SessionRequestManager> manager_ = nullptr);
26 25
27 void Finalize() override; 26 void Finalize() override;
28 27
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index fdc774e30..29e122dfd 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -60,7 +60,6 @@ struct KernelCore::Impl {
60 global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); 60 global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
61 global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); 61 global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
62 global_handle_table->Initialize(KHandleTable::MaxTableSize); 62 global_handle_table->Initialize(KHandleTable::MaxTableSize);
63 default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread");
64 63
65 is_phantom_mode_for_singlecore = false; 64 is_phantom_mode_for_singlecore = false;
66 65
@@ -86,6 +85,8 @@ struct KernelCore::Impl {
86 } 85 }
87 86
88 RegisterHostThread(); 87 RegisterHostThread();
88
89 default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread");
89 } 90 }
90 91
91 void InitializeCores() { 92 void InitializeCores() {
@@ -703,6 +704,15 @@ struct KernelCore::Impl {
703 return port; 704 return port;
704 } 705 }
705 706
707 void RegisterNamedServiceHandler(std::string name, KServerPort* server_port) {
708 auto search = service_interface_handlers.find(name);
709 if (search == service_interface_handlers.end()) {
710 return;
711 }
712
713 search->second(system.ServiceManager(), server_port);
714 }
715
706 void RegisterServerObject(KAutoObject* server_object) { 716 void RegisterServerObject(KAutoObject* server_object) {
707 std::scoped_lock lk(server_objects_lock); 717 std::scoped_lock lk(server_objects_lock);
708 server_objects.insert(server_object); 718 server_objects.insert(server_object);
@@ -715,7 +725,7 @@ struct KernelCore::Impl {
715 725
716 std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel, 726 std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel,
717 const std::string& name) { 727 const std::string& name) {
718 auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, 1, name); 728 auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, name);
719 729
720 service_threads_manager.QueueWork( 730 service_threads_manager.QueueWork(
721 [this, service_thread]() { service_threads.emplace(service_thread); }); 731 [this, service_thread]() { service_threads.emplace(service_thread); });
@@ -774,6 +784,7 @@ struct KernelCore::Impl {
774 /// Map of named ports managed by the kernel, which can be retrieved using 784 /// Map of named ports managed by the kernel, which can be retrieved using
775 /// the ConnectToPort SVC. 785 /// the ConnectToPort SVC.
776 std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; 786 std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
787 std::unordered_map<std::string, ServiceInterfaceHandlerFn> service_interface_handlers;
777 NamedPortTable named_ports; 788 NamedPortTable named_ports;
778 std::unordered_set<KAutoObject*> server_objects; 789 std::unordered_set<KAutoObject*> server_objects;
779 std::unordered_set<KAutoObject*> registered_objects; 790 std::unordered_set<KAutoObject*> registered_objects;
@@ -981,10 +992,19 @@ void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&
981 impl->service_interface_factory.emplace(std::move(name), factory); 992 impl->service_interface_factory.emplace(std::move(name), factory);
982} 993}
983 994
995void KernelCore::RegisterInterfaceForNamedService(std::string name,
996 ServiceInterfaceHandlerFn&& handler) {
997 impl->service_interface_handlers.emplace(std::move(name), handler);
998}
999
984KClientPort* KernelCore::CreateNamedServicePort(std::string name) { 1000KClientPort* KernelCore::CreateNamedServicePort(std::string name) {
985 return impl->CreateNamedServicePort(std::move(name)); 1001 return impl->CreateNamedServicePort(std::move(name));
986} 1002}
987 1003
1004void KernelCore::RegisterNamedServiceHandler(std::string name, KServerPort* server_port) {
1005 impl->RegisterNamedServiceHandler(std::move(name), server_port);
1006}
1007
988void KernelCore::RegisterServerObject(KAutoObject* server_object) { 1008void KernelCore::RegisterServerObject(KAutoObject* server_object) {
989 impl->RegisterServerObject(server_object); 1009 impl->RegisterServerObject(server_object);
990} 1010}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 266be2bc4..670f93ee3 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -45,6 +45,7 @@ class KPort;
45class KProcess; 45class KProcess;
46class KResourceLimit; 46class KResourceLimit;
47class KScheduler; 47class KScheduler;
48class KServerPort;
48class KServerSession; 49class KServerSession;
49class KSession; 50class KSession;
50class KSessionRequest; 51class KSessionRequest;
@@ -63,6 +64,8 @@ class TimeManager;
63using ServiceInterfaceFactory = 64using ServiceInterfaceFactory =
64 std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>; 65 std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>;
65 66
67using ServiceInterfaceHandlerFn = std::function<void(Service::SM::ServiceManager&, KServerPort*)>;
68
66namespace Init { 69namespace Init {
67struct KSlabResourceCounts; 70struct KSlabResourceCounts;
68} 71}
@@ -192,9 +195,15 @@ public:
192 /// Registers a named HLE service, passing a factory used to open a port to that service. 195 /// Registers a named HLE service, passing a factory used to open a port to that service.
193 void RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory); 196 void RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory);
194 197
198 /// Registers a setup function for the named HLE service.
199 void RegisterInterfaceForNamedService(std::string name, ServiceInterfaceHandlerFn&& handler);
200
195 /// Opens a port to a service previously registered with RegisterNamedService. 201 /// Opens a port to a service previously registered with RegisterNamedService.
196 KClientPort* CreateNamedServicePort(std::string name); 202 KClientPort* CreateNamedServicePort(std::string name);
197 203
204 /// Accepts a session on a port created by CreateNamedServicePort.
205 void RegisterNamedServiceHandler(std::string name, KServerPort* server_port);
206
198 /// Registers a server session or port with the gobal emulation state, to be freed on shutdown. 207 /// Registers a server session or port with the gobal emulation state, to be freed on shutdown.
199 /// This is necessary because we do not emulate processes for HLE sessions and ports. 208 /// This is necessary because we do not emulate processes for HLE sessions and ports.
200 void RegisterServerObject(KAutoObject* server_object); 209 void RegisterServerObject(KAutoObject* server_object);
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp
index d23d76706..1fc2edf52 100644
--- a/src/core/hle/kernel/service_thread.cpp
+++ b/src/core/hle/kernel/service_thread.cpp
@@ -1,15 +1,17 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <condition_variable>
5#include <functional> 4#include <functional>
6#include <mutex> 5#include <mutex>
7#include <thread> 6#include <thread>
8#include <vector> 7#include <vector>
9#include <queue>
10 8
11#include "common/scope_exit.h" 9#include "common/scope_exit.h"
12#include "common/thread.h" 10#include "common/thread.h"
11#include "core/hle/ipc_helpers.h"
12#include "core/hle/kernel/hle_ipc.h"
13#include "core/hle/kernel/k_event.h"
14#include "core/hle/kernel/k_scoped_resource_reservation.h"
13#include "core/hle/kernel/k_session.h" 15#include "core/hle/kernel/k_session.h"
14#include "core/hle/kernel/k_thread.h" 16#include "core/hle/kernel/k_thread.h"
15#include "core/hle/kernel/kernel.h" 17#include "core/hle/kernel/kernel.h"
@@ -19,101 +21,201 @@ namespace Kernel {
19 21
20class ServiceThread::Impl final { 22class ServiceThread::Impl final {
21public: 23public:
22 explicit Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name); 24 explicit Impl(KernelCore& kernel, const std::string& service_name);
23 ~Impl(); 25 ~Impl();
24 26
25 void QueueSyncRequest(KSession& session, std::shared_ptr<HLERequestContext>&& context); 27 void WaitAndProcessImpl();
28 void SessionClosed(KServerSession* server_session,
29 std::shared_ptr<SessionRequestManager> manager);
30 void LoopProcess();
31
32 void RegisterServerSession(KServerSession* session,
33 std::shared_ptr<SessionRequestManager> manager);
26 34
27private: 35private:
28 std::vector<std::jthread> threads; 36 KernelCore& kernel;
29 std::queue<std::function<void()>> requests; 37
30 std::mutex queue_mutex; 38 std::jthread m_thread;
31 std::condition_variable_any condition; 39 std::mutex m_session_mutex;
32 const std::string service_name; 40 std::vector<KServerSession*> m_sessions;
41 std::vector<std::shared_ptr<SessionRequestManager>> m_managers;
42 KEvent* m_wakeup_event;
43 KProcess* m_process;
44 std::atomic<bool> m_shutdown_requested;
45 const std::string m_service_name;
33}; 46};
34 47
35ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name) 48void ServiceThread::Impl::WaitAndProcessImpl() {
36 : service_name{name} { 49 // Create local list of waitable sessions.
37 for (std::size_t i = 0; i < num_threads; ++i) { 50 std::vector<KSynchronizationObject*> objs;
38 threads.emplace_back([this, &kernel](std::stop_token stop_token) { 51 std::vector<std::shared_ptr<SessionRequestManager>> managers;
39 Common::SetCurrentThreadName(std::string{service_name}.c_str());
40 52
41 // Wait for first request before trying to acquire a render context 53 {
42 { 54 // Lock to get the list.
43 std::unique_lock lock{queue_mutex}; 55 std::scoped_lock lk{m_session_mutex};
44 condition.wait(lock, stop_token, [this] { return !requests.empty(); });
45 }
46 56
47 if (stop_token.stop_requested()) { 57 // Resize to the needed quantity.
48 return; 58 objs.resize(m_sessions.size() + 1);
49 } 59 managers.resize(m_managers.size());
50 60
51 // Allocate a dummy guest thread for this host thread. 61 // Copy to our local list.
52 kernel.RegisterHostThread(); 62 std::copy(m_sessions.begin(), m_sessions.end(), objs.begin());
63 std::copy(m_managers.begin(), m_managers.end(), managers.begin());
53 64
54 while (true) { 65 // Insert the wakeup event at the end.
55 std::function<void()> task; 66 objs.back() = &m_wakeup_event->GetReadableEvent();
67 }
56 68
57 { 69 // Wait on the list of sessions.
58 std::unique_lock lock{queue_mutex}; 70 s32 index{-1};
59 condition.wait(lock, stop_token, [this] { return !requests.empty(); }); 71 Result rc = KSynchronizationObject::Wait(kernel, &index, objs.data(),
72 static_cast<s32>(objs.size()), -1);
73 ASSERT(!rc.IsFailure());
74
75 // If this was the wakeup event, clear it and finish.
76 if (index >= static_cast<s64>(objs.size() - 1)) {
77 m_wakeup_event->Clear();
78 return;
79 }
60 80
61 if (stop_token.stop_requested()) { 81 // This event is from a server session.
62 return; 82 auto* server_session = static_cast<KServerSession*>(objs[index]);
63 } 83 auto& manager = managers[index];
64 84
65 if (requests.empty()) { 85 // Fetch the HLE request context.
66 continue; 86 std::shared_ptr<HLERequestContext> context;
67 } 87 rc = server_session->ReceiveRequest(&context, manager);
68 88
69 task = std::move(requests.front()); 89 // If the session was closed, handle that.
70 requests.pop(); 90 if (rc == ResultSessionClosed) {
71 } 91 SessionClosed(server_session, manager);
72 92
73 task(); 93 // Finish.
74 } 94 return;
75 });
76 } 95 }
96
97 // TODO: handle other cases
98 ASSERT(rc == ResultSuccess);
99
100 // Perform the request.
101 Result service_rc = manager->CompleteSyncRequest(server_session, *context);
102
103 // Reply to the client.
104 rc = server_session->SendReply(true);
105
106 if (rc == ResultSessionClosed || service_rc == IPC::ERR_REMOTE_PROCESS_DEAD) {
107 SessionClosed(server_session, manager);
108 return;
109 }
110
111 // TODO: handle other cases
112 ASSERT(rc == ResultSuccess);
113 ASSERT(service_rc == ResultSuccess);
77} 114}
78 115
79void ServiceThread::Impl::QueueSyncRequest(KSession& session, 116void ServiceThread::Impl::SessionClosed(KServerSession* server_session,
80 std::shared_ptr<HLERequestContext>&& context) { 117 std::shared_ptr<SessionRequestManager> manager) {
81 { 118 {
82 std::unique_lock lock{queue_mutex}; 119 // Lock to get the list.
120 std::scoped_lock lk{m_session_mutex};
121
122 // Get the index of the session.
123 const auto index =
124 std::find(m_sessions.begin(), m_sessions.end(), server_session) - m_sessions.begin();
125 ASSERT(index < static_cast<s64>(m_sessions.size()));
126
127 // Remove the session and its manager.
128 m_sessions.erase(m_sessions.begin() + index);
129 m_managers.erase(m_managers.begin() + index);
130 }
83 131
84 auto* server_session{&session.GetServerSession()}; 132 // Close our reference to the server session.
133 server_session->Close();
134}
85 135
86 // Open a reference to the session to ensure it is not closes while the service request 136void ServiceThread::Impl::LoopProcess() {
87 // completes asynchronously. 137 Common::SetCurrentThreadName(m_service_name.c_str());
88 server_session->Open();
89 138
90 requests.emplace([server_session, context{std::move(context)}]() { 139 kernel.RegisterHostThread();
91 // Close the reference.
92 SCOPE_EXIT({ server_session->Close(); });
93 140
94 // Complete the service request. 141 while (!m_shutdown_requested.load()) {
95 server_session->CompleteSyncRequest(*context); 142 WaitAndProcessImpl();
96 });
97 } 143 }
98 condition.notify_one(); 144}
145
146void ServiceThread::Impl::RegisterServerSession(KServerSession* server_session,
147 std::shared_ptr<SessionRequestManager> manager) {
148 // Open the server session.
149 server_session->Open();
150
151 {
152 // Lock to get the list.
153 std::scoped_lock lk{m_session_mutex};
154
155 // Insert the session and manager.
156 m_sessions.push_back(server_session);
157 m_managers.push_back(manager);
158 }
159
160 // Signal the wakeup event.
161 m_wakeup_event->Signal();
99} 162}
100 163
101ServiceThread::Impl::~Impl() { 164ServiceThread::Impl::~Impl() {
102 condition.notify_all(); 165 // Shut down the processing thread.
103 for (auto& thread : threads) { 166 m_shutdown_requested.store(true);
104 thread.request_stop(); 167 m_wakeup_event->Signal();
105 thread.join(); 168 m_thread.join();
169
170 // Lock mutex.
171 m_session_mutex.lock();
172
173 // Close all remaining sessions.
174 for (size_t i = 0; i < m_sessions.size(); i++) {
175 m_sessions[i]->Close();
106 } 176 }
177
178 // Close event.
179 m_wakeup_event->GetReadableEvent().Close();
180 m_wakeup_event->Close();
181
182 // Close process.
183 m_process->Close();
184}
185
186ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name)
187 : kernel{kernel_}, m_service_name{service_name} {
188 // Initialize process.
189 m_process = KProcess::Create(kernel);
190 KProcess::Initialize(m_process, kernel.System(), service_name,
191 KProcess::ProcessType::KernelInternal, kernel.GetSystemResourceLimit());
192
193 // Reserve a new event from the process resource limit
194 KScopedResourceReservation event_reservation(m_process, LimitableResource::Events);
195 ASSERT(event_reservation.Succeeded());
196
197 // Initialize event.
198 m_wakeup_event = KEvent::Create(kernel);
199 m_wakeup_event->Initialize(m_process);
200
201 // Commit the event reservation.
202 event_reservation.Commit();
203
204 // Register the event.
205 KEvent::Register(kernel, m_wakeup_event);
206
207 // Start thread.
208 m_thread = std::jthread([this] { LoopProcess(); });
107} 209}
108 210
109ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name) 211ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name)
110 : impl{std::make_unique<Impl>(kernel, num_threads, name)} {} 212 : impl{std::make_unique<Impl>(kernel, name)} {}
111 213
112ServiceThread::~ServiceThread() = default; 214ServiceThread::~ServiceThread() = default;
113 215
114void ServiceThread::QueueSyncRequest(KSession& session, 216void ServiceThread::RegisterServerSession(KServerSession* session,
115 std::shared_ptr<HLERequestContext>&& context) { 217 std::shared_ptr<SessionRequestManager> manager) {
116 impl->QueueSyncRequest(session, std::move(context)); 218 impl->RegisterServerSession(session, manager);
117} 219}
118 220
119} // namespace Kernel 221} // namespace Kernel
diff --git a/src/core/hle/kernel/service_thread.h b/src/core/hle/kernel/service_thread.h
index c5896f2bd..fb4325531 100644
--- a/src/core/hle/kernel/service_thread.h
+++ b/src/core/hle/kernel/service_thread.h
@@ -11,13 +11,15 @@ namespace Kernel {
11class HLERequestContext; 11class HLERequestContext;
12class KernelCore; 12class KernelCore;
13class KSession; 13class KSession;
14class SessionRequestManager;
14 15
15class ServiceThread final { 16class ServiceThread final {
16public: 17public:
17 explicit ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name); 18 explicit ServiceThread(KernelCore& kernel, const std::string& name);
18 ~ServiceThread(); 19 ~ServiceThread();
19 20
20 void QueueSyncRequest(KSession& session, std::shared_ptr<HLERequestContext>&& context); 21 void RegisterServerSession(KServerSession* session,
22 std::shared_ptr<SessionRequestManager> manager);
21 23
22private: 24private:
23 class Impl; 25 class Impl;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 4aca5b27d..8d2c7d6b7 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -24,6 +24,7 @@
24#include "core/hle/kernel/k_memory_block.h" 24#include "core/hle/kernel/k_memory_block.h"
25#include "core/hle/kernel/k_memory_layout.h" 25#include "core/hle/kernel/k_memory_layout.h"
26#include "core/hle/kernel/k_page_table.h" 26#include "core/hle/kernel/k_page_table.h"
27#include "core/hle/kernel/k_port.h"
27#include "core/hle/kernel/k_process.h" 28#include "core/hle/kernel/k_process.h"
28#include "core/hle/kernel/k_readable_event.h" 29#include "core/hle/kernel/k_readable_event.h"
29#include "core/hle/kernel/k_resource_limit.h" 30#include "core/hle/kernel/k_resource_limit.h"
@@ -382,10 +383,11 @@ static Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_n
382 383
383 // Create a session. 384 // Create a session.
384 KClientSession* session{}; 385 KClientSession* session{};
385 R_TRY(port->CreateSession(std::addressof(session), 386 R_TRY(port->CreateSession(std::addressof(session)));
386 std::make_shared<SessionRequestManager>(kernel)));
387 port->Close(); 387 port->Close();
388 388
389 kernel.RegisterNamedServiceHandler(port_name, &port->GetParent()->GetServerPort());
390
389 // Register the session in the table, close the extra reference. 391 // Register the session in the table, close the extra reference.
390 handle_table.Register(*out, session); 392 handle_table.Register(*out, session);
391 session->Close(); 393 session->Close();
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 5db6588e4..0913a8065 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -99,6 +99,10 @@ ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* se
99ServiceFrameworkBase::~ServiceFrameworkBase() { 99ServiceFrameworkBase::~ServiceFrameworkBase() {
100 // Wait for other threads to release access before destroying 100 // Wait for other threads to release access before destroying
101 const auto guard = LockService(); 101 const auto guard = LockService();
102
103 if (named_port != nullptr) {
104 named_port->Close();
105 }
102} 106}
103 107
104void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) { 108void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) {
@@ -115,13 +119,12 @@ Kernel::KClientPort& ServiceFrameworkBase::CreatePort() {
115 119
116 ASSERT(!service_registered); 120 ASSERT(!service_registered);
117 121
118 auto* port = Kernel::KPort::Create(kernel); 122 named_port = Kernel::KPort::Create(kernel);
119 port->Initialize(max_sessions, false, service_name); 123 named_port->Initialize(max_sessions, false, service_name);
120 port->GetServerPort().SetSessionHandler(shared_from_this());
121 124
122 service_registered = true; 125 service_registered = true;
123 126
124 return port->GetClientPort(); 127 return named_port->GetClientPort();
125} 128}
126 129
127void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { 130void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) {
@@ -199,7 +202,6 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,
199 switch (ctx.GetCommandType()) { 202 switch (ctx.GetCommandType()) {
200 case IPC::CommandType::Close: 203 case IPC::CommandType::Close:
201 case IPC::CommandType::TIPC_Close: { 204 case IPC::CommandType::TIPC_Close: {
202 session.Close();
203 IPC::ResponseBuilder rb{ctx, 2}; 205 IPC::ResponseBuilder rb{ctx, 2};
204 rb.Push(ResultSuccess); 206 rb.Push(ResultSuccess);
205 result = IPC::ERR_REMOTE_PROCESS_DEAD; 207 result = IPC::ERR_REMOTE_PROCESS_DEAD;
@@ -244,6 +246,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
244 system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); 246 system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
245 247
246 system.Kernel().RegisterNamedService("sm:", SM::ServiceManager::InterfaceFactory); 248 system.Kernel().RegisterNamedService("sm:", SM::ServiceManager::InterfaceFactory);
249 system.Kernel().RegisterInterfaceForNamedService("sm:", SM::ServiceManager::SessionHandler);
247 250
248 Account::InstallInterfaces(system); 251 Account::InstallInterfaces(system);
249 AM::InstallInterfaces(*sm, *nv_flinger, system); 252 AM::InstallInterfaces(*sm, *nv_flinger, system);
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index ec9deeee4..22e2119d7 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -20,6 +20,7 @@ class System;
20namespace Kernel { 20namespace Kernel {
21class HLERequestContext; 21class HLERequestContext;
22class KClientPort; 22class KClientPort;
23class KPort;
23class KServerSession; 24class KServerSession;
24class ServiceThread; 25class ServiceThread;
25} // namespace Kernel 26} // namespace Kernel
@@ -98,6 +99,9 @@ protected:
98 /// Identifier string used to connect to the service. 99 /// Identifier string used to connect to the service.
99 std::string service_name; 100 std::string service_name;
100 101
102 /// Port used by ManageNamedPort.
103 Kernel::KPort* named_port{};
104
101private: 105private:
102 template <typename T> 106 template <typename T>
103 friend class ServiceFramework; 107 friend class ServiceFramework;
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index cb6c0e96f..c1f535d71 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -43,6 +43,10 @@ Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core
43 return self.sm_interface->CreatePort(); 43 return self.sm_interface->CreatePort();
44} 44}
45 45
46void ServiceManager::SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port) {
47 self.sm_interface->AcceptSession(server_port);
48}
49
46Result ServiceManager::RegisterService(std::string name, u32 max_sessions, 50Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
47 Kernel::SessionRequestHandlerPtr handler) { 51 Kernel::SessionRequestHandlerPtr handler) {
48 52
@@ -83,7 +87,6 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name
83 87
84 port->Initialize(ServerSessionCountMax, false, name); 88 port->Initialize(ServerSessionCountMax, false, name);
85 auto handler = it->second; 89 auto handler = it->second;
86 port->GetServerPort().SetSessionHandler(std::move(handler));
87 90
88 return port; 91 return port;
89} 92}
@@ -144,7 +147,8 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
144 147
145 // Find the named port. 148 // Find the named port.
146 auto port_result = service_manager.GetServicePort(name); 149 auto port_result = service_manager.GetServicePort(name);
147 if (port_result.Failed()) { 150 auto service = service_manager.GetService<Kernel::SessionRequestHandler>(name);
151 if (port_result.Failed() || !service) {
148 LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw); 152 LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw);
149 return port_result.Code(); 153 return port_result.Code();
150 } 154 }
@@ -156,12 +160,11 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
156 160
157 // Create a new session. 161 // Create a new session.
158 Kernel::KClientSession* session{}; 162 Kernel::KClientSession* session{};
159 if (const auto result = port->GetClientPort().CreateSession( 163 if (const auto result = port->GetClientPort().CreateSession(&session); result.IsError()) {
160 std::addressof(session), std::make_shared<Kernel::SessionRequestManager>(kernel));
161 result.IsError()) {
162 LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); 164 LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw);
163 return result; 165 return result;
164 } 166 }
167 service->AcceptSession(&port->GetServerPort());
165 168
166 LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); 169 LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
167 170
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index 878decc6f..cfe370652 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -51,6 +51,7 @@ private:
51class ServiceManager { 51class ServiceManager {
52public: 52public:
53 static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system); 53 static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system);
54 static void SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port);
54 55
55 explicit ServiceManager(Kernel::KernelCore& kernel_); 56 explicit ServiceManager(Kernel::KernelCore& kernel_);
56 ~ServiceManager(); 57 ~ServiceManager();
diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp
index 46a8439d8..940c33478 100644
--- a/src/core/hle/service/sm/sm_controller.cpp
+++ b/src/core/hle/service/sm/sm_controller.cpp
@@ -15,10 +15,9 @@
15namespace Service::SM { 15namespace Service::SM {
16 16
17void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { 17void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
18 ASSERT_MSG(!ctx.Session()->GetSessionRequestManager()->IsDomain(), 18 ASSERT_MSG(!ctx.GetManager()->IsDomain(), "Session is already a domain");
19 "Session is already a domain");
20 LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId()); 19 LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId());
21 ctx.Session()->GetSessionRequestManager()->ConvertToDomainOnRequestEnd(); 20 ctx.GetManager()->ConvertToDomainOnRequestEnd();
22 21
23 IPC::ResponseBuilder rb{ctx, 3}; 22 IPC::ResponseBuilder rb{ctx, 3};
24 rb.Push(ResultSuccess); 23 rb.Push(ResultSuccess);
@@ -29,30 +28,32 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
29 LOG_DEBUG(Service, "called"); 28 LOG_DEBUG(Service, "called");
30 29
31 auto& process = *ctx.GetThread().GetOwnerProcess(); 30 auto& process = *ctx.GetThread().GetOwnerProcess();
32 auto& parent_session = *ctx.Session()->GetParent(); 31 auto session_manager = ctx.GetManager();
33 auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager();
34 auto& session_handler = session_manager->SessionHandler();
35 32
36 // FIXME: this is duplicated from the SVC, it should just call it instead 33 // FIXME: this is duplicated from the SVC, it should just call it instead
37 // once this is a proper process 34 // once this is a proper process
38 35
36 // Declare the session we're going to allocate.
37 Kernel::KSession* session;
38
39 // Reserve a new session from the process resource limit. 39 // Reserve a new session from the process resource limit.
40 Kernel::KScopedResourceReservation session_reservation(&process, 40 Kernel::KScopedResourceReservation session_reservation(&process,
41 Kernel::LimitableResource::Sessions); 41 Kernel::LimitableResource::Sessions);
42 ASSERT(session_reservation.Succeeded()); 42 ASSERT(session_reservation.Succeeded());
43 43
44 // Create the session. 44 // Create the session.
45 Kernel::KSession* session = Kernel::KSession::Create(system.Kernel()); 45 session = Kernel::KSession::Create(system.Kernel());
46 ASSERT(session != nullptr); 46 ASSERT(session != nullptr);
47 47
48 // Initialize the session. 48 // Initialize the session.
49 session->Initialize(nullptr, parent_session.GetName(), session_manager); 49 session->Initialize(nullptr, "");
50 50
51 // Commit the session reservation. 51 // Commit the session reservation.
52 session_reservation.Commit(); 52 session_reservation.Commit();
53 53
54 // Register the session. 54 // Register with manager.
55 session_handler.ClientConnected(&session->GetServerSession()); 55 session_manager->SessionHandler().RegisterSession(&session->GetServerSession(),
56 session_manager);
56 57
57 // We succeeded. 58 // We succeeded.
58 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; 59 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};