Browse Source
Merge pull request #2249 from Subv/sessions_v3
Merge pull request #2249 from Subv/sessions_v3
Kernel/IPC: Use Ports and Sessions as the fundamental building block of Inter Process Communication.nce_cpp
committed by
GitHub
25 changed files with 591 additions and 171 deletions
-
1src/citra_qt/debugger/wait_tree.cpp
-
7src/core/CMakeLists.txt
-
96src/core/hle/ipc.h
-
32src/core/hle/kernel/client_port.cpp
-
13src/core/hle/kernel/client_port.h
-
40src/core/hle/kernel/client_session.cpp
-
65src/core/hle/kernel/client_session.h
-
37src/core/hle/kernel/kernel.h
-
4src/core/hle/kernel/server_port.cpp
-
14src/core/hle/kernel/server_port.h
-
79src/core/hle/kernel/server_session.cpp
-
94src/core/hle/kernel/server_session.h
-
1src/core/hle/result.h
-
3src/core/hle/service/apt/apt.h
-
2src/core/hle/service/apt/apt_a.cpp
-
2src/core/hle/service/apt/apt_s.cpp
-
2src/core/hle/service/apt/apt_u.cpp
-
40src/core/hle/service/fs/archive.cpp
-
32src/core/hle/service/fs/archive.h
-
33src/core/hle/service/fs/fs_user.cpp
-
42src/core/hle/service/service.cpp
-
88src/core/hle/service/service.h
-
2src/core/hle/service/soc_u.cpp
-
14src/core/hle/service/srv.cpp
-
19src/core/hle/svc.cpp
@ -0,0 +1,40 @@ |
|||
// 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_session.h"
|
|||
#include "core/hle/kernel/server_session.h"
|
|||
|
|||
namespace Kernel { |
|||
|
|||
ClientSession::ClientSession() = default; |
|||
ClientSession::~ClientSession() { |
|||
// This destructor will be called automatically when the last ClientSession handle is closed by
|
|||
// the emulated application.
|
|||
|
|||
if (server_session->hle_handler) |
|||
server_session->hle_handler->ClientDisconnected(server_session); |
|||
|
|||
// TODO(Subv): If the session is still open, set the connection status to 2 (Closed by client),
|
|||
// wake up all the ServerSession's waiting threads and set the WaitSynchronization result to
|
|||
// 0xC920181A.
|
|||
} |
|||
|
|||
ResultVal<SharedPtr<ClientSession>> ClientSession::Create(ServerSession* server_session, |
|||
std::string name) { |
|||
SharedPtr<ClientSession> client_session(new ClientSession); |
|||
|
|||
client_session->name = std::move(name); |
|||
client_session->server_session = server_session; |
|||
client_session->session_status = SessionStatus::Open; |
|||
return MakeResult<SharedPtr<ClientSession>>(std::move(client_session)); |
|||
} |
|||
|
|||
ResultCode ClientSession::SendSyncRequest() { |
|||
// Signal the server session that new data is available
|
|||
return server_session->HandleSyncRequest(); |
|||
} |
|||
|
|||
} // namespace
|
|||
@ -0,0 +1,65 @@ |
|||
// Copyright 2016 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
#include <string> |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
#include "core/hle/kernel/kernel.h" |
|||
|
|||
namespace Kernel { |
|||
|
|||
class ServerSession; |
|||
|
|||
enum class SessionStatus { |
|||
Open = 1, |
|||
ClosedByClient = 2, |
|||
ClosedBYServer = 3, |
|||
}; |
|||
|
|||
class ClientSession final : public Object { |
|||
public: |
|||
friend class ServerSession; |
|||
|
|||
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; |
|||
} |
|||
|
|||
/** |
|||
* Sends an SyncRequest from the current emulated thread. |
|||
* @return ResultCode of the operation. |
|||
*/ |
|||
ResultCode SendSyncRequest(); |
|||
|
|||
std::string name; ///< Name of client port (optional) |
|||
ServerSession* server_session; ///< The server session associated with this client session. |
|||
SessionStatus session_status; ///< The session's current status. |
|||
|
|||
private: |
|||
ClientSession(); |
|||
~ClientSession() override; |
|||
|
|||
/** |
|||
* Creates a client session. |
|||
* @param server_session The server session associated with this client session |
|||
* @param name Optional name of client session |
|||
* @return The created client session |
|||
*/ |
|||
static ResultVal<SharedPtr<ClientSession>> Create(ServerSession* server_session, |
|||
std::string name = "Unknown"); |
|||
}; |
|||
|
|||
} // namespace |
|||
@ -0,0 +1,79 @@ |
|||
// 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_session.h"
|
|||
#include "core/hle/kernel/server_session.h"
|
|||
#include "core/hle/kernel/thread.h"
|
|||
|
|||
namespace Kernel { |
|||
|
|||
ServerSession::ServerSession() = default; |
|||
ServerSession::~ServerSession() { |
|||
// This destructor will be called automatically when the last ServerSession handle is closed by
|
|||
// the emulated application.
|
|||
// TODO(Subv): Reduce the ClientPort's connection count,
|
|||
// if the session is still open, set the connection status to 3 (Closed by server),
|
|||
} |
|||
|
|||
ResultVal<SharedPtr<ServerSession>> ServerSession::Create( |
|||
std::string name, std::shared_ptr<Service::SessionRequestHandler> hle_handler) { |
|||
SharedPtr<ServerSession> server_session(new ServerSession); |
|||
|
|||
server_session->name = std::move(name); |
|||
server_session->signaled = false; |
|||
server_session->hle_handler = std::move(hle_handler); |
|||
|
|||
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 its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or
|
|||
// similar.
|
|||
|
|||
// If this ServerSession has an associated HLE handler, forward the request to it.
|
|||
if (hle_handler != nullptr) { |
|||
// Attempt to translate the incoming request's command buffer.
|
|||
ResultCode result = TranslateHLERequest(this); |
|||
if (result.IsError()) |
|||
return result; |
|||
hle_handler->HandleSyncRequest(SharedPtr<ServerSession>(this)); |
|||
// TODO(Subv): Translate the response command buffer.
|
|||
} |
|||
|
|||
// If this ServerSession does not have an HLE implementation, just wake up the threads waiting
|
|||
// on it.
|
|||
signaled = true; |
|||
WakeupAllWaitingThreads(); |
|||
return RESULT_SUCCESS; |
|||
} |
|||
|
|||
ServerSession::SessionPair ServerSession::CreateSessionPair( |
|||
const std::string& name, std::shared_ptr<Service::SessionRequestHandler> hle_handler) { |
|||
auto server_session = |
|||
ServerSession::Create(name + "_Server", std::move(hle_handler)).MoveFrom(); |
|||
// We keep a non-owning pointer to the ServerSession in the ClientSession because we don't want
|
|||
// to prevent the ServerSession's destructor from being called when the emulated
|
|||
// application closes the last ServerSession handle.
|
|||
auto client_session = ClientSession::Create(server_session.get(), name + "_Client").MoveFrom(); |
|||
|
|||
return std::make_tuple(std::move(server_session), std::move(client_session)); |
|||
} |
|||
|
|||
ResultCode TranslateHLERequest(ServerSession* server_session) { |
|||
// TODO(Subv): Implement this function once multiple concurrent processes are supported.
|
|||
return RESULT_SUCCESS; |
|||
} |
|||
} |
|||
@ -0,0 +1,94 @@ |
|||
// Copyright 2014 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <string> |
|||
#include "common/assert.h" |
|||
#include "common/common_types.h" |
|||
#include "core/hle/kernel/kernel.h" |
|||
#include "core/hle/kernel/thread.h" |
|||
#include "core/hle/result.h" |
|||
#include "core/hle/service/service.h" |
|||
#include "core/memory.h" |
|||
|
|||
namespace Kernel { |
|||
|
|||
class ClientSession; |
|||
|
|||
/** |
|||
* Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS |
|||
* primitive for communication between different processes, and are used to implement service calls |
|||
* to the various system services. |
|||
* |
|||
* To make a service call, the client must write the command header and parameters to the buffer |
|||
* located at offset 0x80 of the TLS (Thread-Local Storage) area, then execute a SendSyncRequest |
|||
* SVC call with its ClientSession handle. The kernel will read the command header, using it to |
|||
* marshall the parameters to the process at the server endpoint of the session. |
|||
* After the server replies to the request, the response is marshalled back to the caller's |
|||
* TLS buffer and control is transferred back to it. |
|||
*/ |
|||
class ServerSession final : public WaitObject { |
|||
public: |
|||
std::string GetTypeName() const override { |
|||
return "ServerSession"; |
|||
} |
|||
|
|||
static const HandleType HANDLE_TYPE = HandleType::ServerSession; |
|||
HandleType GetHandleType() const override { |
|||
return HANDLE_TYPE; |
|||
} |
|||
|
|||
using SessionPair = std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>>; |
|||
|
|||
/** |
|||
* Creates a pair of ServerSession and an associated ClientSession. |
|||
* @param name Optional name of the ports |
|||
* @return The created session tuple |
|||
*/ |
|||
static SessionPair CreateSessionPair( |
|||
const std::string& name = "Unknown", |
|||
std::shared_ptr<Service::SessionRequestHandler> hle_handler = nullptr); |
|||
|
|||
/** |
|||
* Handle a sync request from the emulated application. |
|||
* @returns ResultCode from the operation. |
|||
*/ |
|||
ResultCode HandleSyncRequest(); |
|||
|
|||
bool ShouldWait() override; |
|||
|
|||
void Acquire() override; |
|||
|
|||
std::string name; ///< The name of this session (optional) |
|||
bool signaled; ///< Whether there's new data available to this ServerSession |
|||
std::shared_ptr<Service::SessionRequestHandler> |
|||
hle_handler; ///< This session's HLE request handler (optional) |
|||
|
|||
private: |
|||
ServerSession(); |
|||
~ServerSession() override; |
|||
|
|||
/** |
|||
* Creates a server session. The server session can have an optional HLE handler, |
|||
* which will be invoked to handle the IPC requests that this session receives. |
|||
* @param name Optional name of the server session. |
|||
* @param hle_handler Optional HLE handler for this server session. |
|||
* @return The created server session |
|||
*/ |
|||
static ResultVal<SharedPtr<ServerSession>> Create( |
|||
std::string name = "Unknown", |
|||
std::shared_ptr<Service::SessionRequestHandler> hle_handler = nullptr); |
|||
}; |
|||
|
|||
/** |
|||
* Performs command buffer translation for an HLE IPC request. |
|||
* The command buffer from the ServerSession thread's TLS is copied into a |
|||
* buffer and all descriptors in the buffer are processed. |
|||
* TODO(Subv): Implement this function, currently we do not support multiple processes running at |
|||
* once, but once that is implemented we'll need to properly translate all descriptors |
|||
* in the command buffer. |
|||
*/ |
|||
ResultCode TranslateHLERequest(ServerSession* server_session); |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue