From 073653e858abf377fd1ebbdb071809c8830ce99d Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 14 Jun 2016 18:03:30 -0500 Subject: 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. --- src/core/hle/service/fs/archive.cpp | 12 ++++++------ src/core/hle/service/fs/archive.h | 12 +++++++----- src/core/hle/service/fs/fs_user.cpp | 9 +++++---- src/core/hle/service/service.cpp | 16 +++++++++++----- src/core/hle/service/service.h | 21 ++++++++++++++++----- src/core/hle/service/soc_u.cpp | 2 +- src/core/hle/service/srv.cpp | 17 ++++++++++++++++- 7 files changed, 62 insertions(+), 27 deletions(-) (limited to 'src/core/hle/service') 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&& backend, const FileSys::Path& File::~File() {} -ResultVal File::SyncRequest() { +ResultCode File::HandleSyncRequest() { u32* cmd_buff = Kernel::GetCommandBuffer(); FileCommand cmd = static_cast(cmd_buff[0]); switch (cmd) { @@ -193,10 +193,10 @@ ResultVal File::SyncRequest() { LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); ResultCode error = UnimplementedFunction(ErrorModule::FS); cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. - return error; + return ServerSession::HandleSyncRequest(); } cmd_buff[1] = RESULT_SUCCESS.raw; // No error - return MakeResult(false); + return ServerSession::HandleSyncRequest(); } Directory::Directory(std::unique_ptr&& backend, @@ -205,7 +205,7 @@ Directory::Directory(std::unique_ptr&& backend, Directory::~Directory() {} -ResultVal Directory::SyncRequest() { +ResultCode Directory::HandleSyncRequest() { u32* cmd_buff = Kernel::GetCommandBuffer(); DirectoryCommand cmd = static_cast(cmd_buff[0]); switch (cmd) { @@ -236,10 +236,10 @@ ResultVal Directory::SyncRequest() { LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); ResultCode error = UnimplementedFunction(ErrorModule::FS); cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. - return MakeResult(false); + return ServerSession::HandleSyncRequest(); } cmd_buff[1] = RESULT_SUCCESS.raw; // No error - return MakeResult(false); + return ServerSession::HandleSyncRequest(); } //////////////////////////////////////////////////////////////////////////////////////////////////// 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 @@ #include #include "common/common_types.h" #include "core/file_sys/archive_backend.h" -#include "core/hle/kernel/session.h" +#include "core/hle/kernel/server_session.h" #include "core/hle/result.h" namespace FileSys { @@ -41,7 +41,7 @@ enum class MediaType : u32 { NAND = 0, SDMC = 1 }; typedef u64 ArchiveHandle; -class File : public Kernel::Session { +class File : public Kernel::ServerSession { public: File(std::unique_ptr&& backend, const FileSys::Path& path); ~File(); @@ -49,14 +49,15 @@ public: std::string GetName() const override { return "Path: " + path.DebugStr(); } - ResultVal SyncRequest() override; + + ResultCode HandleSyncRequest() override; FileSys::Path path; ///< Path of the file u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means std::unique_ptr backend; ///< File backend interface }; -class Directory : public Kernel::Session { +class Directory : public Kernel::ServerSession { public: Directory(std::unique_ptr&& backend, const FileSys::Path& path); ~Directory(); @@ -64,7 +65,8 @@ public: std::string GetName() const override { return "Directory: " + path.DebugStr(); } - ResultVal SyncRequest() override; + + ResultCode HandleSyncRequest() override; FileSys::Path path; ///< Path of the directory std::unique_ptr 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 @@ #include "common/logging/log.h" #include "common/scope_exit.h" #include "common/string_util.h" +#include "core/hle/kernel/client_session.h" #include "core/hle/result.h" #include "core/hle/service/fs/archive.h" #include "core/hle/service/fs/fs_user.h" @@ -17,7 +18,7 @@ // Namespace FS_User using Kernel::SharedPtr; -using Kernel::Session; +using Kernel::ServerSession; namespace Service { namespace FS { @@ -70,7 +71,7 @@ static void OpenFile(Service::Interface* self) { ResultVal> file_res = OpenFileFromArchive(archive_handle, file_path, mode); cmd_buff[1] = file_res.Code().raw; if (file_res.Succeeded()) { - cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); + cmd_buff[3] = Kernel::g_handle_table.Create((*file_res)->CreateClientSession()).MoveFrom(); } else { cmd_buff[3] = 0; 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) { ResultVal> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); cmd_buff[1] = file_res.Code().raw; if (file_res.Succeeded()) { - cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); + cmd_buff[3] = Kernel::g_handle_table.Create((*file_res)->CreateClientSession()).MoveFrom(); } else { cmd_buff[3] = 0; 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) { ResultVal> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); cmd_buff[1] = dir_res.Code().raw; if (dir_res.Succeeded()) { - cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom(); + cmd_buff[3] = Kernel::g_handle_table.Create((*dir_res)->CreateClientSession()).MoveFrom(); } else { LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s", 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 @@ namespace Service { -std::unordered_map> g_kernel_named_ports; -std::unordered_map> g_srv_services; +std::unordered_map> g_kernel_named_ports; +std::unordered_map> g_srv_services; /** * 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, return function_string; } -ResultVal Interface::SyncRequest() { +ResultCode Interface::HandleSyncRequest() { u32* cmd_buff = Kernel::GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); @@ -75,14 +75,14 @@ ResultVal Interface::SyncRequest() { // TODO(bunnei): Hack - ignore error cmd_buff[1] = 0; - return MakeResult(false); + return RESULT_SUCCESS; } LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); itr->second.func(this); - return MakeResult(false); // TODO: Implement return from actual function + return RESULT_SUCCESS; // TODO: Implement return from actual function, it should fail if the parameter translation fails } void Interface::Register(const FunctionInfo* functions, size_t n) { @@ -97,10 +97,16 @@ void Interface::Register(const FunctionInfo* functions, size_t n) { // Module interface static void AddNamedPort(Interface* interface_) { + interface_->name = interface_->GetPortName(); + interface_->active_sessions = 0; + interface_->max_sessions = interface_->GetMaxSessions(); g_kernel_named_ports.emplace(interface_->GetPortName(), interface_); } void AddService(Interface* interface_) { + interface_->name = interface_->GetPortName(); + interface_->active_sessions = 0; + interface_->max_sessions = interface_->GetMaxSessions(); g_srv_services.emplace(interface_->GetPortName(), interface_); } 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 @@ #include #include #include "common/common_types.h" -#include "core/hle/kernel/session.h" +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/server_session.h" #include "core/hle/result.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -18,9 +19,10 @@ namespace Service { static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) +static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE port /// Interface to a CTROS service -class Interface : public Kernel::Session { +class Interface : public Kernel::ClientPort { // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be // just something that encapsulates a session and acts as a helper to implement service // processes. @@ -33,6 +35,15 @@ public: version.raw = raw_version; } + /** + * Gets the maximum allowed number of sessions that can be connected to this port at the same time. + * It should be overwritten by each service implementation for more fine-grained control. + * @returns The maximum number of connections allowed. + */ + virtual u32 GetMaxSessions() { return DefaultMaxSessions; } + + void AddWaitingSession(Kernel::SharedPtr server_session) override { } + typedef void (*Function)(Interface*); struct FunctionInfo { @@ -49,7 +60,7 @@ public: return "[UNKNOWN SERVICE PORT]"; } - ResultVal SyncRequest() override; + ResultCode HandleSyncRequest() override; protected: /** @@ -81,9 +92,9 @@ void Init(); void Shutdown(); /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC. -extern std::unordered_map> g_kernel_named_ports; +extern std::unordered_map> g_kernel_named_ports; /// Map of services registered with the "srv:" service, retrieved using GetServiceHandle. -extern std::unordered_map> g_srv_services; +extern std::unordered_map> g_srv_services; /// Adds a service to the services table 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 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "common/scope_exit.h" -#include "core/hle/kernel/session.h" +#include "core/hle/kernel/server_session.h" #include "core/hle/result.h" #include "core/hle/service/soc_u.h" #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 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include "common/common_types.h" #include "common/logging/log.h" +#include "core/hle/service/srv.h" +#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/event.h" #include "core/hle/service/srv.h" @@ -81,7 +85,18 @@ static void GetServiceHandle(Service::Interface* self) { auto it = Service::g_srv_services.find(port_name); if (it != Service::g_srv_services.end()) { - cmd_buff[3] = Kernel::g_handle_table.Create(it->second).MoveFrom(); + auto client_port = it->second; + + // Create a new session pair + auto sessions = Kernel::ServerSession::CreateSessionPair(client_port, port_name); + auto client_session = std::get>(sessions); + auto server_session = std::get>(sessions); + + // Add the server session to the port's queue + client_port->AddWaitingSession(server_session); + + // Return the client session + cmd_buff[3] = Kernel::g_handle_table.Create(client_session).MoveFrom(); LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); } else { LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); -- cgit v1.2.3 From 0a33d915f88b89e2fae20edc1e33a8ef60a2519c Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 17 Jun 2016 15:24:38 -0500 Subject: fixup! Kernel/IPC: Use Ports and Sessions as the fundamental building block of Inter Process Communication. --- src/core/hle/service/service.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index fd15ad03f..8df968b2e 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -40,7 +40,7 @@ public: * It should be overwritten by each service implementation for more fine-grained control. * @returns The maximum number of connections allowed. */ - virtual u32 GetMaxSessions() { return DefaultMaxSessions; } + virtual u32 GetMaxSessions() const { return DefaultMaxSessions; } void AddWaitingSession(Kernel::SharedPtr server_session) override { } -- cgit v1.2.3 From c19afd21188e91b9dd2780cf5cb9872a17ad113d Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 17 Jun 2016 17:09:43 -0500 Subject: Kernel/HLE: Service::Interface no longer inherits from any Kernel object, and is now its own standalone class. Interface is now used by aggregation in ClientPort, to forward service commands to their HLE implementation if needed. --- src/core/hle/service/service.cpp | 12 ++++-------- src/core/hle/service/service.h | 12 ++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index f51a042ff..abfc1806b 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -97,17 +97,13 @@ void Interface::Register(const FunctionInfo* functions, size_t n) { // Module interface static void AddNamedPort(Interface* interface_) { - interface_->name = interface_->GetPortName(); - interface_->active_sessions = 0; - interface_->max_sessions = interface_->GetMaxSessions(); - g_kernel_named_ports.emplace(interface_->GetPortName(), interface_); + auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::unique_ptr(interface_)); + g_kernel_named_ports.emplace(interface_->GetPortName(), client_port); } void AddService(Interface* interface_) { - interface_->name = interface_->GetPortName(); - interface_->active_sessions = 0; - interface_->max_sessions = interface_->GetMaxSessions(); - g_srv_services.emplace(interface_->GetPortName(), interface_); + auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::unique_ptr(interface_)); + g_srv_services.emplace(interface_->GetPortName(), client_port); } /// Initialize ServiceManager diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 8df968b2e..b22caca07 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -22,18 +22,16 @@ static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 character static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE port /// Interface to a CTROS service -class Interface : public Kernel::ClientPort { - // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be - // just something that encapsulates a session and acts as a helper to implement service - // processes. +class Interface { public: - std::string GetName() const override { + std::string GetName() const { return GetPortName(); } virtual void SetVersion(u32 raw_version) { version.raw = raw_version; } + virtual ~Interface() {} /** * Gets the maximum allowed number of sessions that can be connected to this port at the same time. @@ -42,8 +40,6 @@ public: */ virtual u32 GetMaxSessions() const { return DefaultMaxSessions; } - void AddWaitingSession(Kernel::SharedPtr server_session) override { } - typedef void (*Function)(Interface*); struct FunctionInfo { @@ -60,7 +56,7 @@ public: return "[UNKNOWN SERVICE PORT]"; } - ResultCode HandleSyncRequest() override; + ResultCode HandleSyncRequest(); protected: /** -- cgit v1.2.3 From c5e7e0fa26fc793c8b9f3effe25586f7fb57953e Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 18 Jun 2016 13:39:26 -0500 Subject: IPC/HLE: Associate the ClientSessions with their parent port's HLE interface if it exists. Pass the triggering ServerSession to the HLE command handler to differentiate which session caused the request. --- src/core/hle/service/service.cpp | 8 +++++--- src/core/hle/service/service.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index abfc1806b..56e4f8734 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -61,7 +61,9 @@ static std::string MakeFunctionString(const char* name, const char* port_name, return function_string; } -ResultCode Interface::HandleSyncRequest() { +ResultCode Interface::HandleSyncRequest(Kernel::SharedPtr server_session) { + // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which session triggered each command. + u32* cmd_buff = Kernel::GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); @@ -97,12 +99,12 @@ void Interface::Register(const FunctionInfo* functions, size_t n) { // Module interface static void AddNamedPort(Interface* interface_) { - auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::unique_ptr(interface_)); + auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::shared_ptr(interface_)); g_kernel_named_ports.emplace(interface_->GetPortName(), client_port); } void AddService(Interface* interface_) { - auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::unique_ptr(interface_)); + auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::shared_ptr(interface_)); g_srv_services.emplace(interface_->GetPortName(), client_port); } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index b22caca07..e2d04450a 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -56,7 +56,7 @@ public: return "[UNKNOWN SERVICE PORT]"; } - ResultCode HandleSyncRequest(); + ResultCode HandleSyncRequest(Kernel::SharedPtr server_session); protected: /** -- cgit v1.2.3 From 009b15b3aa9858930f461d825f7dd030fc963801 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 30 Nov 2016 22:50:13 -0500 Subject: A bit of a redesign. Sessions and Ports are now detached from each other. HLE services are handled by means of a SessionRequestHandler class, Interface now inherits from this class. The File and Directory classes are no longer kernel objects, but SessionRequestHandlers instead, bound to a ServerSession when requested. File::OpenLinkFile now creates a new session pair and binds the File instance to it. --- src/core/hle/service/fs/archive.cpp | 35 +++---- src/core/hle/service/fs/archive.h | 20 ++-- src/core/hle/service/fs/fs_user.cpp | 18 ++-- src/core/hle/service/service.cpp | 17 ++-- src/core/hle/service/service.h | 179 +++++++++++++++++++++++++++++++++++- src/core/hle/service/srv.cpp | 10 +- 6 files changed, 233 insertions(+), 46 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index da009df91..e40483c72 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -23,10 +23,11 @@ #include "core/file_sys/directory_backend.h" #include "core/file_sys/file_backend.h" #include "core/hle/hle.h" +#include "core/hle/kernel/client_session.h" #include "core/hle/result.h" +#include "core/hle/service/service.h" #include "core/hle/service/fs/archive.h" #include "core/hle/service/fs/fs_user.h" -#include "core/hle/service/service.h" #include "core/memory.h" // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. @@ -92,11 +93,10 @@ File::File(std::unique_ptr&& backend, const FileSys::Path& File::~File() {} -ResultCode File::HandleSyncRequest() { +ResultCode File::HandleSyncRequest(Kernel::SharedPtr server_session) { u32* cmd_buff = Kernel::GetCommandBuffer(); FileCommand cmd = static_cast(cmd_buff[0]); switch (cmd) { - // Read from file... case FileCommand::Read: { u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; @@ -170,9 +170,11 @@ ResultCode File::HandleSyncRequest() { break; } - case FileCommand::OpenLinkFile: { + case FileCommand::OpenLinkFile: + { LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); - cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE); + auto sessions = Kernel::ServerSession::CreateSessionPair(GetName(), shared_from_this()); + cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).ValueOr(INVALID_HANDLE); break; } @@ -193,10 +195,10 @@ ResultCode File::HandleSyncRequest() { LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); ResultCode error = UnimplementedFunction(ErrorModule::FS); cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. - return ServerSession::HandleSyncRequest(); + return RESULT_SUCCESS; } cmd_buff[1] = RESULT_SUCCESS.raw; // No error - return ServerSession::HandleSyncRequest(); + return RESULT_SUCCESS; } Directory::Directory(std::unique_ptr&& backend, @@ -205,11 +207,10 @@ Directory::Directory(std::unique_ptr&& backend, Directory::~Directory() {} -ResultCode Directory::HandleSyncRequest() { +ResultCode Directory::HandleSyncRequest(Kernel::SharedPtr server_session) { u32* cmd_buff = Kernel::GetCommandBuffer(); DirectoryCommand cmd = static_cast(cmd_buff[0]); switch (cmd) { - // Read from directory... case DirectoryCommand::Read: { u32 count = cmd_buff[1]; @@ -236,10 +237,10 @@ ResultCode Directory::HandleSyncRequest() { LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); ResultCode error = UnimplementedFunction(ErrorModule::FS); cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. - return ServerSession::HandleSyncRequest(); + return RESULT_SUCCESS; } cmd_buff[1] = RESULT_SUCCESS.raw; // No error - return ServerSession::HandleSyncRequest(); + return RESULT_SUCCESS; } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -306,7 +307,7 @@ ResultCode RegisterArchiveType(std::unique_ptr&& factor return RESULT_SUCCESS; } -ResultVal> OpenFileFromArchive(ArchiveHandle archive_handle, +ResultVal> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { ArchiveBackend* archive = GetArchive(archive_handle); @@ -317,8 +318,8 @@ ResultVal> OpenFileFromArchive(ArchiveHandle archive_han if (backend.Failed()) return backend.Code(); - auto file = Kernel::SharedPtr(new File(backend.MoveFrom(), path)); - return MakeResult>(std::move(file)); + auto file = std::shared_ptr(new File(backend.MoveFrom(), path)); + return MakeResult>(std::move(file)); } ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { @@ -397,7 +398,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, } } -ResultVal> OpenDirectoryFromArchive(ArchiveHandle archive_handle, +ResultVal> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) @@ -407,8 +408,8 @@ ResultVal> OpenDirectoryFromArchive(ArchiveHandle a if (backend.Failed()) return backend.Code(); - auto directory = Kernel::SharedPtr(new Directory(backend.MoveFrom(), path)); - return MakeResult>(std::move(directory)); + auto directory = std::shared_ptr(new Directory(backend.MoveFrom(), path)); + return MakeResult>(std::move(directory)); } ResultVal GetFreeBytesInArchive(ArchiveHandle archive_handle) { diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 22e659c40..29527ef48 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -41,32 +41,32 @@ enum class MediaType : u32 { NAND = 0, SDMC = 1 }; typedef u64 ArchiveHandle; -class File : public Kernel::ServerSession { +class File : public SessionRequestHandler, public std::enable_shared_from_this { public: File(std::unique_ptr&& backend, const FileSys::Path& path); ~File(); - std::string GetName() const override { + std::string GetName() const { return "Path: " + path.DebugStr(); } - ResultCode HandleSyncRequest() override; + ResultCode HandleSyncRequest(Kernel::SharedPtr server_session) override; FileSys::Path path; ///< Path of the file u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means std::unique_ptr backend; ///< File backend interface }; -class Directory : public Kernel::ServerSession { +class Directory : public SessionRequestHandler { public: Directory(std::unique_ptr&& backend, const FileSys::Path& path); ~Directory(); - std::string GetName() const override { + std::string GetName() const { return "Directory: " + path.DebugStr(); } - ResultCode HandleSyncRequest() override; + ResultCode HandleSyncRequest(Kernel::SharedPtr server_session) override; FileSys::Path path; ///< Path of the directory std::unique_ptr backend; ///< File backend interface @@ -99,9 +99,9 @@ ResultCode RegisterArchiveType(std::unique_ptr&& factor * @param archive_handle Handle to an open Archive object * @param path Path to the File inside of the Archive * @param mode Mode under which to open the File - * @return The opened File object as a Session + * @return The opened File object */ -ResultVal> OpenFileFromArchive(ArchiveHandle archive_handle, +ResultVal> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); @@ -178,9 +178,9 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, * Open a Directory from an Archive * @param archive_handle Handle to an open Archive object * @param path Path to the Directory inside of the Archive - * @return The opened Directory object as a Session + * @return The opened Directory object */ -ResultVal> OpenDirectoryFromArchive(ArchiveHandle archive_handle, +ResultVal> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); /** diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index bb78091f9..a29bce22a 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -68,10 +68,12 @@ static void OpenFile(Service::Interface* self) { LOG_DEBUG(Service_FS, "path=%s, mode=%u attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); - ResultVal> file_res = OpenFileFromArchive(archive_handle, file_path, mode); + ResultVal> file_res = OpenFileFromArchive(archive_handle, file_path, mode); cmd_buff[1] = file_res.Code().raw; if (file_res.Succeeded()) { - cmd_buff[3] = Kernel::g_handle_table.Create((*file_res)->CreateClientSession()).MoveFrom(); + std::shared_ptr file = *file_res; + auto sessions = ServerSession::CreateSessionPair(file->GetName(), file); + cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).MoveFrom(); } else { cmd_buff[3] = 0; LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); @@ -128,10 +130,12 @@ static void OpenFileDirectly(Service::Interface* self) { } SCOPE_EXIT({ CloseArchive(*archive_handle); }); - ResultVal> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); + ResultVal> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); cmd_buff[1] = file_res.Code().raw; if (file_res.Succeeded()) { - cmd_buff[3] = Kernel::g_handle_table.Create((*file_res)->CreateClientSession()).MoveFrom(); + std::shared_ptr file = *file_res; + auto sessions = ServerSession::CreateSessionPair(file->GetName(), file); + cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).MoveFrom(); } else { cmd_buff[3] = 0; LOG_ERROR(Service_FS, "failed to get a handle for file %s mode=%u attributes=%u", @@ -389,10 +393,12 @@ static void OpenDirectory(Service::Interface* self) { LOG_DEBUG(Service_FS, "type=%u size=%u data=%s", static_cast(dirname_type), dirname_size, dir_path.DebugStr().c_str()); - ResultVal> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); + ResultVal> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); cmd_buff[1] = dir_res.Code().raw; if (dir_res.Succeeded()) { - cmd_buff[3] = Kernel::g_handle_table.Create((*dir_res)->CreateClientSession()).MoveFrom(); + std::shared_ptr directory = *dir_res; + auto sessions = ServerSession::CreateSessionPair(directory->GetName(), directory); + cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).MoveFrom(); } else { LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s", 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 56e4f8734..c90802455 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -4,6 +4,9 @@ #include "common/logging/log.h" #include "common/string_util.h" + +#include "core/hle/kernel/server_port.h" +#include "core/hle/service/service.h" #include "core/hle/service/ac_u.h" #include "core/hle/service/act_a.h" #include "core/hle/service/act_u.h" @@ -41,8 +44,8 @@ namespace Service { -std::unordered_map> g_kernel_named_ports; -std::unordered_map> g_srv_services; +std::unordered_map, std::shared_ptr>> g_kernel_named_ports; +std::unordered_map, std::shared_ptr>> g_srv_services; /** * Creates a function string for logging, complete with the name (or header code, depending @@ -99,13 +102,15 @@ void Interface::Register(const FunctionInfo* functions, size_t n) { // Module interface static void AddNamedPort(Interface* interface_) { - auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::shared_ptr(interface_)); - g_kernel_named_ports.emplace(interface_->GetPortName(), client_port); + auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName()); + auto client_port = std::get>(ports); + g_kernel_named_ports.emplace(interface_->GetPortName(), std::make_tuple(client_port, std::shared_ptr(interface_))); } void AddService(Interface* interface_) { - auto client_port = Kernel::ClientPort::CreateForHLE(interface_->GetMaxSessions(), std::shared_ptr(interface_)); - g_srv_services.emplace(interface_->GetPortName(), client_port); + auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName()); + auto client_port = std::get>(ports); + g_srv_services.emplace(interface_->GetPortName(), std::make_tuple(client_port, std::shared_ptr(interface_))); } /// Initialize ServiceManager diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index e2d04450a..dd268f39c 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -10,8 +10,163 @@ #include #include "common/common_types.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/server_session.h" +#include "core/hle/kernel/thread.h" #include "core/hle/result.h" +#include "core/memory.h" + +namespace Kernel { +class ServerSession; + +// TODO(Subv): Move these declarations out of here +static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header + +/** + * Returns a pointer to the command buffer in the current thread's TLS + * TODO(Subv): This is not entirely correct, the command buffer should be copied from + * the thread's TLS to an intermediate buffer in kernel memory, and then copied again to + * the service handler process' memory. + * @param offset Optional offset into command buffer + * @return Pointer to command buffer + */ +inline u32* GetCommandBuffer(const int offset = 0) { + return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + + offset); +} +} + +// TODO(Subv): Move this namespace out of here +namespace IPC { + +enum DescriptorType : u32 { + // Buffer related desciptors types (mask : 0x0F) + StaticBuffer = 0x02, + PXIBuffer = 0x04, + MappedBuffer = 0x08, + // Handle related descriptors types (mask : 0x30, but need to check for buffer related + // descriptors first ) + CopyHandle = 0x00, + MoveHandle = 0x10, + CallingPid = 0x20, +}; + +/** +* @brief Creates a command header to be used for IPC +* @param command_id ID of the command to create a header for. +* @param normal_params Size of the normal parameters in words. Up to 63. +* @param translate_params_size Size of the translate parameters in words. Up to 63. +* @return The created IPC header. +* +* Normal parameters are sent directly to the process while the translate parameters might go +* through modifications and checks by the kernel. +* The translate parameters are described by headers generated with the IPC::*Desc functions. +* +* @note While #normal_params is equivalent to the number of normal parameters, +* #translate_params_size includes the size occupied by the translate parameters headers. +*/ +constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, + unsigned int translate_params_size) { + return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | + (u32(translate_params_size) & 0x3F); +} + +union Header { + u32 raw; + BitField<0, 6, u32> translate_params_size; + BitField<6, 6, u32> normal_params; + BitField<16, 16, u32> command_id; +}; + +inline Header ParseHeader(u32 header) { + return{ header }; +} + +constexpr u32 MoveHandleDesc(u32 num_handles = 1) { + return MoveHandle | ((num_handles - 1) << 26); +} + +constexpr u32 CopyHandleDesc(u32 num_handles = 1) { + return CopyHandle | ((num_handles - 1) << 26); +} + +constexpr u32 CallingPidDesc() { + return CallingPid; +} + +constexpr bool isHandleDescriptor(u32 descriptor) { + return (descriptor & 0xF) == 0x0; +} + +constexpr u32 HandleNumberFromDesc(u32 handle_descriptor) { + return (handle_descriptor >> 26) + 1; +} + +constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) { + return StaticBuffer | (size << 14) | ((buffer_id & 0xF) << 10); +} + +union StaticBufferDescInfo { + u32 raw; + BitField<10, 4, u32> buffer_id; + BitField<14, 18, u32> size; +}; + +inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { + return{ desc }; +} + +/** +* @brief Creates a header describing a buffer to be sent over PXI. +* @param size Size of the buffer. Max 0x00FFFFFF. +* @param buffer_id The Id of the buffer. Max 0xF. +* @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have +* read-write access. +* @return The created PXI buffer header. +* +* The next value is a phys-address of a table located in the BASE memregion. +*/ +inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { + u32 type = PXIBuffer; + if (is_read_only) + type |= 0x2; + return type | (size << 8) | ((buffer_id & 0xF) << 4); +} + +enum MappedBufferPermissions { + R = 1, + W = 2, + RW = R | W, +}; + +constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) { + return MappedBuffer | (size << 4) | (u32(perms) << 1); +} + +union MappedBufferDescInfo { + u32 raw; + BitField<4, 28, u32> size; + BitField<1, 2, MappedBufferPermissions> perms; +}; + +inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { + return{ desc }; +} + +inline DescriptorType GetDescriptorType(u32 descriptor) { + // Note: Those checks must be done in this order + if (isHandleDescriptor(descriptor)) + return (DescriptorType)(descriptor & 0x30); + + // handle the fact that the following descriptors can have rights + if (descriptor & MappedBuffer) + return MappedBuffer; + + if (descriptor & PXIBuffer) + return PXIBuffer; + + return StaticBuffer; +} + +} // namespace IPC //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace Service @@ -21,8 +176,22 @@ namespace Service { static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE port +/// TODO(Subv): Write documentation for this class +class SessionRequestHandler { +public: + /** + * Dispatches and handles a sync request from the emulated application. + * @param server_session The ServerSession that was triggered for this sync request, + * it should be used to differentiate which client (As in ClientSession) we're answering to. + * TODO(Subv): Make a HandleSyncRequestParent function that is called from the outside and does { ReturnIfError(Translate()); HandleSyncRequest(); } + * The Translate() function would copy the command buffer from the ServerSession thread's TLS into a temporary buffer, and pass it to HandleSyncRequest. + * TODO(Subv): HandleSyncRequest's return type should be void. + */ + virtual ResultCode HandleSyncRequest(Kernel::SharedPtr server_session) = 0; +}; + /// Interface to a CTROS service -class Interface { +class Interface : public SessionRequestHandler { public: std::string GetName() const { return GetPortName(); @@ -56,7 +225,7 @@ public: return "[UNKNOWN SERVICE PORT]"; } - ResultCode HandleSyncRequest(Kernel::SharedPtr server_session); + ResultCode HandleSyncRequest(Kernel::SharedPtr server_session) override; protected: /** @@ -88,9 +257,9 @@ void Init(); void Shutdown(); /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC. -extern std::unordered_map> g_kernel_named_ports; +extern std::unordered_map, std::shared_ptr>> g_kernel_named_ports; /// Map of services registered with the "srv:" service, retrieved using GetServiceHandle. -extern std::unordered_map> g_srv_services; +extern std::unordered_map, std::shared_ptr>> g_srv_services; /// Adds a service to the services table void AddService(Interface* interface_); diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index eb2e06041..6731afc22 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -10,6 +10,7 @@ #include "core/hle/kernel/client_session.h" #include "core/hle/kernel/event.h" #include "core/hle/service/srv.h" +#include "core/hle/kernel/server_session.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace SRV @@ -85,13 +86,18 @@ static void GetServiceHandle(Service::Interface* self) { auto it = Service::g_srv_services.find(port_name); if (it != Service::g_srv_services.end()) { - auto client_port = it->second; + auto client_port = std::get>(it->second); + // The hle_handler will be nullptr if this port was registered by the emulated + // application by means of srv:RegisterService. + auto hle_handler = std::get>(it->second); // Create a new session pair - auto sessions = Kernel::ServerSession::CreateSessionPair(client_port, port_name); + auto sessions = Kernel::ServerSession::CreateSessionPair(port_name, hle_handler); auto client_session = std::get>(sessions); auto server_session = std::get>(sessions); + // TODO(Subv): Wait the current thread until the ServerPort calls AcceptSession. + // Add the server session to the port's queue client_port->AddWaitingSession(server_session); -- cgit v1.2.3 From 2eceee3a4cc2786dae4e9b80a8b5f3bb666d3fc6 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 30 Nov 2016 23:28:31 -0500 Subject: Fixed the rebase mistakes. --- src/core/hle/service/fs/archive.cpp | 8 +++--- src/core/hle/service/service.h | 50 ++++++++++++++++++------------------- src/core/hle/service/srv.cpp | 3 +-- 3 files changed, 30 insertions(+), 31 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index e40483c72..a9f457726 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -25,9 +25,9 @@ #include "core/hle/hle.h" #include "core/hle/kernel/client_session.h" #include "core/hle/result.h" -#include "core/hle/service/service.h" #include "core/hle/service/fs/archive.h" #include "core/hle/service/fs/fs_user.h" +#include "core/hle/service/service.h" #include "core/memory.h" // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. @@ -97,6 +97,7 @@ ResultCode File::HandleSyncRequest(Kernel::SharedPtr serv u32* cmd_buff = Kernel::GetCommandBuffer(); FileCommand cmd = static_cast(cmd_buff[0]); switch (cmd) { + // Read from file... case FileCommand::Read: { u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; @@ -170,8 +171,7 @@ ResultCode File::HandleSyncRequest(Kernel::SharedPtr serv break; } - case FileCommand::OpenLinkFile: - { + case FileCommand::OpenLinkFile: { LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); auto sessions = Kernel::ServerSession::CreateSessionPair(GetName(), shared_from_this()); cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).ValueOr(INVALID_HANDLE); @@ -195,7 +195,7 @@ ResultCode File::HandleSyncRequest(Kernel::SharedPtr serv LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); ResultCode error = UnimplementedFunction(ErrorModule::FS); cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. - return RESULT_SUCCESS; + return error; } cmd_buff[1] = RESULT_SUCCESS.raw; // No error return RESULT_SUCCESS; diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index dd268f39c..931512339 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -50,23 +50,23 @@ enum DescriptorType : u32 { }; /** -* @brief Creates a command header to be used for IPC -* @param command_id ID of the command to create a header for. -* @param normal_params Size of the normal parameters in words. Up to 63. -* @param translate_params_size Size of the translate parameters in words. Up to 63. -* @return The created IPC header. -* -* Normal parameters are sent directly to the process while the translate parameters might go -* through modifications and checks by the kernel. -* The translate parameters are described by headers generated with the IPC::*Desc functions. -* -* @note While #normal_params is equivalent to the number of normal parameters, -* #translate_params_size includes the size occupied by the translate parameters headers. -*/ + * @brief Creates a command header to be used for IPC + * @param command_id ID of the command to create a header for. + * @param normal_params Size of the normal parameters in words. Up to 63. + * @param translate_params_size Size of the translate parameters in words. Up to 63. + * @return The created IPC header. + * + * Normal parameters are sent directly to the process while the translate parameters might go + * through modifications and checks by the kernel. + * The translate parameters are described by headers generated with the IPC::*Desc functions. + * + * @note While #normal_params is equivalent to the number of normal parameters, + * #translate_params_size includes the size occupied by the translate parameters headers. + */ constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, unsigned int translate_params_size) { return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | - (u32(translate_params_size) & 0x3F); + (u32(translate_params_size) & 0x3F); } union Header { @@ -77,7 +77,7 @@ union Header { }; inline Header ParseHeader(u32 header) { - return{ header }; + return {header}; } constexpr u32 MoveHandleDesc(u32 num_handles = 1) { @@ -111,19 +111,19 @@ union StaticBufferDescInfo { }; inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { - return{ desc }; + return {desc}; } /** -* @brief Creates a header describing a buffer to be sent over PXI. -* @param size Size of the buffer. Max 0x00FFFFFF. -* @param buffer_id The Id of the buffer. Max 0xF. -* @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have -* read-write access. -* @return The created PXI buffer header. -* -* The next value is a phys-address of a table located in the BASE memregion. -*/ + * @brief Creates a header describing a buffer to be sent over PXI. + * @param size Size of the buffer. Max 0x00FFFFFF. + * @param buffer_id The Id of the buffer. Max 0xF. + * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have + * read-write access. + * @return The created PXI buffer header. + * + * The next value is a phys-address of a table located in the BASE memregion. + */ inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { u32 type = PXIBuffer; if (is_read_only) diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 6731afc22..d228e3523 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -6,11 +6,10 @@ #include "common/common_types.h" #include "common/logging/log.h" -#include "core/hle/service/srv.h" #include "core/hle/kernel/client_session.h" +#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/event.h" #include "core/hle/service/srv.h" -#include "core/hle/kernel/server_session.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace SRV -- cgit v1.2.3 From ed210c32b3820c77845c27d1f73e6ff2f0828505 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 1 Dec 2016 10:47:06 -0500 Subject: Threads do not wait for the server endpoint to call AcceptSession before returning from a ConnectToPort or GetServiceHandle call. --- src/core/hle/service/srv.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index d228e3523..c0abfd711 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -95,7 +95,8 @@ static void GetServiceHandle(Service::Interface* self) { auto client_session = std::get>(sessions); auto server_session = std::get>(sessions); - // TODO(Subv): Wait the current thread until the ServerPort calls AcceptSession. + // Note: Threads do not wait for the server endpoint to call + // AcceptSession before returning from this call. // Add the server session to the port's queue client_port->AddWaitingSession(server_session); -- cgit v1.2.3 From dd8887c8cfbb6d3010dde240278a3d4018c5dd85 Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 5 Dec 2016 11:02:08 -0500 Subject: KServerPorts now have an HLE handler "template", which is inherited by all ServerSessions created from it. --- src/core/hle/service/service.cpp | 14 ++++++++------ src/core/hle/service/service.h | 14 ++++++++++---- src/core/hle/service/srv.cpp | 14 +++----------- 3 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index c90802455..3462af8ce 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -44,8 +44,8 @@ namespace Service { -std::unordered_map, std::shared_ptr>> g_kernel_named_ports; -std::unordered_map, std::shared_ptr>> g_srv_services; +std::unordered_map> g_kernel_named_ports; +std::unordered_map> g_srv_services; /** * Creates a function string for logging, complete with the name (or header code, depending @@ -102,15 +102,17 @@ void Interface::Register(const FunctionInfo* functions, size_t n) { // Module interface static void AddNamedPort(Interface* interface_) { - auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName()); + auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), + std::shared_ptr(interface_)); auto client_port = std::get>(ports); - g_kernel_named_ports.emplace(interface_->GetPortName(), std::make_tuple(client_port, std::shared_ptr(interface_))); + g_kernel_named_ports.emplace(interface_->GetPortName(), client_port); } void AddService(Interface* interface_) { - auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName()); + auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), + std::shared_ptr(interface_)); auto client_port = std::get>(ports); - g_srv_services.emplace(interface_->GetPortName(), std::make_tuple(client_port, std::shared_ptr(interface_))); + g_srv_services.emplace(interface_->GetPortName(), client_port); } /// Initialize ServiceManager diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 931512339..e85882713 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -176,7 +176,11 @@ namespace Service { static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE port -/// TODO(Subv): Write documentation for this class +/** + * Interface implemented by HLE Session handlers. + * This can be provided to a ServerSession in order to hook into several relevant events (such as a new connection or a SyncRequest) + * so they can be implemented in the emulator. + */ class SessionRequestHandler { public: /** @@ -190,7 +194,9 @@ public: virtual ResultCode HandleSyncRequest(Kernel::SharedPtr server_session) = 0; }; -/// Interface to a CTROS service +/** + * Framework for implementing HLE service handlers which dispatch incoming SyncRequests based on a table mapping header ids to handler functions. + */ class Interface : public SessionRequestHandler { public: std::string GetName() const { @@ -257,9 +263,9 @@ void Init(); void Shutdown(); /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC. -extern std::unordered_map, std::shared_ptr>> g_kernel_named_ports; +extern std::unordered_map> g_kernel_named_ports; /// Map of services registered with the "srv:" service, retrieved using GetServiceHandle. -extern std::unordered_map, std::shared_ptr>> g_srv_services; +extern std::unordered_map> g_srv_services; /// Adds a service to the services table void AddService(Interface* interface_); diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index c0abfd711..bb2c8fcc4 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -85,21 +85,13 @@ static void GetServiceHandle(Service::Interface* self) { auto it = Service::g_srv_services.find(port_name); if (it != Service::g_srv_services.end()) { - auto client_port = std::get>(it->second); - // The hle_handler will be nullptr if this port was registered by the emulated - // application by means of srv:RegisterService. - auto hle_handler = std::get>(it->second); - - // Create a new session pair - auto sessions = Kernel::ServerSession::CreateSessionPair(port_name, hle_handler); - auto client_session = std::get>(sessions); - auto server_session = std::get>(sessions); + auto client_port = it->second; // Note: Threads do not wait for the server endpoint to call // AcceptSession before returning from this call. - // Add the server session to the port's queue - client_port->AddWaitingSession(server_session); + // Connect to the port and retrieve the client endpoint of the connection Session. + auto client_session = client_port->Connect(); // Return the client session cmd_buff[3] = Kernel::g_handle_table.Create(client_session).MoveFrom(); -- cgit v1.2.3 From 00f0c775702af4145a4a81ec5d357c3586a5c6c3 Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 5 Dec 2016 12:05:00 -0500 Subject: Split SessionRequestHandler::HandleSyncRequest into HandleSyncRequest, TranslateRequest and HandleSyncRequestImpl. HandleSyncRequest now takes care of calling the command buffer translate function before actually invoking the command handler for HLE services. --- src/core/hle/service/fs/archive.cpp | 14 ++++++-------- src/core/hle/service/fs/archive.h | 10 ++++++---- src/core/hle/service/service.cpp | 27 +++++++++++++++++++++++---- src/core/hle/service/service.h | 28 ++++++++++++++++++++++------ 4 files changed, 57 insertions(+), 22 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index a9f457726..c10d6a3a9 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -93,7 +93,7 @@ File::File(std::unique_ptr&& backend, const FileSys::Path& File::~File() {} -ResultCode File::HandleSyncRequest(Kernel::SharedPtr server_session) { +void File::HandleSyncRequestImpl(Kernel::SharedPtr server_session) { u32* cmd_buff = Kernel::GetCommandBuffer(); FileCommand cmd = static_cast(cmd_buff[0]); switch (cmd) { @@ -116,7 +116,7 @@ ResultCode File::HandleSyncRequest(Kernel::SharedPtr serv ResultVal read = backend->Read(offset, data.size(), data.data()); if (read.Failed()) { cmd_buff[1] = read.Code().raw; - return read.Code(); + return; } Memory::WriteBlock(address, data.data(), *read); cmd_buff[2] = static_cast(*read); @@ -137,7 +137,7 @@ ResultCode File::HandleSyncRequest(Kernel::SharedPtr serv ResultVal written = backend->Write(offset, data.size(), flush != 0, data.data()); if (written.Failed()) { cmd_buff[1] = written.Code().raw; - return written.Code(); + return; } cmd_buff[2] = static_cast(*written); break; @@ -195,10 +195,9 @@ ResultCode File::HandleSyncRequest(Kernel::SharedPtr serv LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); ResultCode error = UnimplementedFunction(ErrorModule::FS); cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. - return error; + return; } cmd_buff[1] = RESULT_SUCCESS.raw; // No error - return RESULT_SUCCESS; } Directory::Directory(std::unique_ptr&& backend, @@ -207,7 +206,7 @@ Directory::Directory(std::unique_ptr&& backend, Directory::~Directory() {} -ResultCode Directory::HandleSyncRequest(Kernel::SharedPtr server_session) { +void Directory::HandleSyncRequestImpl(Kernel::SharedPtr server_session) { u32* cmd_buff = Kernel::GetCommandBuffer(); DirectoryCommand cmd = static_cast(cmd_buff[0]); switch (cmd) { @@ -237,10 +236,9 @@ ResultCode Directory::HandleSyncRequest(Kernel::SharedPtr LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); ResultCode error = UnimplementedFunction(ErrorModule::FS); cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. - return RESULT_SUCCESS; + return; } cmd_buff[1] = RESULT_SUCCESS.raw; // No error - return RESULT_SUCCESS; } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 29527ef48..cb014b5d7 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -50,11 +50,12 @@ public: return "Path: " + path.DebugStr(); } - ResultCode HandleSyncRequest(Kernel::SharedPtr server_session) override; - FileSys::Path path; ///< Path of the file u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means std::unique_ptr backend; ///< File backend interface + +protected: + void HandleSyncRequestImpl(Kernel::SharedPtr server_session) override; }; class Directory : public SessionRequestHandler { @@ -66,10 +67,11 @@ public: return "Directory: " + path.DebugStr(); } - ResultCode HandleSyncRequest(Kernel::SharedPtr server_session) override; - FileSys::Path path; ///< Path of the directory std::unique_ptr backend; ///< File backend interface + +protected: + void HandleSyncRequestImpl(Kernel::SharedPtr server_session) override; }; /** diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 3462af8ce..3d5e3058c 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -64,7 +64,27 @@ static std::string MakeFunctionString(const char* name, const char* port_name, return function_string; } -ResultCode Interface::HandleSyncRequest(Kernel::SharedPtr server_session) { +ResultCode SessionRequestHandler::HandleSyncRequest(Kernel::SharedPtr server_session) { + // Attempt to translate the incoming request's command buffer. + ResultCode result = TranslateRequest(server_session); + + if (result.IsError()) + return result; + + // Actually handle the request + HandleSyncRequestImpl(server_session); + + // TODO(Subv): Translate the response command buffer. + + return RESULT_SUCCESS; +} + +ResultCode SessionRequestHandler::TranslateRequest(Kernel::SharedPtr server_session) { + // TODO(Subv): Implement this function once multiple concurrent processes are supported. + return RESULT_SUCCESS; +} + +void Interface::HandleSyncRequestImpl(Kernel::SharedPtr server_session) { // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which session triggered each command. u32* cmd_buff = Kernel::GetCommandBuffer(); @@ -80,14 +100,12 @@ ResultCode Interface::HandleSyncRequest(Kernel::SharedPtr // TODO(bunnei): Hack - ignore error cmd_buff[1] = 0; - return RESULT_SUCCESS; + return; } LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); itr->second.func(this); - - return RESULT_SUCCESS; // TODO: Implement return from actual function, it should fail if the parameter translation fails } void Interface::Register(const FunctionInfo* functions, size_t n) { @@ -179,4 +197,5 @@ void Shutdown() { g_kernel_named_ports.clear(); LOG_DEBUG(Service, "shutdown OK"); } + } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index e85882713..7b7db8499 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -187,11 +187,27 @@ public: * Dispatches and handles a sync request from the emulated application. * @param server_session The ServerSession that was triggered for this sync request, * it should be used to differentiate which client (As in ClientSession) we're answering to. - * TODO(Subv): Make a HandleSyncRequestParent function that is called from the outside and does { ReturnIfError(Translate()); HandleSyncRequest(); } - * The Translate() function would copy the command buffer from the ServerSession thread's TLS into a temporary buffer, and pass it to HandleSyncRequest. - * TODO(Subv): HandleSyncRequest's return type should be void. + * @returns ResultCode the result code of the translate operation. */ - virtual ResultCode HandleSyncRequest(Kernel::SharedPtr server_session) = 0; + ResultCode HandleSyncRequest(Kernel::SharedPtr server_session); + +protected: + /** + * Handles a sync request from the emulated application and writes the response to the command buffer. + * TODO(Subv): Use a wrapper structure to hold all the information relevant to + * this request (ServerSession, Originator thread, Translated command buffer, etc). + */ + virtual void HandleSyncRequestImpl(Kernel::SharedPtr server_session) = 0; + +private: + /** + * Performs command buffer translation for this 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 TranslateRequest(Kernel::SharedPtr server_session); }; /** @@ -231,9 +247,9 @@ public: return "[UNKNOWN SERVICE PORT]"; } - ResultCode HandleSyncRequest(Kernel::SharedPtr server_session) override; - protected: + void HandleSyncRequestImpl(Kernel::SharedPtr server_session) override; + /** * Registers the functions in the service */ -- cgit v1.2.3 From 61a2fe8c3bcd5e6dc7e97945b923d1a5bd8099ec Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 5 Dec 2016 13:44:41 -0500 Subject: HLE: Use a member variable instead of a virtual function to retrieve the max number of sessions that can be connected to an HLE service at the same time. --- src/core/hle/service/apt/apt.h | 2 ++ src/core/hle/service/apt/apt_a.cpp | 2 +- src/core/hle/service/apt/apt_s.cpp | 2 +- src/core/hle/service/apt/apt_u.cpp | 2 +- src/core/hle/service/service.h | 18 +++++++++++++----- 5 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 44dbd8757..9bc6327ed 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -14,6 +14,8 @@ class Interface; namespace APT { +static const u32 MaxAPTSessions = 2; ///< Each APT service can only have up to 2 sessions connected at the same time. + /// Holds information about the parameters used in Send/Glance/ReceiveParameter struct MessageParameter { u32 sender_id = 0; diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp index a7a0c8a41..7f37a7f54 100644 --- a/src/core/hle/service/apt/apt_a.cpp +++ b/src/core/hle/service/apt/apt_a.cpp @@ -39,7 +39,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x01020000, CheckNew3DS, "CheckNew3DS"}, }; -APT_A_Interface::APT_A_Interface() { +APT_A_Interface::APT_A_Interface() : Interface(MaxAPTSessions) { Register(FunctionTable); } diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index c4556a5de..933f26e60 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp @@ -99,7 +99,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x01020000, CheckNew3DS, "CheckNew3DS"}, }; -APT_S_Interface::APT_S_Interface() { +APT_S_Interface::APT_S_Interface() : Interface(MaxAPTSessions) { Register(FunctionTable); } diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index a731c39f6..e06084a1e 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -99,7 +99,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x01020000, CheckNew3DS, "CheckNew3DS"}, }; -APT_U_Interface::APT_U_Interface() { +APT_U_Interface::APT_U_Interface() : Interface(MaxAPTSessions) { Register(FunctionTable); } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 7b7db8499..2274e50ca 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -174,7 +174,7 @@ inline DescriptorType GetDescriptorType(u32 descriptor) { namespace Service { static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) -static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE port +static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE service /** * Interface implemented by HLE Session handlers. @@ -215,6 +215,15 @@ private: */ class Interface : public SessionRequestHandler { public: + /** + * Creates an HLE interface with the specified max sessions. + * @param max_sessions Maximum number of sessions that can be + * connected to this service at the same time. + */ + Interface(u32 max_sessions = DefaultMaxSessions) : max_sessions(max_sessions) { } + + virtual ~Interface() = default; + std::string GetName() const { return GetPortName(); } @@ -222,14 +231,12 @@ public: virtual void SetVersion(u32 raw_version) { version.raw = raw_version; } - virtual ~Interface() {} /** - * Gets the maximum allowed number of sessions that can be connected to this port at the same time. - * It should be overwritten by each service implementation for more fine-grained control. + * Gets the maximum allowed number of sessions that can be connected to this service at the same time. * @returns The maximum number of connections allowed. */ - virtual u32 GetMaxSessions() const { return DefaultMaxSessions; } + u32 GetMaxSessions() const { return max_sessions; } typedef void (*Function)(Interface*); @@ -269,6 +276,7 @@ protected: } version = {}; private: + u32 max_sessions; ///< Maximum number of concurrent sessions that this service can handle. boost::container::flat_map m_functions; }; -- cgit v1.2.3 From c93c5a72bb46796e898f54a7c13dfb8d941ddd4d Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 5 Dec 2016 13:59:57 -0500 Subject: Return an error code when connecting to a saturated port. The error code was taken from the 3DS kernel. --- src/core/hle/service/srv.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index bb2c8fcc4..ff7a84347 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -93,8 +93,12 @@ static void GetServiceHandle(Service::Interface* self) { // Connect to the port and retrieve the client endpoint of the connection Session. auto client_session = client_port->Connect(); - // Return the client session - cmd_buff[3] = Kernel::g_handle_table.Create(client_session).MoveFrom(); + res = client_session.Code(); + + if (client_session.Succeeded()) { + // Return the client session + cmd_buff[3] = Kernel::g_handle_table.Create(*client_session).MoveFrom(); + } LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); } else { LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); -- cgit v1.2.3 From f9bcf895103e5a6d99f5fe755bcac92b7781fd38 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 8 Dec 2016 11:06:19 -0500 Subject: Use std::move where appropriate. --- src/core/hle/service/fs/archive.h | 4 +- src/core/hle/service/service.cpp | 7 +- src/core/hle/service/service.h | 159 +------------------------------------- src/core/hle/service/srv.cpp | 5 -- 4 files changed, 10 insertions(+), 165 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index cb014b5d7..09a922fb5 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -41,7 +41,7 @@ enum class MediaType : u32 { NAND = 0, SDMC = 1 }; typedef u64 ArchiveHandle; -class File : public SessionRequestHandler, public std::enable_shared_from_this { +class File final : public SessionRequestHandler, public std::enable_shared_from_this { public: File(std::unique_ptr&& backend, const FileSys::Path& path); ~File(); @@ -58,7 +58,7 @@ protected: void HandleSyncRequestImpl(Kernel::SharedPtr server_session) override; }; -class Directory : public SessionRequestHandler { +class Directory final : public SessionRequestHandler { public: Directory(std::unique_ptr&& backend, const FileSys::Path& path); ~Directory(); diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 3d5e3058c..6ea5cf745 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -84,6 +84,9 @@ ResultCode SessionRequestHandler::TranslateRequest(Kernel::SharedPtr server_session) { // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which session triggered each command. @@ -123,14 +126,14 @@ static void AddNamedPort(Interface* interface_) { auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), std::shared_ptr(interface_)); auto client_port = std::get>(ports); - g_kernel_named_ports.emplace(interface_->GetPortName(), client_port); + g_kernel_named_ports.emplace(interface_->GetPortName(), std::move(client_port)); } void AddService(Interface* interface_) { auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), std::shared_ptr(interface_)); auto client_port = std::get>(ports); - g_srv_services.emplace(interface_->GetPortName(), client_port); + g_srv_services.emplace(interface_->GetPortName(), std::move(client_port)); } /// Initialize ServiceManager diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 2274e50ca..ba5ba062e 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -9,165 +9,12 @@ #include #include #include "common/common_types.h" +#include "core/hle/ipc.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/thread.h" #include "core/hle/result.h" #include "core/memory.h" -namespace Kernel { -class ServerSession; - -// TODO(Subv): Move these declarations out of here -static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header - -/** - * Returns a pointer to the command buffer in the current thread's TLS - * TODO(Subv): This is not entirely correct, the command buffer should be copied from - * the thread's TLS to an intermediate buffer in kernel memory, and then copied again to - * the service handler process' memory. - * @param offset Optional offset into command buffer - * @return Pointer to command buffer - */ -inline u32* GetCommandBuffer(const int offset = 0) { - return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + - offset); -} -} - -// TODO(Subv): Move this namespace out of here -namespace IPC { - -enum DescriptorType : u32 { - // Buffer related desciptors types (mask : 0x0F) - StaticBuffer = 0x02, - PXIBuffer = 0x04, - MappedBuffer = 0x08, - // Handle related descriptors types (mask : 0x30, but need to check for buffer related - // descriptors first ) - CopyHandle = 0x00, - MoveHandle = 0x10, - CallingPid = 0x20, -}; - -/** - * @brief Creates a command header to be used for IPC - * @param command_id ID of the command to create a header for. - * @param normal_params Size of the normal parameters in words. Up to 63. - * @param translate_params_size Size of the translate parameters in words. Up to 63. - * @return The created IPC header. - * - * Normal parameters are sent directly to the process while the translate parameters might go - * through modifications and checks by the kernel. - * The translate parameters are described by headers generated with the IPC::*Desc functions. - * - * @note While #normal_params is equivalent to the number of normal parameters, - * #translate_params_size includes the size occupied by the translate parameters headers. - */ -constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, - unsigned int translate_params_size) { - return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | - (u32(translate_params_size) & 0x3F); -} - -union Header { - u32 raw; - BitField<0, 6, u32> translate_params_size; - BitField<6, 6, u32> normal_params; - BitField<16, 16, u32> command_id; -}; - -inline Header ParseHeader(u32 header) { - return {header}; -} - -constexpr u32 MoveHandleDesc(u32 num_handles = 1) { - return MoveHandle | ((num_handles - 1) << 26); -} - -constexpr u32 CopyHandleDesc(u32 num_handles = 1) { - return CopyHandle | ((num_handles - 1) << 26); -} - -constexpr u32 CallingPidDesc() { - return CallingPid; -} - -constexpr bool isHandleDescriptor(u32 descriptor) { - return (descriptor & 0xF) == 0x0; -} - -constexpr u32 HandleNumberFromDesc(u32 handle_descriptor) { - return (handle_descriptor >> 26) + 1; -} - -constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) { - return StaticBuffer | (size << 14) | ((buffer_id & 0xF) << 10); -} - -union StaticBufferDescInfo { - u32 raw; - BitField<10, 4, u32> buffer_id; - BitField<14, 18, u32> size; -}; - -inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { - return {desc}; -} - -/** - * @brief Creates a header describing a buffer to be sent over PXI. - * @param size Size of the buffer. Max 0x00FFFFFF. - * @param buffer_id The Id of the buffer. Max 0xF. - * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have - * read-write access. - * @return The created PXI buffer header. - * - * The next value is a phys-address of a table located in the BASE memregion. - */ -inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { - u32 type = PXIBuffer; - if (is_read_only) - type |= 0x2; - return type | (size << 8) | ((buffer_id & 0xF) << 4); -} - -enum MappedBufferPermissions { - R = 1, - W = 2, - RW = R | W, -}; - -constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) { - return MappedBuffer | (size << 4) | (u32(perms) << 1); -} - -union MappedBufferDescInfo { - u32 raw; - BitField<4, 28, u32> size; - BitField<1, 2, MappedBufferPermissions> perms; -}; - -inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { - return{ desc }; -} - -inline DescriptorType GetDescriptorType(u32 descriptor) { - // Note: Those checks must be done in this order - if (isHandleDescriptor(descriptor)) - return (DescriptorType)(descriptor & 0x30); - - // handle the fact that the following descriptors can have rights - if (descriptor & MappedBuffer) - return MappedBuffer; - - if (descriptor & PXIBuffer) - return PXIBuffer; - - return StaticBuffer; -} - -} // namespace IPC - //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace Service @@ -220,9 +67,9 @@ public: * @param max_sessions Maximum number of sessions that can be * connected to this service at the same time. */ - Interface(u32 max_sessions = DefaultMaxSessions) : max_sessions(max_sessions) { } + Interface(u32 max_sessions = DefaultMaxSessions); - virtual ~Interface() = default; + virtual ~Interface(); std::string GetName() const { return GetPortName(); diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index ff7a84347..37420201b 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -87,12 +87,7 @@ static void GetServiceHandle(Service::Interface* self) { if (it != Service::g_srv_services.end()) { auto client_port = it->second; - // Note: Threads do not wait for the server endpoint to call - // AcceptSession before returning from this call. - - // Connect to the port and retrieve the client endpoint of the connection Session. auto client_session = client_port->Connect(); - res = client_session.Code(); if (client_session.Succeeded()) { -- cgit v1.2.3 From 386112da3265d111595329508b860800e5cf14e8 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 8 Dec 2016 15:01:10 -0500 Subject: Added a framework for partially handling Session disconnections. Further implementation will happen in a future commit. Fixes a regression. --- src/core/hle/service/fs/archive.cpp | 1 + src/core/hle/service/fs/fs_user.cpp | 3 +++ src/core/hle/service/service.cpp | 10 ++++++++++ src/core/hle/service/service.h | 18 ++++++++++++++++++ 4 files changed, 32 insertions(+) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index c10d6a3a9..b63c6eaac 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -174,6 +174,7 @@ void File::HandleSyncRequestImpl(Kernel::SharedPtr server case FileCommand::OpenLinkFile: { LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); auto sessions = Kernel::ServerSession::CreateSessionPair(GetName(), shared_from_this()); + ClientConnected(std::get>(sessions)); cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).ValueOr(INVALID_HANDLE); break; } diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index a29bce22a..ea1050fb6 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -73,6 +73,7 @@ static void OpenFile(Service::Interface* self) { if (file_res.Succeeded()) { std::shared_ptr file = *file_res; auto sessions = ServerSession::CreateSessionPair(file->GetName(), file); + file->ClientConnected(std::get>(sessions)); cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).MoveFrom(); } else { cmd_buff[3] = 0; @@ -135,6 +136,7 @@ static void OpenFileDirectly(Service::Interface* self) { if (file_res.Succeeded()) { std::shared_ptr file = *file_res; auto sessions = ServerSession::CreateSessionPair(file->GetName(), file); + file->ClientConnected(std::get>(sessions)); cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).MoveFrom(); } else { cmd_buff[3] = 0; @@ -398,6 +400,7 @@ static void OpenDirectory(Service::Interface* self) { if (dir_res.Succeeded()) { std::shared_ptr directory = *dir_res; auto sessions = ServerSession::CreateSessionPair(directory->GetName(), directory); + directory->ClientConnected(std::get>(sessions)); cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).MoveFrom(); } else { LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s", diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 6ea5cf745..167cb09a8 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include "common/logging/log.h" #include "common/string_util.h" @@ -79,6 +81,14 @@ ResultCode SessionRequestHandler::HandleSyncRequest(Kernel::SharedPtr server_session) { + connected_sessions.push_back(server_session); +} + +void SessionRequestHandler::ClientDisconnected(Kernel::SharedPtr server_session) { + boost::range::remove_erase(connected_sessions, server_session); +} + ResultCode SessionRequestHandler::TranslateRequest(Kernel::SharedPtr server_session) { // TODO(Subv): Implement this function once multiple concurrent processes are supported. return RESULT_SUCCESS; diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index ba5ba062e..2293b473a 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -38,6 +38,20 @@ public: */ ResultCode HandleSyncRequest(Kernel::SharedPtr server_session); + /** + * Signals that a client has just connected to this HLE handler and keeps the + * associated ServerSession alive for the duration of the connection. + * @param server_session Owning pointer to the ServerSession associated with the connection. + */ + void ClientConnected(Kernel::SharedPtr server_session); + + /** + * Signals that a client has just disconnected from this HLE handler and releases the + * associated ServerSession. + * @param server_session ServerSession associated with the connection. + */ + void ClientDisconnected(Kernel::SharedPtr server_session); + protected: /** * Handles a sync request from the emulated application and writes the response to the command buffer. @@ -55,6 +69,10 @@ private: * but once that is implemented we'll need to properly translate all descriptors in the command buffer. */ ResultCode TranslateRequest(Kernel::SharedPtr server_session); + + /// List of sessions that are connected to this handler. + /// A ServerSession whose server endpoint is an HLE implementation is kept alive by this list for the duration of the connection. + std::vector> connected_sessions; }; /** -- cgit v1.2.3 From deb83c9fc5c27ca8c50db0b00deb9cd798a814e7 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Dec 2016 12:39:12 -0500 Subject: Kernel/IPC: Small codestyle cleanup --- src/core/hle/service/service.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 167cb09a8..4f973c634 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -94,8 +94,8 @@ ResultCode SessionRequestHandler::TranslateRequest(Kernel::SharedPtr server_session) { // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which session triggered each command. -- cgit v1.2.3 From ebbb55ec8f827096f1c743cc4b7f4a2aa05a3ed3 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Dec 2016 12:52:12 -0500 Subject: Moved the HLE command buffer translation task to ServerSession instead of the HLE handler superclass. --- src/core/hle/service/fs/archive.cpp | 4 ++-- src/core/hle/service/fs/archive.h | 4 ++-- src/core/hle/service/service.cpp | 22 +--------------------- src/core/hle/service/service.h | 30 ++++++++++-------------------- 4 files changed, 15 insertions(+), 45 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index b63c6eaac..bca57061e 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -93,7 +93,7 @@ File::File(std::unique_ptr&& backend, const FileSys::Path& File::~File() {} -void File::HandleSyncRequestImpl(Kernel::SharedPtr server_session) { +void File::HandleSyncRequest(Kernel::SharedPtr server_session) { u32* cmd_buff = Kernel::GetCommandBuffer(); FileCommand cmd = static_cast(cmd_buff[0]); switch (cmd) { @@ -207,7 +207,7 @@ Directory::Directory(std::unique_ptr&& backend, Directory::~Directory() {} -void Directory::HandleSyncRequestImpl(Kernel::SharedPtr server_session) { +void Directory::HandleSyncRequest(Kernel::SharedPtr server_session) { u32* cmd_buff = Kernel::GetCommandBuffer(); DirectoryCommand cmd = static_cast(cmd_buff[0]); switch (cmd) { diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 09a922fb5..eb76706a1 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -55,7 +55,7 @@ public: std::unique_ptr backend; ///< File backend interface protected: - void HandleSyncRequestImpl(Kernel::SharedPtr server_session) override; + void HandleSyncRequest(Kernel::SharedPtr server_session) override; }; class Directory final : public SessionRequestHandler { @@ -71,7 +71,7 @@ public: std::unique_ptr backend; ///< File backend interface protected: - void HandleSyncRequestImpl(Kernel::SharedPtr server_session) override; + void HandleSyncRequest(Kernel::SharedPtr server_session) override; }; /** diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 4f973c634..418b128b1 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -66,21 +66,6 @@ static std::string MakeFunctionString(const char* name, const char* port_name, return function_string; } -ResultCode SessionRequestHandler::HandleSyncRequest(Kernel::SharedPtr server_session) { - // Attempt to translate the incoming request's command buffer. - ResultCode result = TranslateRequest(server_session); - - if (result.IsError()) - return result; - - // Actually handle the request - HandleSyncRequestImpl(server_session); - - // TODO(Subv): Translate the response command buffer. - - return RESULT_SUCCESS; -} - void SessionRequestHandler::ClientConnected(Kernel::SharedPtr server_session) { connected_sessions.push_back(server_session); } @@ -89,15 +74,10 @@ void SessionRequestHandler::ClientDisconnected(Kernel::SharedPtr server_session) { - // TODO(Subv): Implement this function once multiple concurrent processes are supported. - return RESULT_SUCCESS; -} - Interface::Interface(u32 max_sessions) : max_sessions(max_sessions) {} Interface::~Interface() = default; -void Interface::HandleSyncRequestImpl(Kernel::SharedPtr server_session) { +void Interface::HandleSyncRequest(Kernel::SharedPtr server_session) { // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which session triggered each command. u32* cmd_buff = Kernel::GetCommandBuffer(); diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 2293b473a..a3af48684 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -15,6 +15,11 @@ #include "core/hle/result.h" #include "core/memory.h" + +namespace Kernel { +class ServerSession; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace Service @@ -31,12 +36,14 @@ static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maxim class SessionRequestHandler { public: /** - * Dispatches and handles a sync request from the emulated application. + * Handles a sync request from the emulated application. * @param server_session The ServerSession that was triggered for this sync request, * it should be used to differentiate which client (As in ClientSession) we're answering to. + * TODO(Subv): Use a wrapper structure to hold all the information relevant to + * this request (ServerSession, Originator thread, Translated command buffer, etc). * @returns ResultCode the result code of the translate operation. */ - ResultCode HandleSyncRequest(Kernel::SharedPtr server_session); + virtual void HandleSyncRequest(Kernel::SharedPtr server_session) = 0; /** * Signals that a client has just connected to this HLE handler and keeps the @@ -53,23 +60,6 @@ public: void ClientDisconnected(Kernel::SharedPtr server_session); protected: - /** - * Handles a sync request from the emulated application and writes the response to the command buffer. - * TODO(Subv): Use a wrapper structure to hold all the information relevant to - * this request (ServerSession, Originator thread, Translated command buffer, etc). - */ - virtual void HandleSyncRequestImpl(Kernel::SharedPtr server_session) = 0; - -private: - /** - * Performs command buffer translation for this 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 TranslateRequest(Kernel::SharedPtr server_session); - /// List of sessions that are connected to this handler. /// A ServerSession whose server endpoint is an HLE implementation is kept alive by this list for the duration of the connection. std::vector> connected_sessions; @@ -120,7 +110,7 @@ public: } protected: - void HandleSyncRequestImpl(Kernel::SharedPtr server_session) override; + void HandleSyncRequest(Kernel::SharedPtr server_session) override; /** * Registers the functions in the service -- cgit v1.2.3 From 016307ae656afc85ab59a5c2598205ef81f99231 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 14 Dec 2016 12:33:49 -0500 Subject: Fixed the codestyle to match our clang-format rules. --- src/core/hle/service/apt/apt.h | 3 ++- src/core/hle/service/fs/archive.cpp | 10 ++++++---- src/core/hle/service/fs/archive.h | 6 +++--- src/core/hle/service/fs/fs_user.cpp | 21 +++++++++++++++------ src/core/hle/service/service.cpp | 21 ++++++++++++--------- src/core/hle/service/service.h | 21 +++++++++++++-------- src/core/hle/service/srv.cpp | 2 +- 7 files changed, 52 insertions(+), 32 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 9bc6327ed..bcc437f93 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -14,7 +14,8 @@ class Interface; namespace APT { -static const u32 MaxAPTSessions = 2; ///< Each APT service can only have up to 2 sessions connected at the same time. +/// Each APT service can only have up to 2 sessions connected at the same time. +static const u32 MaxAPTSessions = 2; /// Holds information about the parameters used in Send/Glance/ReceiveParameter struct MessageParameter { diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index bca57061e..6184e6f1b 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -175,7 +175,9 @@ void File::HandleSyncRequest(Kernel::SharedPtr server_ses LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); auto sessions = Kernel::ServerSession::CreateSessionPair(GetName(), shared_from_this()); ClientConnected(std::get>(sessions)); - cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).ValueOr(INVALID_HANDLE); + cmd_buff[3] = Kernel::g_handle_table + .Create(std::get>(sessions)) + .ValueOr(INVALID_HANDLE); break; } @@ -307,8 +309,8 @@ ResultCode RegisterArchiveType(std::unique_ptr&& factor } ResultVal> OpenFileFromArchive(ArchiveHandle archive_handle, - const FileSys::Path& path, - const FileSys::Mode mode) { + const FileSys::Path& path, + const FileSys::Mode mode) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_ARCHIVE_HANDLE; @@ -398,7 +400,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, } ResultVal> OpenDirectoryFromArchive(ArchiveHandle archive_handle, - const FileSys::Path& path) { + const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_ARCHIVE_HANDLE; diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index eb76706a1..82d591897 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -104,8 +104,8 @@ ResultCode RegisterArchiveType(std::unique_ptr&& factor * @return The opened File object */ ResultVal> OpenFileFromArchive(ArchiveHandle archive_handle, - const FileSys::Path& path, - const FileSys::Mode mode); + const FileSys::Path& path, + const FileSys::Mode mode); /** * Delete a File from an Archive @@ -183,7 +183,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, * @return The opened Directory object */ ResultVal> OpenDirectoryFromArchive(ArchiveHandle archive_handle, - const FileSys::Path& path); + const FileSys::Path& path); /** * Get the free space in an Archive diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index ea1050fb6..0b03bea22 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -68,13 +68,16 @@ static void OpenFile(Service::Interface* self) { LOG_DEBUG(Service_FS, "path=%s, mode=%u attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); - ResultVal> file_res = OpenFileFromArchive(archive_handle, file_path, mode); + ResultVal> file_res = + OpenFileFromArchive(archive_handle, file_path, mode); cmd_buff[1] = file_res.Code().raw; if (file_res.Succeeded()) { std::shared_ptr file = *file_res; auto sessions = ServerSession::CreateSessionPair(file->GetName(), file); file->ClientConnected(std::get>(sessions)); - cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).MoveFrom(); + cmd_buff[3] = Kernel::g_handle_table + .Create(std::get>(sessions)) + .MoveFrom(); } else { cmd_buff[3] = 0; LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); @@ -131,13 +134,16 @@ static void OpenFileDirectly(Service::Interface* self) { } SCOPE_EXIT({ CloseArchive(*archive_handle); }); - ResultVal> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); + ResultVal> file_res = + OpenFileFromArchive(*archive_handle, file_path, mode); cmd_buff[1] = file_res.Code().raw; if (file_res.Succeeded()) { std::shared_ptr file = *file_res; auto sessions = ServerSession::CreateSessionPair(file->GetName(), file); file->ClientConnected(std::get>(sessions)); - cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).MoveFrom(); + cmd_buff[3] = Kernel::g_handle_table + .Create(std::get>(sessions)) + .MoveFrom(); } else { cmd_buff[3] = 0; LOG_ERROR(Service_FS, "failed to get a handle for file %s mode=%u attributes=%u", @@ -395,13 +401,16 @@ static void OpenDirectory(Service::Interface* self) { LOG_DEBUG(Service_FS, "type=%u size=%u data=%s", static_cast(dirname_type), dirname_size, dir_path.DebugStr().c_str()); - ResultVal> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); + ResultVal> dir_res = + OpenDirectoryFromArchive(archive_handle, dir_path); cmd_buff[1] = dir_res.Code().raw; if (dir_res.Succeeded()) { std::shared_ptr directory = *dir_res; auto sessions = ServerSession::CreateSessionPair(directory->GetName(), directory); directory->ClientConnected(std::get>(sessions)); - cmd_buff[3] = Kernel::g_handle_table.Create(std::get>(sessions)).MoveFrom(); + cmd_buff[3] = Kernel::g_handle_table + .Create(std::get>(sessions)) + .MoveFrom(); } else { LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s", 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 418b128b1..9f68898db 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -8,7 +8,6 @@ #include "common/string_util.h" #include "core/hle/kernel/server_port.h" -#include "core/hle/service/service.h" #include "core/hle/service/ac_u.h" #include "core/hle/service/act_a.h" #include "core/hle/service/act_u.h" @@ -66,11 +65,13 @@ static std::string MakeFunctionString(const char* name, const char* port_name, return function_string; } -void SessionRequestHandler::ClientConnected(Kernel::SharedPtr server_session) { +void SessionRequestHandler::ClientConnected( + Kernel::SharedPtr server_session) { connected_sessions.push_back(server_session); } -void SessionRequestHandler::ClientDisconnected(Kernel::SharedPtr server_session) { +void SessionRequestHandler::ClientDisconnected( + Kernel::SharedPtr server_session) { boost::range::remove_erase(connected_sessions, server_session); } @@ -78,7 +79,8 @@ Interface::Interface(u32 max_sessions) : max_sessions(max_sessions) {} Interface::~Interface() = default; void Interface::HandleSyncRequest(Kernel::SharedPtr server_session) { - // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which session triggered each command. + // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which + // session triggered each command. u32* cmd_buff = Kernel::GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); @@ -113,15 +115,17 @@ void Interface::Register(const FunctionInfo* functions, size_t n) { // Module interface static void AddNamedPort(Interface* interface_) { - auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), - std::shared_ptr(interface_)); + auto ports = + Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), + std::shared_ptr(interface_)); auto client_port = std::get>(ports); g_kernel_named_ports.emplace(interface_->GetPortName(), std::move(client_port)); } void AddService(Interface* interface_) { - auto ports = Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), - std::shared_ptr(interface_)); + auto ports = + Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName(), + std::shared_ptr(interface_)); auto client_port = std::get>(ports); g_srv_services.emplace(interface_->GetPortName(), std::move(client_port)); } @@ -190,5 +194,4 @@ void Shutdown() { g_kernel_named_ports.clear(); LOG_DEBUG(Service, "shutdown OK"); } - } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index a3af48684..a7ba7688f 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -15,7 +15,6 @@ #include "core/hle/result.h" #include "core/memory.h" - namespace Kernel { class ServerSession; } @@ -26,12 +25,13 @@ class ServerSession; namespace Service { static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) -static const u32 DefaultMaxSessions = 10; ///< Arbitrary default number of maximum connections to an HLE service +/// Arbitrary default number of maximum connections to an HLE service. +static const u32 DefaultMaxSessions = 10; /** * Interface implemented by HLE Session handlers. - * This can be provided to a ServerSession in order to hook into several relevant events (such as a new connection or a SyncRequest) - * so they can be implemented in the emulator. + * This can be provided to a ServerSession in order to hook into several relevant events + * (such as a new connection or a SyncRequest) so they can be implemented in the emulator. */ class SessionRequestHandler { public: @@ -61,12 +61,14 @@ public: protected: /// List of sessions that are connected to this handler. - /// A ServerSession whose server endpoint is an HLE implementation is kept alive by this list for the duration of the connection. + /// A ServerSession whose server endpoint is an HLE implementation is kept alive by this list + // for the duration of the connection. std::vector> connected_sessions; }; /** - * Framework for implementing HLE service handlers which dispatch incoming SyncRequests based on a table mapping header ids to handler functions. + * Framework for implementing HLE service handlers which dispatch incoming SyncRequests based on a + * table mapping header ids to handler functions. */ class Interface : public SessionRequestHandler { public: @@ -88,10 +90,13 @@ public: } /** - * Gets the maximum allowed number of sessions that can be connected to this service at the same time. + * Gets the maximum allowed number of sessions that can be connected to this service + * at the same time. * @returns The maximum number of connections allowed. */ - u32 GetMaxSessions() const { return max_sessions; } + u32 GetMaxSessions() const { + return max_sessions; + } typedef void (*Function)(Interface*); diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 37420201b..18d0a699d 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -7,8 +7,8 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "core/hle/kernel/client_session.h" -#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/event.h" +#include "core/hle/kernel/server_session.h" #include "core/hle/service/srv.h" //////////////////////////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3