diff options
| author | 2016-06-14 18:03:30 -0500 | |
|---|---|---|
| committer | 2016-11-30 23:02:05 -0500 | |
| commit | 073653e858abf377fd1ebbdb071809c8830ce99d (patch) | |
| tree | a29e1c1e50d53162ed89cd90e8c069525150392f /src | |
| parent | Merge pull request #2228 from freiro/winver_fix (diff) | |
| download | yuzu-073653e858abf377fd1ebbdb071809c8830ce99d.tar.gz yuzu-073653e858abf377fd1ebbdb071809c8830ce99d.tar.xz yuzu-073653e858abf377fd1ebbdb071809c8830ce99d.zip | |
Kernel/IPC: Use Ports and Sessions as the fundamental building block of Inter Process Communication.
All handles obtained via srv::GetServiceHandle or svcConnectToPort are references to ClientSessions.
Service modules will wait on the counterpart of those ClientSessions (Called ServerSessions) using svcReplyAndReceive or svcWaitSynchronization[1|N], and will be awoken when a SyncRequest is performed.
HLE Interfaces are now ClientPorts which override the HandleSyncRequest virtual member function to perform command handling immediately.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/client_port.cpp | 7 | ||||
| -rw-r--r-- | src/core/hle/kernel/client_port.h | 23 | ||||
| -rw-r--r-- | src/core/hle/kernel/client_session.cpp | 42 | ||||
| -rw-r--r-- | src/core/hle/kernel/client_session.h | 50 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 36 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.cpp | 58 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.h (renamed from src/core/hle/kernel/session.h) | 73 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.cpp | 12 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.h | 12 | ||||
| -rw-r--r-- | src/core/hle/service/fs/fs_user.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/service/service.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/service/service.h | 21 | ||||
| -rw-r--r-- | src/core/hle/service/soc_u.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/srv.cpp | 17 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 18 |
16 files changed, 314 insertions, 88 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 299f1f261..59260d2e8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -36,6 +36,7 @@ set(SRCS | |||
| 36 | hle/applets/swkbd.cpp | 36 | hle/applets/swkbd.cpp |
| 37 | hle/kernel/address_arbiter.cpp | 37 | hle/kernel/address_arbiter.cpp |
| 38 | hle/kernel/client_port.cpp | 38 | hle/kernel/client_port.cpp |
| 39 | hle/kernel/client_session.cpp | ||
| 39 | hle/kernel/event.cpp | 40 | hle/kernel/event.cpp |
| 40 | hle/kernel/kernel.cpp | 41 | hle/kernel/kernel.cpp |
| 41 | hle/kernel/memory.cpp | 42 | hle/kernel/memory.cpp |
| @@ -44,7 +45,7 @@ set(SRCS | |||
| 44 | hle/kernel/resource_limit.cpp | 45 | hle/kernel/resource_limit.cpp |
| 45 | hle/kernel/semaphore.cpp | 46 | hle/kernel/semaphore.cpp |
| 46 | hle/kernel/server_port.cpp | 47 | hle/kernel/server_port.cpp |
| 47 | hle/kernel/session.cpp | 48 | hle/kernel/server_session.cpp |
| 48 | hle/kernel/shared_memory.cpp | 49 | hle/kernel/shared_memory.cpp |
| 49 | hle/kernel/thread.cpp | 50 | hle/kernel/thread.cpp |
| 50 | hle/kernel/timer.cpp | 51 | hle/kernel/timer.cpp |
| @@ -184,6 +185,7 @@ set(HEADERS | |||
| 184 | hle/applets/swkbd.h | 185 | hle/applets/swkbd.h |
| 185 | hle/kernel/address_arbiter.h | 186 | hle/kernel/address_arbiter.h |
| 186 | hle/kernel/client_port.h | 187 | hle/kernel/client_port.h |
| 188 | hle/kernel/client_session.h | ||
| 187 | hle/kernel/event.h | 189 | hle/kernel/event.h |
| 188 | hle/kernel/kernel.h | 190 | hle/kernel/kernel.h |
| 189 | hle/kernel/memory.h | 191 | hle/kernel/memory.h |
| @@ -192,7 +194,7 @@ set(HEADERS | |||
| 192 | hle/kernel/resource_limit.h | 194 | hle/kernel/resource_limit.h |
| 193 | hle/kernel/semaphore.h | 195 | hle/kernel/semaphore.h |
| 194 | hle/kernel/server_port.h | 196 | hle/kernel/server_port.h |
| 195 | hle/kernel/session.h | 197 | hle/kernel/server_session.h |
| 196 | hle/kernel/shared_memory.h | 198 | hle/kernel/shared_memory.h |
| 197 | hle/kernel/thread.h | 199 | hle/kernel/thread.h |
| 198 | hle/kernel/timer.h | 200 | hle/kernel/timer.h |
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index aedc6f989..5ee7679eb 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp | |||
| @@ -6,10 +6,17 @@ | |||
| 6 | #include "core/hle/kernel/client_port.h" | 6 | #include "core/hle/kernel/client_port.h" |
| 7 | #include "core/hle/kernel/kernel.h" | 7 | #include "core/hle/kernel/kernel.h" |
| 8 | #include "core/hle/kernel/server_port.h" | 8 | #include "core/hle/kernel/server_port.h" |
| 9 | #include "core/hle/kernel/server_session.h" | ||
| 9 | 10 | ||
| 10 | namespace Kernel { | 11 | namespace Kernel { |
| 11 | 12 | ||
| 12 | ClientPort::ClientPort() {} | 13 | ClientPort::ClientPort() {} |
| 13 | ClientPort::~ClientPort() {} | 14 | ClientPort::~ClientPort() {} |
| 14 | 15 | ||
| 16 | void ClientPort::AddWaitingSession(SharedPtr<ServerSession> server_session) { | ||
| 17 | server_port->pending_sessions.push_back(server_session); | ||
| 18 | // Wake the threads waiting on the ServerPort | ||
| 19 | server_port->WakeupAllWaitingThreads(); | ||
| 20 | } | ||
| 21 | |||
| 15 | } // namespace | 22 | } // namespace |
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index d28147718..eb0882870 100644 --- a/src/core/hle/kernel/client_port.h +++ b/src/core/hle/kernel/client_port.h | |||
| @@ -11,16 +11,27 @@ | |||
| 11 | namespace Kernel { | 11 | namespace Kernel { |
| 12 | 12 | ||
| 13 | class ServerPort; | 13 | class ServerPort; |
| 14 | class ServerSession; | ||
| 14 | 15 | ||
| 15 | class ClientPort : public Object { | 16 | class ClientPort : public Object { |
| 16 | public: | 17 | public: |
| 17 | friend class ServerPort; | 18 | friend class ServerPort; |
| 18 | std::string GetTypeName() const override { | 19 | |
| 19 | return "ClientPort"; | 20 | /** |
| 20 | } | 21 | * Adds the specified server session to the queue of pending sessions of the associated ServerPort |
| 21 | std::string GetName() const override { | 22 | * @param server_session Server session to add to the queue |
| 22 | return name; | 23 | */ |
| 23 | } | 24 | virtual void AddWaitingSession(SharedPtr<ServerSession> server_session); |
| 25 | |||
| 26 | /** | ||
| 27 | * Handle a sync request from the emulated application. | ||
| 28 | * Only HLE services should override this function. | ||
| 29 | * @returns ResultCode from the operation. | ||
| 30 | */ | ||
| 31 | virtual ResultCode HandleSyncRequest() { return RESULT_SUCCESS; } | ||
| 32 | |||
| 33 | std::string GetTypeName() const override { return "ClientPort"; } | ||
| 34 | std::string GetName() const override { return name; } | ||
| 24 | 35 | ||
| 25 | static const HandleType HANDLE_TYPE = HandleType::ClientPort; | 36 | static const HandleType HANDLE_TYPE = HandleType::ClientPort; |
| 26 | HandleType GetHandleType() const override { | 37 | HandleType GetHandleType() const override { |
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp new file mode 100644 index 000000000..f1ad9b65b --- /dev/null +++ b/src/core/hle/kernel/client_session.cpp | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | |||
| 7 | #include "core/hle/kernel/client_port.h" | ||
| 8 | #include "core/hle/kernel/client_session.h" | ||
| 9 | #include "core/hle/kernel/server_session.h" | ||
| 10 | #include "core/hle/kernel/kernel.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | |||
| 14 | ClientSession::ClientSession() {} | ||
| 15 | ClientSession::~ClientSession() {} | ||
| 16 | |||
| 17 | ResultVal<SharedPtr<ClientSession>> ClientSession::Create(SharedPtr<ServerSession> server_session, SharedPtr<ClientPort> client_port, std::string name) { | ||
| 18 | SharedPtr<ClientSession> client_session(new ClientSession); | ||
| 19 | |||
| 20 | client_session->name = std::move(name); | ||
| 21 | client_session->server_session = server_session; | ||
| 22 | client_session->client_port = client_port; | ||
| 23 | |||
| 24 | return MakeResult<SharedPtr<ClientSession>>(std::move(client_session)); | ||
| 25 | } | ||
| 26 | |||
| 27 | ResultCode ClientSession::HandleSyncRequest() { | ||
| 28 | // Signal the server session that new data is available | ||
| 29 | ResultCode result = server_session->HandleSyncRequest(); | ||
| 30 | |||
| 31 | if (result.IsError()) | ||
| 32 | return result; | ||
| 33 | |||
| 34 | // Tell the client port to handle the request in case it's an HLE service. | ||
| 35 | // The client port can be nullptr for port-less sessions (Like for example File and Directory sessions). | ||
| 36 | if (client_port != nullptr) | ||
| 37 | result = client_port->HandleSyncRequest(); | ||
| 38 | |||
| 39 | return result; | ||
| 40 | } | ||
| 41 | |||
| 42 | } // namespace | ||
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h new file mode 100644 index 000000000..4fe9b4517 --- /dev/null +++ b/src/core/hle/kernel/client_session.h | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | // Copyright 2016 Citra 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 <string> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | #include "core/hle/kernel/kernel.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | class ClientPort; | ||
| 16 | class ServerSession; | ||
| 17 | |||
| 18 | class ClientSession final : public Object { | ||
| 19 | public: | ||
| 20 | /** | ||
| 21 | * Creates a client session. | ||
| 22 | * @param server_session The server session associated with this client session | ||
| 23 | * @param client_port The client port which this session is connected to | ||
| 24 | * @param name Optional name of client session | ||
| 25 | * @return The created client session | ||
| 26 | */ | ||
| 27 | static ResultVal<SharedPtr<ClientSession>> Create(SharedPtr<ServerSession> server_session, SharedPtr<ClientPort> client_port, std::string name = "Unknown"); | ||
| 28 | |||
| 29 | std::string GetTypeName() const override { return "ClientSession"; } | ||
| 30 | std::string GetName() const override { return name; } | ||
| 31 | |||
| 32 | static const HandleType HANDLE_TYPE = HandleType::ClientSession; | ||
| 33 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | ||
| 34 | |||
| 35 | /** | ||
| 36 | * Handle a SyncRequest from the emulated application. | ||
| 37 | * @return ResultCode of the operation. | ||
| 38 | */ | ||
| 39 | ResultCode HandleSyncRequest(); | ||
| 40 | |||
| 41 | std::string name; ///< Name of client port (optional) | ||
| 42 | SharedPtr<ServerSession> server_session; ///< The server session associated with this client session. | ||
| 43 | SharedPtr<ClientPort> client_port; ///< The client port which this session is connected to. | ||
| 44 | |||
| 45 | private: | ||
| 46 | ClientSession(); | ||
| 47 | ~ClientSession() override; | ||
| 48 | }; | ||
| 49 | |||
| 50 | } // namespace | ||
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 231cf7b75..c11c14b7d 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -31,22 +31,24 @@ enum KernelHandle : Handle { | |||
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | enum class HandleType : u32 { | 33 | enum class HandleType : u32 { |
| 34 | Unknown = 0, | 34 | Unknown = 0, |
| 35 | 35 | ||
| 36 | Session = 2, | 36 | |
| 37 | Event = 3, | 37 | Event = 3, |
| 38 | Mutex = 4, | 38 | Mutex = 4, |
| 39 | SharedMemory = 5, | 39 | SharedMemory = 5, |
| 40 | Redirection = 6, | 40 | Redirection = 6, |
| 41 | Thread = 7, | 41 | Thread = 7, |
| 42 | Process = 8, | 42 | Process = 8, |
| 43 | AddressArbiter = 9, | 43 | AddressArbiter = 9, |
| 44 | Semaphore = 10, | 44 | Semaphore = 10, |
| 45 | Timer = 11, | 45 | Timer = 11, |
| 46 | ResourceLimit = 12, | 46 | ResourceLimit = 12, |
| 47 | CodeSet = 13, | 47 | CodeSet = 13, |
| 48 | ClientPort = 14, | 48 | ClientPort = 14, |
| 49 | ServerPort = 15, | 49 | ServerPort = 15, |
| 50 | ClientSession = 16, | ||
| 51 | ServerSession = 17, | ||
| 50 | }; | 52 | }; |
| 51 | 53 | ||
| 52 | enum { | 54 | enum { |
| @@ -82,7 +84,7 @@ public: | |||
| 82 | */ | 84 | */ |
| 83 | bool IsWaitable() const { | 85 | bool IsWaitable() const { |
| 84 | switch (GetHandleType()) { | 86 | switch (GetHandleType()) { |
| 85 | case HandleType::Session: | 87 | case HandleType::ServerSession: |
| 86 | case HandleType::ServerPort: | 88 | case HandleType::ServerPort: |
| 87 | case HandleType::Event: | 89 | case HandleType::Event: |
| 88 | case HandleType::Mutex: | 90 | case HandleType::Mutex: |
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp new file mode 100644 index 000000000..9f5350ce5 --- /dev/null +++ b/src/core/hle/kernel/server_session.cpp | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <tuple> | ||
| 6 | |||
| 7 | #include "core/hle/kernel/client_port.h" | ||
| 8 | #include "core/hle/kernel/client_session.h" | ||
| 9 | #include "core/hle/kernel/server_session.h" | ||
| 10 | #include "core/hle/kernel/thread.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | |||
| 14 | ServerSession::ServerSession() {} | ||
| 15 | ServerSession::~ServerSession() {} | ||
| 16 | |||
| 17 | ResultVal<SharedPtr<ServerSession>> ServerSession::Create(std::string name) { | ||
| 18 | SharedPtr<ServerSession> server_session(new ServerSession); | ||
| 19 | |||
| 20 | server_session->name = std::move(name); | ||
| 21 | server_session->signaled = false; | ||
| 22 | |||
| 23 | return MakeResult<SharedPtr<ServerSession>>(std::move(server_session)); | ||
| 24 | } | ||
| 25 | |||
| 26 | bool ServerSession::ShouldWait() { | ||
| 27 | return !signaled; | ||
| 28 | } | ||
| 29 | |||
| 30 | void ServerSession::Acquire() { | ||
| 31 | ASSERT_MSG(!ShouldWait(), "object unavailable!"); | ||
| 32 | signaled = false; | ||
| 33 | } | ||
| 34 | |||
| 35 | ResultCode ServerSession::HandleSyncRequest() { | ||
| 36 | // The ServerSession received a sync request, this means that there's new data available | ||
| 37 | // from one of its ClientSessions, so wake up any threads that may be waiting on a svcReplyAndReceive or similar. | ||
| 38 | signaled = true; | ||
| 39 | WakeupAllWaitingThreads(); | ||
| 40 | return RESULT_SUCCESS; | ||
| 41 | } | ||
| 42 | |||
| 43 | SharedPtr<ClientSession> ServerSession::CreateClientSession() { | ||
| 44 | // In Citra, some types of ServerSessions (File and Directory sessions) are not created as a pair of Server-Client sessions, | ||
| 45 | // but are instead created as a single ServerSession, which then hands over a ClientSession on demand (When opening the File or Directory). | ||
| 46 | // The real kernel (Or more specifically, the real FS service) does create the pair of Sessions at the same time (via svcCreateSession), and simply | ||
| 47 | // stores the ClientSession until it is needed. | ||
| 48 | return ClientSession::Create(SharedPtr<ServerSession>(this), nullptr, name + "Client").MoveFrom(); | ||
| 49 | } | ||
| 50 | |||
| 51 | std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> ServerSession::CreateSessionPair(SharedPtr<ClientPort> client_port, std::string name) { | ||
| 52 | auto server_session = ServerSession::Create(name + "Server").MoveFrom(); | ||
| 53 | auto client_session = ClientSession::Create(server_session, client_port, name + "Client").MoveFrom(); | ||
| 54 | |||
| 55 | return std::make_tuple(server_session, client_session); | ||
| 56 | } | ||
| 57 | |||
| 58 | } | ||
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/server_session.h index ec025f732..eab9fe211 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/server_session.h | |||
| @@ -162,57 +162,64 @@ inline u32* GetCommandBuffer(const int offset = 0) { | |||
| 162 | offset); | 162 | offset); |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | class ClientSession; | ||
| 166 | class ClientPort; | ||
| 167 | |||
| 165 | /** | 168 | /** |
| 166 | * Kernel object representing the client endpoint of an IPC session. Sessions are the basic CTR-OS | 169 | * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS |
| 167 | * primitive for communication between different processes, and are used to implement service calls | 170 | * primitive for communication between different processes, and are used to implement service calls |
| 168 | * to the various system services. | 171 | * to the various system services. |
| 169 | * | 172 | * |
| 170 | * To make a service call, the client must write the command header and parameters to the buffer | 173 | * To make a service call, the client must write the command header and parameters to the buffer |
| 171 | * located at offset 0x80 of the TLS (Thread-Local Storage) area, then execute a SendSyncRequest | 174 | * located at offset 0x80 of the TLS (Thread-Local Storage) area, then execute a SendSyncRequest |
| 172 | * SVC call with its Session handle. The kernel will read the command header, using it to marshall | 175 | * SVC call with its ClientSession handle. The kernel will read the command header, using it to marshall |
| 173 | * the parameters to the process at the server endpoint of the session. After the server replies to | 176 | * the parameters to the process at the server endpoint of the session. After the server replies to |
| 174 | * the request, the response is marshalled back to the caller's TLS buffer and control is | 177 | * the request, the response is marshalled back to the caller's TLS buffer and control is |
| 175 | * transferred back to it. | 178 | * transferred back to it. |
| 176 | * | ||
| 177 | * In Citra, only the client endpoint is currently implemented and only HLE calls, where the IPC | ||
| 178 | * request is answered by C++ code in the emulator, are supported. When SendSyncRequest is called | ||
| 179 | * with the session handle, this class's SyncRequest method is called, which should read the TLS | ||
| 180 | * buffer and emulate the call accordingly. Since the code can directly read the emulated memory, | ||
| 181 | * no parameter marshalling is done. | ||
| 182 | * | ||
| 183 | * In the long term, this should be turned into the full-fledged IPC mechanism implemented by | ||
| 184 | * CTR-OS so that IPC calls can be optionally handled by the real implementations of processes, as | ||
| 185 | * opposed to HLE simulations. | ||
| 186 | */ | 179 | */ |
| 187 | class Session : public WaitObject { | 180 | class ServerSession : public WaitObject { |
| 188 | public: | 181 | public: |
| 189 | Session(); | 182 | ServerSession(); |
| 190 | ~Session() override; | 183 | ~ServerSession() override; |
| 184 | |||
| 185 | /** | ||
| 186 | * Creates a server session. | ||
| 187 | * @param name Optional name of the server session | ||
| 188 | * @return The created server session | ||
| 189 | */ | ||
| 190 | static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown"); | ||
| 191 | 191 | ||
| 192 | std::string GetTypeName() const override { | 192 | std::string GetTypeName() const override { return "ServerSession"; } |
| 193 | return "Session"; | ||
| 194 | } | ||
| 195 | 193 | ||
| 196 | static const HandleType HANDLE_TYPE = HandleType::Session; | 194 | static const HandleType HANDLE_TYPE = HandleType::ServerSession; |
| 197 | HandleType GetHandleType() const override { | 195 | HandleType GetHandleType() const override { return HANDLE_TYPE; } |
| 198 | return HANDLE_TYPE; | 196 | |
| 199 | } | 197 | /** |
| 198 | * Creates a pair of ServerSession and an associated ClientSession. | ||
| 199 | * @param client_port ClientPort to which the sessions are connected | ||
| 200 | * @param name Optional name of the ports | ||
| 201 | * @return The created session tuple | ||
| 202 | */ | ||
| 203 | static std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> CreateSessionPair(SharedPtr<ClientPort> client_port, std::string name = "Unknown"); | ||
| 204 | |||
| 205 | /** | ||
| 206 | * Creates a portless ClientSession and associates it with this ServerSession. | ||
| 207 | * @returns ClientSession The newly created ClientSession. | ||
| 208 | */ | ||
| 209 | SharedPtr<ClientSession> CreateClientSession(); | ||
| 200 | 210 | ||
| 201 | /** | 211 | /** |
| 202 | * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls | 212 | * Handle a sync request from the emulated application. |
| 203 | * aren't supported yet. | 213 | * Only HLE services should override this function. |
| 214 | * @returns ResultCode from the operation. | ||
| 204 | */ | 215 | */ |
| 205 | virtual ResultVal<bool> SyncRequest() = 0; | 216 | virtual ResultCode HandleSyncRequest(); |
| 206 | 217 | ||
| 207 | // TODO(bunnei): These functions exist to satisfy a hardware test with a Session object | 218 | bool ShouldWait() override; |
| 208 | // passed into WaitSynchronization. Figure out the meaning of them. | ||
| 209 | 219 | ||
| 210 | bool ShouldWait() override { | 220 | void Acquire() override; |
| 211 | return true; | ||
| 212 | } | ||
| 213 | 221 | ||
| 214 | void Acquire() override { | 222 | std::string name; ///< The name of this session (optional) |
| 215 | ASSERT_MSG(!ShouldWait(), "object unavailable!"); | 223 | bool signaled; ///< Whether there's new data available to this ServerSession |
| 216 | } | ||
| 217 | }; | 224 | }; |
| 218 | } | 225 | } |
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 4c29784e8..da009df91 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp | |||
| @@ -92,7 +92,7 @@ File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& | |||
| 92 | 92 | ||
| 93 | File::~File() {} | 93 | File::~File() {} |
| 94 | 94 | ||
| 95 | ResultVal<bool> File::SyncRequest() { | 95 | ResultCode File::HandleSyncRequest() { |
| 96 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 96 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 97 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | 97 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); |
| 98 | switch (cmd) { | 98 | switch (cmd) { |
| @@ -193,10 +193,10 @@ ResultVal<bool> File::SyncRequest() { | |||
| 193 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); | 193 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); |
| 194 | ResultCode error = UnimplementedFunction(ErrorModule::FS); | 194 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 195 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. | 195 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 196 | return error; | 196 | return ServerSession::HandleSyncRequest(); |
| 197 | } | 197 | } |
| 198 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 198 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 199 | return MakeResult<bool>(false); | 199 | return ServerSession::HandleSyncRequest(); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, | 202 | Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, |
| @@ -205,7 +205,7 @@ Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, | |||
| 205 | 205 | ||
| 206 | Directory::~Directory() {} | 206 | Directory::~Directory() {} |
| 207 | 207 | ||
| 208 | ResultVal<bool> Directory::SyncRequest() { | 208 | ResultCode Directory::HandleSyncRequest() { |
| 209 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 209 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 210 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); | 210 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); |
| 211 | switch (cmd) { | 211 | switch (cmd) { |
| @@ -236,10 +236,10 @@ ResultVal<bool> Directory::SyncRequest() { | |||
| 236 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); | 236 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); |
| 237 | ResultCode error = UnimplementedFunction(ErrorModule::FS); | 237 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 238 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. | 238 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 239 | return MakeResult<bool>(false); | 239 | return ServerSession::HandleSyncRequest(); |
| 240 | } | 240 | } |
| 241 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 241 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 242 | return MakeResult<bool>(false); | 242 | return ServerSession::HandleSyncRequest(); |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 245 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 21ed9717b..22e659c40 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "core/file_sys/archive_backend.h" | 10 | #include "core/file_sys/archive_backend.h" |
| 11 | #include "core/hle/kernel/session.h" | 11 | #include "core/hle/kernel/server_session.h" |
| 12 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 13 | 13 | ||
| 14 | namespace FileSys { | 14 | namespace FileSys { |
| @@ -41,7 +41,7 @@ enum class MediaType : u32 { NAND = 0, SDMC = 1 }; | |||
| 41 | 41 | ||
| 42 | typedef u64 ArchiveHandle; | 42 | typedef u64 ArchiveHandle; |
| 43 | 43 | ||
| 44 | class File : public Kernel::Session { | 44 | class File : public Kernel::ServerSession { |
| 45 | public: | 45 | public: |
| 46 | File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path); | 46 | File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path); |
| 47 | ~File(); | 47 | ~File(); |
| @@ -49,14 +49,15 @@ public: | |||
| 49 | std::string GetName() const override { | 49 | std::string GetName() const override { |
| 50 | return "Path: " + path.DebugStr(); | 50 | return "Path: " + path.DebugStr(); |
| 51 | } | 51 | } |
| 52 | ResultVal<bool> SyncRequest() override; | 52 | |
| 53 | ResultCode HandleSyncRequest() override; | ||
| 53 | 54 | ||
| 54 | FileSys::Path path; ///< Path of the file | 55 | FileSys::Path path; ///< Path of the file |
| 55 | u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means | 56 | u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means |
| 56 | std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface | 57 | std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface |
| 57 | }; | 58 | }; |
| 58 | 59 | ||
| 59 | class Directory : public Kernel::Session { | 60 | class Directory : public Kernel::ServerSession { |
| 60 | public: | 61 | public: |
| 61 | Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path); | 62 | Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path); |
| 62 | ~Directory(); | 63 | ~Directory(); |
| @@ -64,7 +65,8 @@ public: | |||
| 64 | std::string GetName() const override { | 65 | std::string GetName() const override { |
| 65 | return "Directory: " + path.DebugStr(); | 66 | return "Directory: " + path.DebugStr(); |
| 66 | } | 67 | } |
| 67 | ResultVal<bool> SyncRequest() override; | 68 | |
| 69 | ResultCode HandleSyncRequest() override; | ||
| 68 | 70 | ||
| 69 | FileSys::Path path; ///< Path of the directory | 71 | FileSys::Path path; ///< Path of the directory |
| 70 | std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface | 72 | std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface |
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 9ec17b395..bb78091f9 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "common/scope_exit.h" | 9 | #include "common/scope_exit.h" |
| 10 | #include "common/string_util.h" | 10 | #include "common/string_util.h" |
| 11 | #include "core/hle/kernel/client_session.h" | ||
| 11 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 12 | #include "core/hle/service/fs/archive.h" | 13 | #include "core/hle/service/fs/archive.h" |
| 13 | #include "core/hle/service/fs/fs_user.h" | 14 | #include "core/hle/service/fs/fs_user.h" |
| @@ -17,7 +18,7 @@ | |||
| 17 | // Namespace FS_User | 18 | // Namespace FS_User |
| 18 | 19 | ||
| 19 | using Kernel::SharedPtr; | 20 | using Kernel::SharedPtr; |
| 20 | using Kernel::Session; | 21 | using Kernel::ServerSession; |
| 21 | 22 | ||
| 22 | namespace Service { | 23 | namespace Service { |
| 23 | namespace FS { | 24 | namespace FS { |
| @@ -70,7 +71,7 @@ static void OpenFile(Service::Interface* self) { | |||
| 70 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); | 71 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); |
| 71 | cmd_buff[1] = file_res.Code().raw; | 72 | cmd_buff[1] = file_res.Code().raw; |
| 72 | if (file_res.Succeeded()) { | 73 | if (file_res.Succeeded()) { |
| 73 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); | 74 | cmd_buff[3] = Kernel::g_handle_table.Create((*file_res)->CreateClientSession()).MoveFrom(); |
| 74 | } else { | 75 | } else { |
| 75 | cmd_buff[3] = 0; | 76 | cmd_buff[3] = 0; |
| 76 | LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); | 77 | LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); |
| @@ -130,7 +131,7 @@ static void OpenFileDirectly(Service::Interface* self) { | |||
| 130 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); | 131 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); |
| 131 | cmd_buff[1] = file_res.Code().raw; | 132 | cmd_buff[1] = file_res.Code().raw; |
| 132 | if (file_res.Succeeded()) { | 133 | if (file_res.Succeeded()) { |
| 133 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); | 134 | cmd_buff[3] = Kernel::g_handle_table.Create((*file_res)->CreateClientSession()).MoveFrom(); |
| 134 | } else { | 135 | } else { |
| 135 | cmd_buff[3] = 0; | 136 | cmd_buff[3] = 0; |
| 136 | LOG_ERROR(Service_FS, "failed to get a handle for file %s mode=%u attributes=%u", | 137 | LOG_ERROR(Service_FS, "failed to get a handle for file %s mode=%u attributes=%u", |
| @@ -391,7 +392,7 @@ static void OpenDirectory(Service::Interface* self) { | |||
| 391 | ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); | 392 | ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); |
| 392 | cmd_buff[1] = dir_res.Code().raw; | 393 | cmd_buff[1] = dir_res.Code().raw; |
| 393 | if (dir_res.Succeeded()) { | 394 | if (dir_res.Succeeded()) { |
| 394 | cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom(); | 395 | cmd_buff[3] = Kernel::g_handle_table.Create((*dir_res)->CreateClientSession()).MoveFrom(); |
| 395 | } else { | 396 | } else { |
| 396 | LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s", | 397 | LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s", |
| 397 | dirname_type, dirname_size, dir_path.DebugStr().c_str()); | 398 | dirname_type, dirname_size, dir_path.DebugStr().c_str()); |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index ca7eeac8a..f51a042ff 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -41,8 +41,8 @@ | |||
| 41 | 41 | ||
| 42 | namespace Service { | 42 | namespace Service { |
| 43 | 43 | ||
| 44 | std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports; | 44 | std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_kernel_named_ports; |
| 45 | std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; | 45 | std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_srv_services; |
| 46 | 46 | ||
| 47 | /** | 47 | /** |
| 48 | * Creates a function string for logging, complete with the name (or header code, depending | 48 | * Creates a function string for logging, complete with the name (or header code, depending |
| @@ -61,7 +61,7 @@ static std::string MakeFunctionString(const char* name, const char* port_name, | |||
| 61 | return function_string; | 61 | return function_string; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | ResultVal<bool> Interface::SyncRequest() { | 64 | ResultCode Interface::HandleSyncRequest() { |
| 65 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 65 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 66 | auto itr = m_functions.find(cmd_buff[0]); | 66 | auto itr = m_functions.find(cmd_buff[0]); |
| 67 | 67 | ||
| @@ -75,14 +75,14 @@ ResultVal<bool> Interface::SyncRequest() { | |||
| 75 | 75 | ||
| 76 | // TODO(bunnei): Hack - ignore error | 76 | // TODO(bunnei): Hack - ignore error |
| 77 | cmd_buff[1] = 0; | 77 | cmd_buff[1] = 0; |
| 78 | return MakeResult<bool>(false); | 78 | return RESULT_SUCCESS; |
| 79 | } | 79 | } |
| 80 | LOG_TRACE(Service, "%s", | 80 | LOG_TRACE(Service, "%s", |
| 81 | MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); | 81 | MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); |
| 82 | 82 | ||
| 83 | itr->second.func(this); | 83 | itr->second.func(this); |
| 84 | 84 | ||
| 85 | return MakeResult<bool>(false); // TODO: Implement return from actual function | 85 | return RESULT_SUCCESS; // TODO: Implement return from actual function, it should fail if the parameter translation fails |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | void Interface::Register(const FunctionInfo* functions, size_t n) { | 88 | void Interface::Register(const FunctionInfo* functions, size_t n) { |
| @@ -97,10 +97,16 @@ void Interface::Register(const FunctionInfo* functions, size_t n) { | |||
| 97 | // Module interface | 97 | // Module interface |
| 98 | 98 | ||
| 99 | static void AddNamedPort(Interface* interface_) { | 99 | static void AddNamedPort(Interface* interface_) { |
| 100 | interface_->name = interface_->GetPortName(); | ||
| 101 | interface_->active_sessions = 0; | ||
| 102 | interface_->max_sessions = interface_->GetMaxSessions(); | ||
| 100 | g_kernel_named_ports.emplace(interface_->GetPortName(), interface_); | 103 | g_kernel_named_ports.emplace(interface_->GetPortName(), interface_); |
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | void AddService(Interface* interface_) { | 106 | void AddService(Interface* interface_) { |
| 107 | interface_->name = interface_->GetPortName(); | ||
| 108 | interface_->active_sessions = 0; | ||
| 109 | interface_->max_sessions = interface_->GetMaxSessions(); | ||
| 104 | g_srv_services.emplace(interface_->GetPortName(), interface_); | 110 | g_srv_services.emplace(interface_->GetPortName(), interface_); |
| 105 | } | 111 | } |
| 106 | 112 | ||
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 29daacfc4..fd15ad03f 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -9,7 +9,8 @@ | |||
| 9 | #include <unordered_map> | 9 | #include <unordered_map> |
| 10 | #include <boost/container/flat_map.hpp> | 10 | #include <boost/container/flat_map.hpp> |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "core/hle/kernel/session.h" | 12 | #include "core/hle/kernel/client_port.h" |
| 13 | #include "core/hle/kernel/server_session.h" | ||
| 13 | #include "core/hle/result.h" | 14 | #include "core/hle/result.h" |
| 14 | 15 | ||
| 15 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -18,9 +19,10 @@ | |||
| 18 | namespace Service { | 19 | namespace Service { |
| 19 | 20 | ||
| 20 | static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) | 21 | static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) |
| 22 | static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE port | ||
| 21 | 23 | ||
| 22 | /// Interface to a CTROS service | 24 | /// Interface to a CTROS service |
| 23 | class Interface : public Kernel::Session { | 25 | class Interface : public Kernel::ClientPort { |
| 24 | // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be | 26 | // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be |
| 25 | // just something that encapsulates a session and acts as a helper to implement service | 27 | // just something that encapsulates a session and acts as a helper to implement service |
| 26 | // processes. | 28 | // processes. |
| @@ -33,6 +35,15 @@ public: | |||
| 33 | version.raw = raw_version; | 35 | version.raw = raw_version; |
| 34 | } | 36 | } |
| 35 | 37 | ||
| 38 | /** | ||
| 39 | * Gets the maximum allowed number of sessions that can be connected to this port at the same time. | ||
| 40 | * It should be overwritten by each service implementation for more fine-grained control. | ||
| 41 | * @returns The maximum number of connections allowed. | ||
| 42 | */ | ||
| 43 | virtual u32 GetMaxSessions() { return DefaultMaxSessions; } | ||
| 44 | |||
| 45 | void AddWaitingSession(Kernel::SharedPtr<Kernel::ServerSession> server_session) override { } | ||
| 46 | |||
| 36 | typedef void (*Function)(Interface*); | 47 | typedef void (*Function)(Interface*); |
| 37 | 48 | ||
| 38 | struct FunctionInfo { | 49 | struct FunctionInfo { |
| @@ -49,7 +60,7 @@ public: | |||
| 49 | return "[UNKNOWN SERVICE PORT]"; | 60 | return "[UNKNOWN SERVICE PORT]"; |
| 50 | } | 61 | } |
| 51 | 62 | ||
| 52 | ResultVal<bool> SyncRequest() override; | 63 | ResultCode HandleSyncRequest() override; |
| 53 | 64 | ||
| 54 | protected: | 65 | protected: |
| 55 | /** | 66 | /** |
| @@ -81,9 +92,9 @@ void Init(); | |||
| 81 | void Shutdown(); | 92 | void Shutdown(); |
| 82 | 93 | ||
| 83 | /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC. | 94 | /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC. |
| 84 | extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports; | 95 | extern std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_kernel_named_ports; |
| 85 | /// Map of services registered with the "srv:" service, retrieved using GetServiceHandle. | 96 | /// Map of services registered with the "srv:" service, retrieved using GetServiceHandle. |
| 86 | extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; | 97 | extern std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_srv_services; |
| 87 | 98 | ||
| 88 | /// Adds a service to the services table | 99 | /// Adds a service to the services table |
| 89 | void AddService(Interface* interface_); | 100 | void AddService(Interface* interface_); |
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index 46b75db25..2e8b2fc00 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/scope_exit.h" | 13 | #include "common/scope_exit.h" |
| 14 | #include "core/hle/kernel/session.h" | 14 | #include "core/hle/kernel/server_session.h" |
| 15 | #include "core/hle/result.h" | 15 | #include "core/hle/result.h" |
| 16 | #include "core/hle/service/soc_u.h" | 16 | #include "core/hle/service/soc_u.h" |
| 17 | #include "core/memory.h" | 17 | #include "core/memory.h" |
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index b25be413a..eb2e06041 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp | |||
| @@ -2,8 +2,12 @@ | |||
| 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> | ||
| 6 | |||
| 5 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 6 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/hle/service/srv.h" | ||
| 10 | #include "core/hle/kernel/client_session.h" | ||
| 7 | #include "core/hle/kernel/event.h" | 11 | #include "core/hle/kernel/event.h" |
| 8 | #include "core/hle/service/srv.h" | 12 | #include "core/hle/service/srv.h" |
| 9 | 13 | ||
| @@ -81,7 +85,18 @@ static void GetServiceHandle(Service::Interface* self) { | |||
| 81 | auto it = Service::g_srv_services.find(port_name); | 85 | auto it = Service::g_srv_services.find(port_name); |
| 82 | 86 | ||
| 83 | if (it != Service::g_srv_services.end()) { | 87 | if (it != Service::g_srv_services.end()) { |
| 84 | cmd_buff[3] = Kernel::g_handle_table.Create(it->second).MoveFrom(); | 88 | auto client_port = it->second; |
| 89 | |||
| 90 | // Create a new session pair | ||
| 91 | auto sessions = Kernel::ServerSession::CreateSessionPair(client_port, port_name); | ||
| 92 | auto client_session = std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions); | ||
| 93 | auto server_session = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions); | ||
| 94 | |||
| 95 | // Add the server session to the port's queue | ||
| 96 | client_port->AddWaitingSession(server_session); | ||
| 97 | |||
| 98 | // Return the client session | ||
| 99 | cmd_buff[3] = Kernel::g_handle_table.Create(client_session).MoveFrom(); | ||
| 85 | LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); | 100 | LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); |
| 86 | } else { | 101 | } else { |
| 87 | LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); | 102 | LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index c6b80dc50..be03e53bc 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "core/hle/function_wrappers.h" | 13 | #include "core/hle/function_wrappers.h" |
| 14 | #include "core/hle/kernel/address_arbiter.h" | 14 | #include "core/hle/kernel/address_arbiter.h" |
| 15 | #include "core/hle/kernel/client_port.h" | 15 | #include "core/hle/kernel/client_port.h" |
| 16 | #include "core/hle/kernel/client_session.h" | ||
| 16 | #include "core/hle/kernel/event.h" | 17 | #include "core/hle/kernel/event.h" |
| 17 | #include "core/hle/kernel/memory.h" | 18 | #include "core/hle/kernel/memory.h" |
| 18 | #include "core/hle/kernel/mutex.h" | 19 | #include "core/hle/kernel/mutex.h" |
| @@ -222,20 +223,31 @@ static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) { | |||
| 222 | return ERR_NOT_FOUND; | 223 | return ERR_NOT_FOUND; |
| 223 | } | 224 | } |
| 224 | 225 | ||
| 225 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(it->second)); | 226 | auto client_port = it->second; |
| 227 | |||
| 228 | // Create a new session pair | ||
| 229 | auto sessions = Kernel::ServerSession::CreateSessionPair(client_port, port_name); | ||
| 230 | auto client_session = std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions); | ||
| 231 | auto server_session = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions); | ||
| 232 | |||
| 233 | // Add the server session to the port's queue | ||
| 234 | client_port->AddWaitingSession(server_session); | ||
| 235 | |||
| 236 | // Return the client session | ||
| 237 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(client_session)); | ||
| 226 | return RESULT_SUCCESS; | 238 | return RESULT_SUCCESS; |
| 227 | } | 239 | } |
| 228 | 240 | ||
| 229 | /// Synchronize to an OS service | 241 | /// Synchronize to an OS service |
| 230 | static ResultCode SendSyncRequest(Handle handle) { | 242 | static ResultCode SendSyncRequest(Handle handle) { |
| 231 | SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle); | 243 | SharedPtr<Kernel::ClientSession> session = Kernel::g_handle_table.Get<Kernel::ClientSession>(handle); |
| 232 | if (session == nullptr) { | 244 | if (session == nullptr) { |
| 233 | return ERR_INVALID_HANDLE; | 245 | return ERR_INVALID_HANDLE; |
| 234 | } | 246 | } |
| 235 | 247 | ||
| 236 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); | 248 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); |
| 237 | 249 | ||
| 238 | return session->SyncRequest().Code(); | 250 | return session->HandleSyncRequest(); |
| 239 | } | 251 | } |
| 240 | 252 | ||
| 241 | /// Close a handle | 253 | /// Close a handle |