diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/ipc_helpers.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/init/init_slab_setup.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_client_port.cpp | 119 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_client_port.h | 46 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_event.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_port.cpp | 68 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_port.h | 87 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_port.cpp | 94 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_port.h | 55 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_session.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_session.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_session.cpp | 18 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_session.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 22 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_results.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/service.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.cpp | 31 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.h | 13 |
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 | ||
| 36 | SessionRequestHandler::~SessionRequestHandler() = default; | 36 | SessionRequestHandler::~SessionRequestHandler() = default; |
| 37 | 37 | ||
| 38 | void SessionRequestHandler::ClientConnected(KSession* session) { | 38 | void 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 | ||
| 43 | void SessionRequestHandler::ClientDisconnected(KSession* session) { | 42 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { |
| 44 | session->GetServerSession().SetHleHandler(nullptr); | 43 | session->SetHleHandler(nullptr); |
| 45 | boost::range::remove_erase(sessions, session); | ||
| 46 | } | 44 | } |
| 47 | 45 | ||
| 48 | HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, | 46 | HLERequestContext::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 | |||
| 84 | protected: | ||
| 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 | ||
| 12 | namespace Kernel { | 14 | namespace Kernel { |
| @@ -14,45 +16,110 @@ namespace Kernel { | |||
| 14 | KClientPort::KClientPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} | 16 | KClientPort::KClientPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} |
| 15 | KClientPort::~KClientPort() = default; | 17 | KClientPort::~KClientPort() = default; |
| 16 | 18 | ||
| 17 | void KClientPort::Initialize(s32 max_sessions_, std::string&& name_) { | 19 | void 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 | ||
| 22 | KServerPort* KClientPort::GetServerPort() const { | 28 | void KClientPort::OnSessionFinalized() { |
| 23 | return server_port; | 29 | KScopedSchedulerLock sl{kernel}; |
| 24 | } | ||
| 25 | 30 | ||
| 26 | ResultVal<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); | 37 | void KClientPort::OnServerClosed() {} |
| 33 | session->Initialize(name + ":ClientPort"); | ||
| 34 | 38 | ||
| 35 | if (server_port->HasHLEHandler()) { | 39 | bool 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())); | 43 | bool KClientPort::IsServerClosed() const { |
| 44 | return this->GetParent()->IsServerClosed(); | ||
| 42 | } | 45 | } |
| 43 | 46 | ||
| 44 | void KClientPort::ConnectionClosed() { | 47 | void 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 | ||
| 52 | void KClientPort::Destroy() {} | ||
| 53 | |||
| 54 | bool KClientPort::IsSignaled() const { | 55 | bool KClientPort::IsSignaled() const { |
| 55 | return num_sessions < max_sessions; | 56 | return num_sessions < max_sessions; |
| 56 | } | 57 | } |
| 57 | 58 | ||
| 59 | ResultCode 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 | ||
| 16 | class KClientSession; | 16 | class KClientSession; |
| 17 | class KernelCore; | 17 | class KernelCore; |
| 18 | class KServerPort; | 18 | class KPort; |
| 19 | 19 | ||
| 20 | class KClientPort final : public KSynchronizationObject { | 20 | class 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 | ||
| 65 | private: | 68 | private: |
| 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 | ||
| 21 | public: | 21 | public: |
| 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 | |||
| 10 | namespace Kernel { | ||
| 11 | |||
| 12 | KPort::KPort(KernelCore& kernel) | ||
| 13 | : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {} | ||
| 14 | |||
| 15 | KPort::~KPort() = default; | ||
| 16 | |||
| 17 | void 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 | |||
| 33 | void KPort::OnClientClosed() { | ||
| 34 | KScopedSchedulerLock sl{kernel}; | ||
| 35 | |||
| 36 | if (state == State::Normal) { | ||
| 37 | state = State::ClientClosed; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | void KPort::OnServerClosed() { | ||
| 42 | KScopedSchedulerLock sl{kernel}; | ||
| 43 | |||
| 44 | if (state == State::Normal) { | ||
| 45 | state = State::ServerClosed; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | bool KPort::IsServerClosed() const { | ||
| 50 | KScopedSchedulerLock sl{kernel}; | ||
| 51 | return state == State::ServerClosed; | ||
| 52 | } | ||
| 53 | |||
| 54 | ResultCode 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 | |||
| 16 | namespace Kernel { | ||
| 17 | |||
| 18 | class KServerSession; | ||
| 19 | |||
| 20 | class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjectWithList> { | ||
| 21 | KERNEL_AUTOOBJECT_TRAITS(KPort, KAutoObject); | ||
| 22 | |||
| 23 | public: | ||
| 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 | |||
| 70 | private: | ||
| 71 | enum class State : u8 { | ||
| 72 | Invalid = 0, | ||
| 73 | Normal = 1, | ||
| 74 | ClientClosed = 2, | ||
| 75 | ServerClosed = 3, | ||
| 76 | }; | ||
| 77 | |||
| 78 | private: | ||
| 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 { | |||
| 16 | KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} | 18 | KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} |
| 17 | KServerPort::~KServerPort() = default; | 19 | KServerPort::~KServerPort() = default; |
| 18 | 20 | ||
| 19 | void KServerPort::Initialize(std::string&& name_) { | 21 | void 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 | ||
| 24 | ResultVal<KServerSession*> KServerPort::Accept() { | 27 | bool 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 | ||
| 34 | void KServerPort::AppendPendingSession(KServerSession* pending_session) { | 31 | void 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 | ||
| 41 | void KServerPort::Destroy() {} | 58 | void 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 | ||
| 43 | bool KServerPort::IsSignaled() const { | 69 | bool 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 | ||
| 47 | KServerPort::PortPair KServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions, | 78 | void 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"); | 90 | KServerSession* 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 | ||
| 16 | namespace Kernel { | 19 | namespace Kernel { |
| 17 | 20 | ||
| 18 | class KClientPort; | ||
| 19 | class KernelCore; | 21 | class KernelCore; |
| 20 | class KServerSession; | 22 | class KPort; |
| 21 | class SessionRequestHandler; | 23 | class SessionRequestHandler; |
| 22 | 24 | ||
| 23 | class KServerPort final : public KSynchronizationObject { | 25 | class KServerPort final : public KSynchronizationObject { |
| 24 | KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject); | 26 | KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject); |
| 25 | 27 | ||
| 28 | private: | ||
| 29 | using SessionList = boost::intrusive::list<KServerSession>; | ||
| 30 | |||
| 26 | public: | 31 | public: |
| 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 | ||
| 92 | private: | 85 | private: |
| 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) | 88 | private: |
| 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; | |||
| 31 | class SessionRequestHandler; | 33 | class SessionRequestHandler; |
| 32 | class KThread; | 34 | class KThread; |
| 33 | 35 | ||
| 34 | class KServerSession final : public KSynchronizationObject { | 36 | class 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} {} |
| 15 | KSession::~KSession() = default; | 16 | KSession::~KSession() = default; |
| 16 | 17 | ||
| 17 | void KSession::Initialize(std::string&& name_) { | 18 | void 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 | ||
| 44 | void KSession::Finalize() {} | 51 | void KSession::Finalize() { |
| 52 | if (port != nullptr) { | ||
| 53 | port->OnSessionFinalized(); | ||
| 54 | port->Close(); | ||
| 55 | } | ||
| 56 | } | ||
| 45 | 57 | ||
| 46 | void KSession::OnServerClosed() { | 58 | void 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; | |||
| 37 | class KEvent; | 37 | class KEvent; |
| 38 | class KLinkedListNode; | 38 | class KLinkedListNode; |
| 39 | class KMemoryManager; | 39 | class KMemoryManager; |
| 40 | class KPort; | ||
| 41 | class Process; | ||
| 40 | class KResourceLimit; | 42 | class KResourceLimit; |
| 41 | class KScheduler; | 43 | class KScheduler; |
| 42 | class KSession; | 44 | class KSession; |
| @@ -45,7 +47,6 @@ class KThread; | |||
| 45 | class KTransferMemory; | 47 | class KTransferMemory; |
| 46 | class KWritableEvent; | 48 | class KWritableEvent; |
| 47 | class PhysicalCore; | 49 | class PhysicalCore; |
| 48 | class Process; | ||
| 49 | class ServiceThread; | 50 | class ServiceThread; |
| 50 | class Synchronization; | 51 | class Synchronization; |
| 51 | class TimeManager; | 52 | class 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 |
| 294 | static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, | 294 | static 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. |
| 342 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | 346 | static 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}; | |||
| 36 | constexpr ResultCode ResultSessionClosed{ErrorModule::Kernel, 123}; | 36 | constexpr ResultCode ResultSessionClosed{ErrorModule::Kernel, 123}; |
| 37 | constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125}; | 37 | constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125}; |
| 38 | constexpr ResultCode ResultReservedUsed{ErrorModule::Kernel, 126}; | 38 | constexpr ResultCode ResultReservedUsed{ErrorModule::Kernel, 126}; |
| 39 | constexpr ResultCode ResultPortClosed{ErrorModule::Kernel, 131}; | ||
| 39 | constexpr ResultCode ResultLimitReached{ErrorModule::Kernel, 132}; | 40 | constexpr ResultCode ResultLimitReached{ErrorModule::Kernel, 132}; |
| 40 | constexpr ResultCode ResultInvalidId{ErrorModule::Kernel, 519}; | 41 | constexpr 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 | ||
| 71 | ResultCode ServiceManager::UnregisterService(const std::string& name) { | 71 | ResultCode 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 | ||
| 86 | ResultVal<Kernel::KClientPort*> ServiceManager::GetServicePort(const std::string& name) { | 86 | ResultVal<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 { | |||
| 24 | class KClientPort; | 22 | class KClientPort; |
| 25 | class KClientSession; | 23 | class KClientSession; |
| 26 | class KernelCore; | 24 | class KernelCore; |
| 25 | class KPort; | ||
| 27 | class KServerPort; | 26 | class KServerPort; |
| 28 | class SessionRequestHandler; | 27 | class 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; |