summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/ipc_helpers.h4
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp10
-rw-r--r--src/core/hle/kernel/hle_ipc.h10
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp4
-rw-r--r--src/core/hle/kernel/k_client_port.cpp119
-rw-r--r--src/core/hle/kernel/k_client_port.h46
-rw-r--r--src/core/hle/kernel/k_event.h2
-rw-r--r--src/core/hle/kernel/k_port.cpp68
-rw-r--r--src/core/hle/kernel/k_port.h87
-rw-r--r--src/core/hle/kernel/k_server_port.cpp94
-rw-r--r--src/core/hle/kernel/k_server_port.h55
-rw-r--r--src/core/hle/kernel/k_server_session.cpp2
-rw-r--r--src/core/hle/kernel/k_server_session.h5
-rw-r--r--src/core/hle/kernel/k_session.cpp18
-rw-r--r--src/core/hle/kernel/k_session.h2
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/svc.cpp22
-rw-r--r--src/core/hle/kernel/svc_results.h1
-rw-r--r--src/core/hle/service/service.cpp9
-rw-r--r--src/core/hle/service/sm/sm.cpp31
-rw-r--r--src/core/hle/service/sm/sm.h13
22 files changed, 444 insertions, 166 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 487e6f720..cee6d30f6 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -194,6 +194,8 @@ add_library(core STATIC
194 hle/kernel/k_page_linked_list.h 194 hle/kernel/k_page_linked_list.h
195 hle/kernel/k_page_table.cpp 195 hle/kernel/k_page_table.cpp
196 hle/kernel/k_page_table.h 196 hle/kernel/k_page_table.h
197 hle/kernel/k_port.cpp
198 hle/kernel/k_port.h
197 hle/kernel/k_priority_queue.h 199 hle/kernel/k_priority_queue.h
198 hle/kernel/k_readable_event.cpp 200 hle/kernel/k_readable_event.cpp
199 hle/kernel/k_readable_event.h 201 hle/kernel/k_readable_event.h
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 18aebf6ea..8128445fd 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -136,10 +136,10 @@ public:
136 context->AddDomainObject(std::move(iface)); 136 context->AddDomainObject(std::move(iface));
137 } else { 137 } else {
138 auto* session = Kernel::KSession::Create(kernel); 138 auto* session = Kernel::KSession::Create(kernel);
139 session->Initialize(iface->GetServiceName()); 139 session->Initialize(nullptr, iface->GetServiceName());
140 140
141 context->AddMoveObject(&session->GetClientSession()); 141 context->AddMoveObject(&session->GetClientSession());
142 iface->ClientConnected(session); 142 iface->ClientConnected(&session->GetServerSession());
143 } 143 }
144 } 144 }
145 145
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 9e1e63204..ddff9ce99 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -35,14 +35,12 @@ SessionRequestHandler::SessionRequestHandler() = default;
35 35
36SessionRequestHandler::~SessionRequestHandler() = default; 36SessionRequestHandler::~SessionRequestHandler() = default;
37 37
38void SessionRequestHandler::ClientConnected(KSession* session) { 38void SessionRequestHandler::ClientConnected(KServerSession* session) {
39 session->GetServerSession().SetHleHandler(shared_from_this()); 39 session->SetHleHandler(shared_from_this());
40 sessions.push_back(session);
41} 40}
42 41
43void SessionRequestHandler::ClientDisconnected(KSession* session) { 42void SessionRequestHandler::ClientDisconnected(KServerSession* session) {
44 session->GetServerSession().SetHleHandler(nullptr); 43 session->SetHleHandler(nullptr);
45 boost::range::remove_erase(sessions, session);
46} 44}
47 45
48HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, 46HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_,
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index b7484c445..d63c730ac 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -72,20 +72,14 @@ public:
72 * associated ServerSession alive for the duration of the connection. 72 * associated ServerSession alive for the duration of the connection.
73 * @param server_session Owning pointer to the ServerSession associated with the connection. 73 * @param server_session Owning pointer to the ServerSession associated with the connection.
74 */ 74 */
75 void ClientConnected(KSession* session); 75 void ClientConnected(KServerSession* session);
76 76
77 /** 77 /**
78 * Signals that a client has just disconnected from this HLE handler and releases the 78 * Signals that a client has just disconnected from this HLE handler and releases the
79 * associated ServerSession. 79 * associated ServerSession.
80 * @param server_session ServerSession associated with the connection. 80 * @param server_session ServerSession associated with the connection.
81 */ 81 */
82 void ClientDisconnected(KSession* session); 82 void ClientDisconnected(KServerSession* session);
83
84protected:
85 /// List of sessions that are connected to this handler.
86 /// A ServerSession whose server endpoint is an HLE implementation is kept alive by this list
87 /// for the duration of the connection.
88 std::vector<KSession*> sessions;
89}; 83};
90 84
91/** 85/**
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index a5ddd7344..f8c255732 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -12,6 +12,7 @@
12#include "core/hle/kernel/k_event.h" 12#include "core/hle/kernel/k_event.h"
13#include "core/hle/kernel/k_memory_layout.h" 13#include "core/hle/kernel/k_memory_layout.h"
14#include "core/hle/kernel/k_memory_manager.h" 14#include "core/hle/kernel/k_memory_manager.h"
15#include "core/hle/kernel/k_port.h"
15#include "core/hle/kernel/k_resource_limit.h" 16#include "core/hle/kernel/k_resource_limit.h"
16#include "core/hle/kernel/k_session.h" 17#include "core/hle/kernel/k_session.h"
17#include "core/hle/kernel/k_shared_memory.h" 18#include "core/hle/kernel/k_shared_memory.h"
@@ -30,8 +31,9 @@ namespace Kernel::Init {
30 HANDLER(Process, (SLAB_COUNT(Process)), ##__VA_ARGS__) \ 31 HANDLER(Process, (SLAB_COUNT(Process)), ##__VA_ARGS__) \
31 HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \ 32 HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \
32 HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \ 33 HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \
33 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ 34 HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \
34 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ 35 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \
36 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \
35 HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \ 37 HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \
36 HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) 38 HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__)
37 39
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp
index 00e1bbc59..b6f1d713f 100644
--- a/src/core/hle/kernel/k_client_port.cpp
+++ b/src/core/hle/kernel/k_client_port.cpp
@@ -1,12 +1,14 @@
1// Copyright 2016 Citra Emulator Project 1// Copyright 2021 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/scope_exit.h"
5#include "core/hle/kernel/hle_ipc.h" 6#include "core/hle/kernel/hle_ipc.h"
6#include "core/hle/kernel/k_client_port.h" 7#include "core/hle/kernel/k_client_port.h"
7#include "core/hle/kernel/k_server_port.h" 8#include "core/hle/kernel/k_port.h"
9#include "core/hle/kernel/k_scheduler.h"
10#include "core/hle/kernel/k_scoped_resource_reservation.h"
8#include "core/hle/kernel/k_session.h" 11#include "core/hle/kernel/k_session.h"
9#include "core/hle/kernel/object.h"
10#include "core/hle/kernel/svc_results.h" 12#include "core/hle/kernel/svc_results.h"
11 13
12namespace Kernel { 14namespace Kernel {
@@ -14,45 +16,110 @@ namespace Kernel {
14KClientPort::KClientPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} 16KClientPort::KClientPort(KernelCore& kernel) : KSynchronizationObject{kernel} {}
15KClientPort::~KClientPort() = default; 17KClientPort::~KClientPort() = default;
16 18
17void KClientPort::Initialize(s32 max_sessions_, std::string&& name_) { 19void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_) {
20 // Set member variables.
21 num_sessions = 0;
22 peak_sessions = 0;
23 parent = parent_;
18 max_sessions = max_sessions_; 24 max_sessions = max_sessions_;
19 name = std::move(name_); 25 name = std::move(name_);
20} 26}
21 27
22KServerPort* KClientPort::GetServerPort() const { 28void KClientPort::OnSessionFinalized() {
23 return server_port; 29 KScopedSchedulerLock sl{kernel};
24}
25 30
26ResultVal<KClientSession*> KClientPort::Connect() { 31 const auto prev = num_sessions--;
27 if (num_sessions >= max_sessions) { 32 if (prev == max_sessions) {
28 return ResultOutOfSessions; 33 this->NotifyAvailable();
29 } 34 }
30 num_sessions++; 35}
31 36
32 auto* session = Kernel::KSession::Create(kernel); 37void KClientPort::OnServerClosed() {}
33 session->Initialize(name + ":ClientPort");
34 38
35 if (server_port->HasHLEHandler()) { 39bool KClientPort::IsLight() const {
36 server_port->GetHLEHandler()->ClientConnected(session); 40 return this->GetParent()->IsLight();
37 } else { 41}
38 server_port->AppendPendingSession(std::addressof(session->GetServerSession()));
39 }
40 42
41 return MakeResult(std::addressof(session->GetClientSession())); 43bool KClientPort::IsServerClosed() const {
44 return this->GetParent()->IsServerClosed();
42} 45}
43 46
44void KClientPort::ConnectionClosed() { 47void KClientPort::Destroy() {
45 if (num_sessions == 0) { 48 // Note with our parent that we're closed.
46 return; 49 parent->OnClientClosed();
47 }
48 50
49 --num_sessions; 51 // Close our reference to our parent.
52 parent->Close();
50} 53}
51 54
52void KClientPort::Destroy() {}
53
54bool KClientPort::IsSignaled() const { 55bool KClientPort::IsSignaled() const {
55 return num_sessions < max_sessions; 56 return num_sessions < max_sessions;
56} 57}
57 58
59ResultCode KClientPort::CreateSession(KClientSession** out) {
60 // Reserve a new session from the resource limit.
61 KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
62 LimitableResource::Sessions);
63 R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
64
65 // Update the session counts.
66 {
67 // Atomically increment the number of sessions.
68 s32 new_sessions;
69 {
70 const auto max = max_sessions;
71 auto cur_sessions = num_sessions.load(std::memory_order_acquire);
72 do {
73 R_UNLESS(cur_sessions < max, ResultOutOfSessions);
74 new_sessions = cur_sessions + 1;
75 } while (!num_sessions.compare_exchange_weak(cur_sessions, new_sessions,
76 std::memory_order_relaxed));
77 }
78
79 // Atomically update the peak session tracking.
80 {
81 auto peak = peak_sessions.load(std::memory_order_acquire);
82 do {
83 if (peak >= new_sessions) {
84 break;
85 }
86 } while (!peak_sessions.compare_exchange_weak(peak, new_sessions,
87 std::memory_order_relaxed));
88 }
89 }
90
91 // Create a new session.
92 KSession* session = KSession::Create(kernel);
93 if (session == nullptr) {
94 /* Decrement the session count. */
95 const auto prev = num_sessions--;
96 if (prev == max_sessions) {
97 this->NotifyAvailable();
98 }
99
100 return ResultOutOfResource;
101 }
102
103 // Initialize the session.
104 session->Initialize(this, parent->GetName());
105
106 // Commit the session reservation.
107 session_reservation.Commit();
108
109 // Register the session.
110 KSession::Register(kernel, session);
111 auto session_guard = SCOPE_GUARD({
112 session->GetClientSession().Close();
113 session->GetServerSession().Close();
114 });
115
116 // Enqueue the session with our parent.
117 R_TRY(parent->EnqueueSession(std::addressof(session->GetServerSession())));
118
119 // We succeeded, so set the output.
120 session_guard.Cancel();
121 *out = std::addressof(session->GetClientSession());
122 return RESULT_SUCCESS;
123}
124
58} // namespace Kernel 125} // namespace Kernel
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h
index 60dea4763..43a17f4a4 100644
--- a/src/core/hle/kernel/k_client_port.h
+++ b/src/core/hle/kernel/k_client_port.h
@@ -15,7 +15,7 @@ namespace Kernel {
15 15
16class KClientSession; 16class KClientSession;
17class KernelCore; 17class KernelCore;
18class KServerPort; 18class KPort;
19 19
20class KClientPort final : public KSynchronizationObject { 20class KClientPort final : public KSynchronizationObject {
21 KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject); 21 KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject);
@@ -24,30 +24,33 @@ public:
24 explicit KClientPort(KernelCore& kernel); 24 explicit KClientPort(KernelCore& kernel);
25 virtual ~KClientPort() override; 25 virtual ~KClientPort() override;
26 26
27 friend class KServerPort; 27 void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_);
28 void OnSessionFinalized();
29 void OnServerClosed();
28 30
29 void Initialize(s32 max_sessions_, std::string&& name_); 31 constexpr const KPort* GetParent() const {
30 32 return parent;
31 KServerPort* GetServerPort() const; 33 }
32 34
33 /** 35 s32 GetNumSessions() const {
34 * Creates a new Session pair, adds the created ServerSession to the associated ServerPort's 36 return num_sessions;
35 * list of pending sessions, and signals the ServerPort, causing any threads 37 }
36 * waiting on it to awake. 38 s32 GetPeakSessions() const {
37 * @returns ClientSession The client endpoint of the created Session pair, or error code. 39 return peak_sessions;
38 */ 40 }
39 ResultVal<KClientSession*> Connect(); 41 s32 GetMaxSessions() const {
42 return max_sessions;
43 }
40 44
41 /** 45 bool IsLight() const;
42 * Signifies that a previously active connection has been closed, 46 bool IsServerClosed() const;
43 * decreasing the total number of active connections to this port.
44 */
45 void ConnectionClosed();
46 47
47 // Overridden virtual functions. 48 // Overridden virtual functions.
48 virtual void Destroy() override; 49 virtual void Destroy() override;
49 virtual bool IsSignaled() const override; 50 virtual bool IsSignaled() const override;
50 51
52 ResultCode CreateSession(KClientSession** out);
53
51 // DEPRECATED 54 // DEPRECATED
52 55
53 std::string GetTypeName() const override { 56 std::string GetTypeName() const override {
@@ -63,10 +66,11 @@ public:
63 } 66 }
64 67
65private: 68private:
66 KServerPort* server_port{}; ///< ServerPort associated with this client port. 69 std::atomic<s32> num_sessions{};
67 s32 max_sessions{}; ///< Maximum number of simultaneous sessions the port can have 70 std::atomic<s32> peak_sessions{};
68 std::atomic<s32> num_sessions{}; ///< Number of currently open sessions to this port 71 s32 max_sessions{};
69 std::string name; ///< Name of client port (optional) 72 KPort* parent{};
73 std::string name;
70}; 74};
71 75
72} // namespace Kernel 76} // namespace Kernel
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h
index 2c48a0499..45634e401 100644
--- a/src/core/hle/kernel/k_event.h
+++ b/src/core/hle/kernel/k_event.h
@@ -20,7 +20,7 @@ class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObj
20 20
21public: 21public:
22 explicit KEvent(KernelCore& kernel); 22 explicit KEvent(KernelCore& kernel);
23 ~KEvent() override; 23 virtual ~KEvent();
24 24
25 void Initialize(std::string&& name); 25 void Initialize(std::string&& name);
26 26
diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp
new file mode 100644
index 000000000..734aa2a8c
--- /dev/null
+++ b/src/core/hle/kernel/k_port.cpp
@@ -0,0 +1,68 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/hle_ipc.h"
6#include "core/hle/kernel/k_port.h"
7#include "core/hle/kernel/k_scheduler.h"
8#include "core/hle/kernel/svc_results.h"
9
10namespace Kernel {
11
12KPort::KPort(KernelCore& kernel)
13 : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {}
14
15KPort::~KPort() = default;
16
17void KPort::Initialize(s32 max_sessions_, bool is_light_, const std::string& name_) {
18 // Open a new reference count to the initialized port.
19 Open();
20
21 // Create and initialize our server/client pair.
22 KAutoObject::Create(std::addressof(server));
23 KAutoObject::Create(std::addressof(client));
24 server.Initialize(this, name_ + ":Server");
25 client.Initialize(this, max_sessions_, name_ + ":Client");
26
27 // Set our member variables.
28 is_light = is_light_;
29 name = name_;
30 state = State::Normal;
31}
32
33void KPort::OnClientClosed() {
34 KScopedSchedulerLock sl{kernel};
35
36 if (state == State::Normal) {
37 state = State::ClientClosed;
38 }
39}
40
41void KPort::OnServerClosed() {
42 KScopedSchedulerLock sl{kernel};
43
44 if (state == State::Normal) {
45 state = State::ServerClosed;
46 }
47}
48
49bool KPort::IsServerClosed() const {
50 KScopedSchedulerLock sl{kernel};
51 return state == State::ServerClosed;
52}
53
54ResultCode KPort::EnqueueSession(KServerSession* session) {
55 KScopedSchedulerLock sl{kernel};
56
57 R_UNLESS(state == State::Normal, ResultPortClosed);
58
59 if (server.HasHLEHandler()) {
60 server.GetHLEHandler()->ClientConnected(session);
61 } else {
62 server.EnqueueSession(session);
63 }
64
65 return RESULT_SUCCESS;
66}
67
68} // namespace Kernel
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h
new file mode 100644
index 000000000..68c8ed8df
--- /dev/null
+++ b/src/core/hle/kernel/k_port.h
@@ -0,0 +1,87 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <string>
9
10#include "common/common_types.h"
11#include "core/hle/kernel/k_client_port.h"
12#include "core/hle/kernel/k_server_port.h"
13#include "core/hle/kernel/slab_helpers.h"
14#include "core/hle/result.h"
15
16namespace Kernel {
17
18class KServerSession;
19
20class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjectWithList> {
21 KERNEL_AUTOOBJECT_TRAITS(KPort, KAutoObject);
22
23public:
24 explicit KPort(KernelCore& kernel);
25 virtual ~KPort();
26
27 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
28
29 void Initialize(s32 max_sessions_, bool is_light_, const std::string& name_);
30 void OnClientClosed();
31 void OnServerClosed();
32
33 bool IsLight() const {
34 return is_light;
35 }
36
37 bool IsServerClosed() const;
38
39 ResultCode EnqueueSession(KServerSession* session);
40
41 KClientPort& GetClientPort() {
42 return client;
43 }
44 KServerPort& GetServerPort() {
45 return server;
46 }
47 const KClientPort& GetClientPort() const {
48 return client;
49 }
50 const KServerPort& GetServerPort() const {
51 return server;
52 }
53
54 // DEPRECATED
55
56 friend class ServerPort;
57 std::string GetTypeName() const override {
58 return "Port";
59 }
60 std::string GetName() const override {
61 return name;
62 }
63
64 HandleType GetHandleType() const override {
65 return {};
66 }
67
68 void Finalize() override {}
69
70private:
71 enum class State : u8 {
72 Invalid = 0,
73 Normal = 1,
74 ClientClosed = 2,
75 ServerClosed = 3,
76 };
77
78private:
79 KServerPort server;
80 KClientPort client;
81 State state{State::Invalid};
82 bool is_light{};
83
84 std::string name; ///< Name of client port (optional)
85};
86
87} // namespace Kernel
diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp
index 2c51d66db..fcc04abaa 100644
--- a/src/core/hle/kernel/k_server_port.cpp
+++ b/src/core/hle/kernel/k_server_port.cpp
@@ -1,10 +1,12 @@
1// Copyright 2016 Citra Emulator Project 1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <tuple> 5#include <tuple>
6#include "common/assert.h" 6#include "common/assert.h"
7#include "core/hle/kernel/k_client_port.h" 7#include "core/hle/kernel/k_client_port.h"
8#include "core/hle/kernel/k_port.h"
9#include "core/hle/kernel/k_scheduler.h"
8#include "core/hle/kernel/k_server_port.h" 10#include "core/hle/kernel/k_server_port.h"
9#include "core/hle/kernel/k_server_session.h" 11#include "core/hle/kernel/k_server_session.h"
10#include "core/hle/kernel/k_thread.h" 12#include "core/hle/kernel/k_thread.h"
@@ -16,50 +18,88 @@ namespace Kernel {
16KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} 18KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {}
17KServerPort::~KServerPort() = default; 19KServerPort::~KServerPort() = default;
18 20
19void KServerPort::Initialize(std::string&& name_) { 21void KServerPort::Initialize(KPort* parent_, std::string&& name_) {
20 // Set member variables. 22 // Set member variables.
23 parent = parent_;
21 name = std::move(name_); 24 name = std::move(name_);
22} 25}
23 26
24ResultVal<KServerSession*> KServerPort::Accept() { 27bool KServerPort::IsLight() const {
25 if (pending_sessions.empty()) { 28 return this->GetParent()->IsLight();
26 return ResultNotFound;
27 }
28
29 auto* session = pending_sessions.back();
30 pending_sessions.pop_back();
31 return MakeResult(session);
32} 29}
33 30
34void KServerPort::AppendPendingSession(KServerSession* pending_session) { 31void KServerPort::CleanupSessions() {
35 pending_sessions.push_back(std::move(pending_session)); 32 // Ensure our preconditions are met.
36 if (pending_sessions.size() == 1) { 33 if (this->IsLight()) {
37 NotifyAvailable(); 34 UNIMPLEMENTED();
35 }
36
37 // Cleanup the session list.
38 while (true) {
39 // Get the last session in the list
40 KServerSession* session = nullptr;
41 {
42 KScopedSchedulerLock sl{kernel};
43 if (!session_list.empty()) {
44 session = std::addressof(session_list.front());
45 session_list.pop_front();
46 }
47 }
48
49 // Close the session.
50 if (session != nullptr) {
51 session->Close();
52 } else {
53 break;
54 }
38 } 55 }
39} 56}
40 57
41void KServerPort::Destroy() {} 58void KServerPort::Destroy() {
59 // Note with our parent that we're closed.
60 parent->OnServerClosed();
61
62 // Perform necessary cleanup of our session lists.
63 this->CleanupSessions();
64
65 // Close our reference to our parent.
66 parent->Close();
67}
42 68
43bool KServerPort::IsSignaled() const { 69bool KServerPort::IsSignaled() const {
44 return !pending_sessions.empty(); 70 if (this->IsLight()) {
71 UNIMPLEMENTED();
72 return false;
73 } else {
74 return !session_list.empty();
75 }
45} 76}
46 77
47KServerPort::PortPair KServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions, 78void KServerPort::EnqueueSession(KServerSession* session) {
48 std::string name) { 79 ASSERT(!this->IsLight());
49 KServerPort* server_port = new KServerPort(kernel); 80
50 KClientPort* client_port = new KClientPort(kernel); 81 KScopedSchedulerLock sl{kernel};
51 82
52 KAutoObject::Create(server_port); 83 // Add the session to our queue.
53 KAutoObject::Create(client_port); 84 session_list.push_back(*session);
85 if (session_list.size() == 1) {
86 this->NotifyAvailable();
87 }
88}
54 89
55 server_port->Initialize(name + "_Server"); 90KServerSession* KServerPort::AcceptSession() {
56 client_port->Initialize(max_sessions, name + "_Client"); 91 ASSERT(!this->IsLight());
57 92
58 client_port->server_port = server_port; 93 KScopedSchedulerLock sl{kernel};
59 94
60 server_port->name = name + "_Server"; 95 // Return the first session in the list.
96 if (session_list.empty()) {
97 return nullptr;
98 }
61 99
62 return std::make_pair(server_port, client_port); 100 KServerSession* session = std::addressof(session_list.front());
101 session_list.pop_front();
102 return session;
63} 103}
64 104
65} // namespace Kernel 105} // namespace Kernel
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h
index 13fa54e5e..9f45ca3f4 100644
--- a/src/core/hle/kernel/k_server_port.h
+++ b/src/core/hle/kernel/k_server_port.h
@@ -1,4 +1,4 @@
1// Copyright 2016 Citra Emulator Project 1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
@@ -8,46 +8,33 @@
8#include <string> 8#include <string>
9#include <utility> 9#include <utility>
10#include <vector> 10#include <vector>
11
12#include <boost/intrusive/list.hpp>
13
11#include "common/common_types.h" 14#include "common/common_types.h"
15#include "core/hle/kernel/k_server_session.h"
12#include "core/hle/kernel/k_synchronization_object.h" 16#include "core/hle/kernel/k_synchronization_object.h"
13#include "core/hle/kernel/object.h"
14#include "core/hle/result.h" 17#include "core/hle/result.h"
15 18
16namespace Kernel { 19namespace Kernel {
17 20
18class KClientPort;
19class KernelCore; 21class KernelCore;
20class KServerSession; 22class KPort;
21class SessionRequestHandler; 23class SessionRequestHandler;
22 24
23class KServerPort final : public KSynchronizationObject { 25class KServerPort final : public KSynchronizationObject {
24 KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject); 26 KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject);
25 27
28private:
29 using SessionList = boost::intrusive::list<KServerSession>;
30
26public: 31public:
27 explicit KServerPort(KernelCore& kernel); 32 explicit KServerPort(KernelCore& kernel);
28 virtual ~KServerPort() override; 33 virtual ~KServerPort() override;
29 34
30 using HLEHandler = std::shared_ptr<SessionRequestHandler>; 35 using HLEHandler = std::shared_ptr<SessionRequestHandler>;
31 using PortPair = std::pair<KServerPort*, KClientPort*>;
32
33 void Initialize(std::string&& name_);
34
35 /**
36 * Creates a pair of ServerPort and an associated ClientPort.
37 *
38 * @param kernel The kernel instance to create the port pair under.
39 * @param max_sessions Maximum number of sessions to the port
40 * @param name Optional name of the ports
41 * @return The created port tuple
42 */
43 static PortPair CreatePortPair(KernelCore& kernel, u32 max_sessions,
44 std::string name = "UnknownPort");
45 36
46 /** 37 void Initialize(KPort* parent_, std::string&& name_);
47 * Accepts a pending incoming connection on this port. If there are no pending sessions, will
48 * return ERR_NO_PENDING_SESSIONS.
49 */
50 ResultVal<KServerSession*> Accept();
51 38
52 /// Whether or not this server port has an HLE handler available. 39 /// Whether or not this server port has an HLE handler available.
53 bool HasHLEHandler() const { 40 bool HasHLEHandler() const {
@@ -67,9 +54,15 @@ public:
67 hle_handler = std::move(hle_handler_); 54 hle_handler = std::move(hle_handler_);
68 } 55 }
69 56
70 /// Appends a ServerSession to the collection of ServerSessions 57 void EnqueueSession(KServerSession* pending_session);
71 /// waiting to be accepted by this port. 58
72 void AppendPendingSession(KServerSession* pending_session); 59 KServerSession* AcceptSession();
60
61 constexpr const KPort* GetParent() const {
62 return parent;
63 }
64
65 bool IsLight() const;
73 66
74 // Overridden virtual functions. 67 // Overridden virtual functions.
75 virtual void Destroy() override; 68 virtual void Destroy() override;
@@ -90,14 +83,12 @@ public:
90 } 83 }
91 84
92private: 85private:
93 /// ServerSessions waiting to be accepted by the port 86 void CleanupSessions();
94 std::vector<KServerSession*> pending_sessions;
95 87
96 /// This session's HLE request handler template (optional) 88private:
97 /// ServerSessions created from this port inherit a reference to this handler. 89 SessionList session_list;
98 HLEHandler hle_handler; 90 HLEHandler hle_handler;
99 91 KPort* parent{};
100 /// Name of the port (optional)
101 std::string name; 92 std::string name;
102}; 93};
103 94
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index 46ba7081b..863f9aa5f 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -50,7 +50,7 @@ void KServerSession::OnClientClosed() {
50 if (handler) { 50 if (handler) {
51 // Note that after this returns, this server session's hle_handler is 51 // Note that after this returns, this server session's hle_handler is
52 // invalidated (set to null). 52 // invalidated (set to null).
53 handler->ClientDisconnected(parent); 53 handler->ClientDisconnected(this);
54 } 54 }
55} 55}
56 56
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index ef81c4e30..d748754d0 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -9,6 +9,8 @@
9#include <utility> 9#include <utility>
10#include <vector> 10#include <vector>
11 11
12#include <boost/intrusive/list.hpp>
13
12#include "common/threadsafe_queue.h" 14#include "common/threadsafe_queue.h"
13#include "core/hle/kernel/k_synchronization_object.h" 15#include "core/hle/kernel/k_synchronization_object.h"
14#include "core/hle/kernel/service_thread.h" 16#include "core/hle/kernel/service_thread.h"
@@ -31,7 +33,8 @@ class KSession;
31class SessionRequestHandler; 33class SessionRequestHandler;
32class KThread; 34class KThread;
33 35
34class KServerSession final : public KSynchronizationObject { 36class KServerSession final : public KSynchronizationObject,
37 public boost::intrusive::list_base_hook<> {
35 KERNEL_AUTOOBJECT_TRAITS(KServerSession, KSynchronizationObject); 38 KERNEL_AUTOOBJECT_TRAITS(KServerSession, KSynchronizationObject);
36 39
37 friend class ServiceThread; 40 friend class ServiceThread;
diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp
index ca1cf18cd..6f4276189 100644
--- a/src/core/hle/kernel/k_session.cpp
+++ b/src/core/hle/kernel/k_session.cpp
@@ -1,8 +1,9 @@
1// Copyright 2019 yuzu emulator team 1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "core/hle/kernel/k_client_port.h"
6#include "core/hle/kernel/k_client_session.h" 7#include "core/hle/kernel/k_client_session.h"
7#include "core/hle/kernel/k_scoped_resource_reservation.h" 8#include "core/hle/kernel/k_scoped_resource_reservation.h"
8#include "core/hle/kernel/k_server_session.h" 9#include "core/hle/kernel/k_server_session.h"
@@ -14,7 +15,7 @@ KSession::KSession(KernelCore& kernel)
14 : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {} 15 : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {}
15KSession::~KSession() = default; 16KSession::~KSession() = default;
16 17
17void KSession::Initialize(std::string&& name_) { 18void KSession::Initialize(KClientPort* port_, std::string&& name_) {
18 // Increment reference count. 19 // Increment reference count.
19 // Because reference count is one on creation, this will result 20 // 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 21 // in a reference count of two. Thus, when both server and client are closed
@@ -37,11 +38,22 @@ void KSession::Initialize(std::string&& name_) {
37 process = kernel.CurrentProcess(); 38 process = kernel.CurrentProcess();
38 process->Open(); 39 process->Open();
39 40
41 // Set our port.
42 port = port_;
43 if (port != nullptr) {
44 port->Open();
45 }
46
40 // Mark initialized. 47 // Mark initialized.
41 initialized = true; 48 initialized = true;
42} 49}
43 50
44void KSession::Finalize() {} 51void KSession::Finalize() {
52 if (port != nullptr) {
53 port->OnSessionFinalized();
54 port->Close();
55 }
56}
45 57
46void KSession::OnServerClosed() { 58void KSession::OnServerClosed() {
47 if (GetState() == State::Normal) { 59 if (GetState() == State::Normal) {
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h
index 6a6fcb588..1597cc608 100644
--- a/src/core/hle/kernel/k_session.h
+++ b/src/core/hle/kernel/k_session.h
@@ -28,7 +28,7 @@ public:
28 explicit KSession(KernelCore& kernel); 28 explicit KSession(KernelCore& kernel);
29 virtual ~KSession() override; 29 virtual ~KSession() override;
30 30
31 void Initialize(std::string&& name_); 31 void Initialize(KClientPort* port_, std::string&& name_);
32 32
33 virtual void Finalize() override; 33 virtual void Finalize() override;
34 34
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 19b3530b4..723be6b51 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -37,6 +37,8 @@ class KClientSession;
37class KEvent; 37class KEvent;
38class KLinkedListNode; 38class KLinkedListNode;
39class KMemoryManager; 39class KMemoryManager;
40class KPort;
41class Process;
40class KResourceLimit; 42class KResourceLimit;
41class KScheduler; 43class KScheduler;
42class KSession; 44class KSession;
@@ -45,7 +47,6 @@ class KThread;
45class KTransferMemory; 47class KTransferMemory;
46class KWritableEvent; 48class KWritableEvent;
47class PhysicalCore; 49class PhysicalCore;
48class Process;
49class ServiceThread; 50class ServiceThread;
50class Synchronization; 51class Synchronization;
51class TimeManager; 52class TimeManager;
@@ -272,6 +273,8 @@ public:
272 return slab_heap_container->event; 273 return slab_heap_container->event;
273 } else if constexpr (std::is_same_v<T, KLinkedListNode>) { 274 } else if constexpr (std::is_same_v<T, KLinkedListNode>) {
274 return slab_heap_container->linked_list_node; 275 return slab_heap_container->linked_list_node;
276 } else if constexpr (std::is_same_v<T, KPort>) {
277 return slab_heap_container->port;
275 } else if constexpr (std::is_same_v<T, Process>) { 278 } else if constexpr (std::is_same_v<T, Process>) {
276 return slab_heap_container->process; 279 return slab_heap_container->process;
277 } else if constexpr (std::is_same_v<T, KResourceLimit>) { 280 } else if constexpr (std::is_same_v<T, KResourceLimit>) {
@@ -323,6 +326,7 @@ private:
323 KSlabHeap<KClientSession> client_session; 326 KSlabHeap<KClientSession> client_session;
324 KSlabHeap<KEvent> event; 327 KSlabHeap<KEvent> event;
325 KSlabHeap<KLinkedListNode> linked_list_node; 328 KSlabHeap<KLinkedListNode> linked_list_node;
329 KSlabHeap<KPort> port;
326 KSlabHeap<Process> process; 330 KSlabHeap<Process> process;
327 KSlabHeap<KResourceLimit> resource_limit; 331 KSlabHeap<KResourceLimit> resource_limit;
328 KSlabHeap<KSession> session; 332 KSlabHeap<KSession> session;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 8d8d3dd5a..ef8fa98a9 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -293,9 +293,7 @@ static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr
293/// Connect to an OS service given the port name, returns the handle to the port to out 293/// Connect to an OS service given the port name, returns the handle to the port to out
294static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, 294static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
295 VAddr port_name_address) { 295 VAddr port_name_address) {
296 std::lock_guard lock{HLE::g_hle_lock};
297 auto& memory = system.Memory(); 296 auto& memory = system.Memory();
298
299 if (!memory.IsValidVirtualAddress(port_name_address)) { 297 if (!memory.IsValidVirtualAddress(port_name_address)) {
300 LOG_ERROR(Kernel_SVC, 298 LOG_ERROR(Kernel_SVC,
301 "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}", 299 "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
@@ -314,21 +312,27 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
314 312
315 LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); 313 LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
316 314
315 // Get the current handle table.
317 auto& kernel = system.Kernel(); 316 auto& kernel = system.Kernel();
317 auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
318
319 // Find the client port.
318 const auto it = kernel.FindNamedPort(port_name); 320 const auto it = kernel.FindNamedPort(port_name);
319 if (!kernel.IsValidNamedPort(it)) { 321 if (!kernel.IsValidNamedPort(it)) {
320 LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name); 322 LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
321 return ResultNotFound; 323 return ResultNotFound;
322 } 324 }
325 auto port = it->second;
323 326
324 auto client_port = it->second; 327 // Create a session.
328 KClientSession* session{};
329 R_TRY(port->CreateSession(std::addressof(session)));
325 330
326 KClientSession* client_session{}; 331 // Register the session in the table, close the extra reference.
327 CASCADE_RESULT(client_session, client_port->Connect()); 332 handle_table.Add(out_handle, session);
333 session->Close();
328 334
329 // Return the client session 335 // We succeeded.
330 auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
331 handle_table.Add(out_handle, client_session);
332 return RESULT_SUCCESS; 336 return RESULT_SUCCESS;
333} 337}
334 338
@@ -340,13 +344,13 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle,
340 344
341/// Makes a blocking IPC call to an OS service. 345/// Makes a blocking IPC call to an OS service.
342static ResultCode SendSyncRequest(Core::System& system, Handle handle) { 346static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
343 LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
344 347
345 auto& kernel = system.Kernel(); 348 auto& kernel = system.Kernel();
346 349
347 KScopedAutoObject session = 350 KScopedAutoObject session =
348 kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle); 351 kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
349 R_UNLESS(session.IsNotNull(), ResultInvalidHandle); 352 R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
353 LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
350 354
351 auto thread = kernel.CurrentScheduler()->GetCurrentThread(); 355 auto thread = kernel.CurrentScheduler()->GetCurrentThread();
352 { 356 {
diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h
index cd32acd99..53a940723 100644
--- a/src/core/hle/kernel/svc_results.h
+++ b/src/core/hle/kernel/svc_results.h
@@ -36,6 +36,7 @@ constexpr ResultCode ResultBusy{ErrorModule::Kernel, 122};
36constexpr ResultCode ResultSessionClosed{ErrorModule::Kernel, 123}; 36constexpr ResultCode ResultSessionClosed{ErrorModule::Kernel, 123};
37constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125}; 37constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125};
38constexpr ResultCode ResultReservedUsed{ErrorModule::Kernel, 126}; 38constexpr ResultCode ResultReservedUsed{ErrorModule::Kernel, 126};
39constexpr ResultCode ResultPortClosed{ErrorModule::Kernel, 131};
39constexpr ResultCode ResultLimitReached{ErrorModule::Kernel, 132}; 40constexpr ResultCode ResultLimitReached{ErrorModule::Kernel, 132};
40constexpr ResultCode ResultInvalidId{ErrorModule::Kernel, 519}; 41constexpr ResultCode ResultInvalidId{ErrorModule::Kernel, 519};
41 42
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index a882b3b4e..42e464024 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -116,10 +116,11 @@ void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) {
116 116
117 ASSERT(!port_installed); 117 ASSERT(!port_installed);
118 118
119 auto [server_port, client_port] = 119 auto* port = Kernel::KPort::Create(kernel);
120 Kernel::KServerPort::CreatePortPair(kernel, max_sessions, service_name); 120 port->Initialize(max_sessions, false, service_name);
121 server_port->SetHleHandler(shared_from_this()); 121 port->GetServerPort().SetHleHandler(shared_from_this());
122 kernel.AddNamedPort(service_name, client_port); 122 kernel.AddNamedPort(service_name, &port->GetClientPort());
123
123 port_installed = true; 124 port_installed = true;
124} 125}
125 126
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 51274bfb1..71ab4b6f5 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -8,6 +8,7 @@
8#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/k_client_port.h" 9#include "core/hle/kernel/k_client_port.h"
10#include "core/hle/kernel/k_client_session.h" 10#include "core/hle/kernel/k_client_session.h"
11#include "core/hle/kernel/k_port.h"
11#include "core/hle/kernel/k_server_port.h" 12#include "core/hle/kernel/k_server_port.h"
12#include "core/hle/kernel/k_server_session.h" 13#include "core/hle/kernel/k_server_session.h"
13#include "core/hle/kernel/k_session.h" 14#include "core/hle/kernel/k_session.h"
@@ -59,13 +60,12 @@ ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name
59 return ERR_ALREADY_REGISTERED; 60 return ERR_ALREADY_REGISTERED;
60 } 61 }
61 62
62 auto [server_port, client_port] = 63 auto* port = Kernel::KPort::Create(kernel);
63 Kernel::KServerPort::CreatePortPair(kernel, max_sessions, name); 64 port->Initialize(max_sessions, false, name);
64 65
65 client_port->Open(); 66 registered_services.emplace(std::move(name), port);
66 67
67 registered_services.emplace(std::move(name), client_port); 68 return MakeResult(&port->GetServerPort());
68 return MakeResult(server_port);
69} 69}
70 70
71ResultCode ServiceManager::UnregisterService(const std::string& name) { 71ResultCode ServiceManager::UnregisterService(const std::string& name) {
@@ -83,7 +83,7 @@ ResultCode ServiceManager::UnregisterService(const std::string& name) {
83 return RESULT_SUCCESS; 83 return RESULT_SUCCESS;
84} 84}
85 85
86ResultVal<Kernel::KClientPort*> ServiceManager::GetServicePort(const std::string& name) { 86ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) {
87 87
88 CASCADE_CODE(ValidateServiceName(name)); 88 CASCADE_CODE(ValidateServiceName(name));
89 auto it = registered_services.find(name); 89 auto it = registered_services.find(name);
@@ -118,25 +118,26 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
118 118
119 std::string name(name_buf.begin(), end); 119 std::string name(name_buf.begin(), end);
120 120
121 auto client_port = service_manager->GetServicePort(name); 121 auto result = service_manager->GetServicePort(name);
122 if (client_port.Failed()) { 122 if (result.Failed()) {
123 IPC::ResponseBuilder rb{ctx, 2}; 123 IPC::ResponseBuilder rb{ctx, 2};
124 rb.Push(client_port.Code()); 124 rb.Push(result.Code());
125 LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, client_port.Code().raw); 125 LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw);
126 if (name.length() == 0) 126 if (name.length() == 0)
127 return; // LibNX Fix 127 return; // LibNX Fix
128 UNIMPLEMENTED(); 128 UNIMPLEMENTED();
129 return; 129 return;
130 } 130 }
131 131
132 auto* port = result.Unwrap();
133
132 auto* session = Kernel::KSession::Create(kernel); 134 auto* session = Kernel::KSession::Create(kernel);
133 session->Initialize(std::move(name)); 135 session->Initialize(&port->GetClientPort(), std::move(name));
134 136
135 const auto& server_port = client_port.Unwrap()->GetServerPort(); 137 if (port->GetServerPort().GetHLEHandler()) {
136 if (server_port->GetHLEHandler()) { 138 port->GetServerPort().GetHLEHandler()->ClientConnected(&session->GetServerSession());
137 server_port->GetHLEHandler()->ClientConnected(session);
138 } else { 139 } else {
139 server_port->AppendPendingSession(&session->GetServerSession()); 140 port->EnqueueSession(&session->GetServerSession());
140 } 141 }
141 142
142 LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetObjectId()); 143 LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetObjectId());
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index b0204c4bb..af5010c3b 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -10,9 +10,7 @@
10#include <unordered_map> 10#include <unordered_map>
11 11
12#include "common/concepts.h" 12#include "common/concepts.h"
13#include "core/hle/kernel/k_client_port.h" 13#include "core/hle/kernel/k_port.h"
14#include "core/hle/kernel/k_server_port.h"
15#include "core/hle/kernel/object.h"
16#include "core/hle/result.h" 14#include "core/hle/result.h"
17#include "core/hle/service/service.h" 15#include "core/hle/service/service.h"
18 16
@@ -24,6 +22,7 @@ namespace Kernel {
24class KClientPort; 22class KClientPort;
25class KClientSession; 23class KClientSession;
26class KernelCore; 24class KernelCore;
25class KPort;
27class KServerPort; 26class KServerPort;
28class SessionRequestHandler; 27class SessionRequestHandler;
29} // namespace Kernel 28} // namespace Kernel
@@ -57,7 +56,7 @@ public:
57 56
58 ResultVal<Kernel::KServerPort*> RegisterService(std::string name, u32 max_sessions); 57 ResultVal<Kernel::KServerPort*> RegisterService(std::string name, u32 max_sessions);
59 ResultCode UnregisterService(const std::string& name); 58 ResultCode UnregisterService(const std::string& name);
60 ResultVal<Kernel::KClientPort*> GetServicePort(const std::string& name); 59 ResultVal<Kernel::KPort*> GetServicePort(const std::string& name);
61 60
62 template <Common::DerivedFrom<Kernel::SessionRequestHandler> T> 61 template <Common::DerivedFrom<Kernel::SessionRequestHandler> T>
63 std::shared_ptr<T> GetService(const std::string& service_name) const { 62 std::shared_ptr<T> GetService(const std::string& service_name) const {
@@ -66,11 +65,11 @@ public:
66 LOG_DEBUG(Service, "Can't find service: {}", service_name); 65 LOG_DEBUG(Service, "Can't find service: {}", service_name);
67 return nullptr; 66 return nullptr;
68 } 67 }
69 auto port = service->second->GetServerPort(); 68 auto* port = service->second;
70 if (port == nullptr) { 69 if (port == nullptr) {
71 return nullptr; 70 return nullptr;
72 } 71 }
73 return std::static_pointer_cast<T>(port->GetHLEHandler()); 72 return std::static_pointer_cast<T>(port->GetServerPort().GetHLEHandler());
74 } 73 }
75 74
76 void InvokeControlRequest(Kernel::HLERequestContext& context); 75 void InvokeControlRequest(Kernel::HLERequestContext& context);
@@ -80,7 +79,7 @@ private:
80 std::unique_ptr<Controller> controller_interface; 79 std::unique_ptr<Controller> controller_interface;
81 80
82 /// Map of registered services, retrieved using GetServicePort. 81 /// Map of registered services, retrieved using GetServicePort.
83 std::unordered_map<std::string, Kernel::KClientPort*> registered_services; 82 std::unordered_map<std::string, Kernel::KPort*> registered_services;
84 83
85 /// Kernel context 84 /// Kernel context
86 Kernel::KernelCore& kernel; 85 Kernel::KernelCore& kernel;