Browse Source
Kernel/IPC: Use Ports and Sessions as the fundamental building block of Inter Process Communication.
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.pull/15/merge
16 changed files with 314 additions and 88 deletions
-
6src/core/CMakeLists.txt
-
7src/core/hle/kernel/client_port.cpp
-
23src/core/hle/kernel/client_port.h
-
42src/core/hle/kernel/client_session.cpp
-
50src/core/hle/kernel/client_session.h
-
36src/core/hle/kernel/kernel.h
-
58src/core/hle/kernel/server_session.cpp
-
73src/core/hle/kernel/server_session.h
-
12src/core/hle/service/fs/archive.cpp
-
12src/core/hle/service/fs/archive.h
-
9src/core/hle/service/fs/fs_user.cpp
-
16src/core/hle/service/service.cpp
-
21src/core/hle/service/service.h
-
2src/core/hle/service/soc_u.cpp
-
17src/core/hle/service/srv.cpp
-
18src/core/hle/svc.cpp
@ -0,0 +1,42 @@ |
|||||
|
// Copyright 2016 Citra Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include "common/assert.h"
|
||||
|
|
||||
|
#include "core/hle/kernel/client_port.h"
|
||||
|
#include "core/hle/kernel/client_session.h"
|
||||
|
#include "core/hle/kernel/server_session.h"
|
||||
|
#include "core/hle/kernel/kernel.h"
|
||||
|
|
||||
|
namespace Kernel { |
||||
|
|
||||
|
ClientSession::ClientSession() {} |
||||
|
ClientSession::~ClientSession() {} |
||||
|
|
||||
|
ResultVal<SharedPtr<ClientSession>> ClientSession::Create(SharedPtr<ServerSession> server_session, SharedPtr<ClientPort> client_port, std::string name) { |
||||
|
SharedPtr<ClientSession> client_session(new ClientSession); |
||||
|
|
||||
|
client_session->name = std::move(name); |
||||
|
client_session->server_session = server_session; |
||||
|
client_session->client_port = client_port; |
||||
|
|
||||
|
return MakeResult<SharedPtr<ClientSession>>(std::move(client_session)); |
||||
|
} |
||||
|
|
||||
|
ResultCode ClientSession::HandleSyncRequest() { |
||||
|
// Signal the server session that new data is available
|
||||
|
ResultCode result = server_session->HandleSyncRequest(); |
||||
|
|
||||
|
if (result.IsError()) |
||||
|
return result; |
||||
|
|
||||
|
// Tell the client port to handle the request in case it's an HLE service.
|
||||
|
// The client port can be nullptr for port-less sessions (Like for example File and Directory sessions).
|
||||
|
if (client_port != nullptr) |
||||
|
result = client_port->HandleSyncRequest(); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
} // namespace
|
||||
@ -0,0 +1,50 @@ |
|||||
|
// Copyright 2016 Citra Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <string> |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
|
||||
|
#include "core/hle/kernel/kernel.h" |
||||
|
|
||||
|
namespace Kernel { |
||||
|
|
||||
|
class ClientPort; |
||||
|
class ServerSession; |
||||
|
|
||||
|
class ClientSession final : public Object { |
||||
|
public: |
||||
|
/** |
||||
|
* Creates a client session. |
||||
|
* @param server_session The server session associated with this client session |
||||
|
* @param client_port The client port which this session is connected to |
||||
|
* @param name Optional name of client session |
||||
|
* @return The created client session |
||||
|
*/ |
||||
|
static ResultVal<SharedPtr<ClientSession>> Create(SharedPtr<ServerSession> server_session, SharedPtr<ClientPort> client_port, std::string name = "Unknown"); |
||||
|
|
||||
|
std::string GetTypeName() const override { return "ClientSession"; } |
||||
|
std::string GetName() const override { return name; } |
||||
|
|
||||
|
static const HandleType HANDLE_TYPE = HandleType::ClientSession; |
||||
|
HandleType GetHandleType() const override { return HANDLE_TYPE; } |
||||
|
|
||||
|
/** |
||||
|
* Handle a SyncRequest from the emulated application. |
||||
|
* @return ResultCode of the operation. |
||||
|
*/ |
||||
|
ResultCode HandleSyncRequest(); |
||||
|
|
||||
|
std::string name; ///< Name of client port (optional) |
||||
|
SharedPtr<ServerSession> server_session; ///< The server session associated with this client session. |
||||
|
SharedPtr<ClientPort> client_port; ///< The client port which this session is connected to. |
||||
|
|
||||
|
private: |
||||
|
ClientSession(); |
||||
|
~ClientSession() override; |
||||
|
}; |
||||
|
|
||||
|
} // namespace |
||||
@ -0,0 +1,58 @@ |
|||||
|
// Copyright 2016 Citra Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include <tuple>
|
||||
|
|
||||
|
#include "core/hle/kernel/client_port.h"
|
||||
|
#include "core/hle/kernel/client_session.h"
|
||||
|
#include "core/hle/kernel/server_session.h"
|
||||
|
#include "core/hle/kernel/thread.h"
|
||||
|
|
||||
|
namespace Kernel { |
||||
|
|
||||
|
ServerSession::ServerSession() {} |
||||
|
ServerSession::~ServerSession() {} |
||||
|
|
||||
|
ResultVal<SharedPtr<ServerSession>> ServerSession::Create(std::string name) { |
||||
|
SharedPtr<ServerSession> server_session(new ServerSession); |
||||
|
|
||||
|
server_session->name = std::move(name); |
||||
|
server_session->signaled = false; |
||||
|
|
||||
|
return MakeResult<SharedPtr<ServerSession>>(std::move(server_session)); |
||||
|
} |
||||
|
|
||||
|
bool ServerSession::ShouldWait() { |
||||
|
return !signaled; |
||||
|
} |
||||
|
|
||||
|
void ServerSession::Acquire() { |
||||
|
ASSERT_MSG(!ShouldWait(), "object unavailable!"); |
||||
|
signaled = false; |
||||
|
} |
||||
|
|
||||
|
ResultCode ServerSession::HandleSyncRequest() { |
||||
|
// The ServerSession received a sync request, this means that there's new data available
|
||||
|
// from one of its ClientSessions, so wake up any threads that may be waiting on a svcReplyAndReceive or similar.
|
||||
|
signaled = true; |
||||
|
WakeupAllWaitingThreads(); |
||||
|
return RESULT_SUCCESS; |
||||
|
} |
||||
|
|
||||
|
SharedPtr<ClientSession> ServerSession::CreateClientSession() { |
||||
|
// In Citra, some types of ServerSessions (File and Directory sessions) are not created as a pair of Server-Client sessions,
|
||||
|
// but are instead created as a single ServerSession, which then hands over a ClientSession on demand (When opening the File or Directory).
|
||||
|
// The real kernel (Or more specifically, the real FS service) does create the pair of Sessions at the same time (via svcCreateSession), and simply
|
||||
|
// stores the ClientSession until it is needed.
|
||||
|
return ClientSession::Create(SharedPtr<ServerSession>(this), nullptr, name + "Client").MoveFrom(); |
||||
|
} |
||||
|
|
||||
|
std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> ServerSession::CreateSessionPair(SharedPtr<ClientPort> client_port, std::string name) { |
||||
|
auto server_session = ServerSession::Create(name + "Server").MoveFrom(); |
||||
|
auto client_session = ClientSession::Create(server_session, client_port, name + "Client").MoveFrom(); |
||||
|
|
||||
|
return std::make_tuple(server_session, client_session); |
||||
|
} |
||||
|
|
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue