diff options
| author | 2021-05-15 23:49:03 -0700 | |
|---|---|---|
| committer | 2021-05-20 21:41:49 -0700 | |
| commit | 7361eac10ff8991f16165190792a948a02b9b756 (patch) | |
| tree | 9fdd0bd629afb6a6d20602c341e74511de2cc135 /src/core/hle/kernel | |
| parent | Revert "WORKAROUND: temp. disable session resource limits while we work out i... (diff) | |
| download | yuzu-7361eac10ff8991f16165190792a948a02b9b756.tar.gz yuzu-7361eac10ff8991f16165190792a948a02b9b756.tar.xz yuzu-7361eac10ff8991f16165190792a948a02b9b756.zip | |
hle: kernel: Implement CloneCurrentObject and improve session management.
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 20 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 82 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_client_port.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_port.cpp | 7 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_port.h | 16 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_session.cpp | 35 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_session.h | 36 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_session.h | 4 |
8 files changed, 130 insertions, 73 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 24700f7a5..689f58cf6 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -35,11 +35,11 @@ SessionRequestHandler::SessionRequestHandler() = default; | |||
| 35 | SessionRequestHandler::~SessionRequestHandler() = default; | 35 | SessionRequestHandler::~SessionRequestHandler() = default; |
| 36 | 36 | ||
| 37 | void SessionRequestHandler::ClientConnected(KServerSession* session) { | 37 | void SessionRequestHandler::ClientConnected(KServerSession* session) { |
| 38 | session->SetHleHandler(shared_from_this()); | 38 | session->SetSessionHandler(shared_from_this()); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { | 41 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { |
| 42 | session->SetHleHandler(nullptr); | 42 | session->SetSessionHandler(nullptr); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, | 45 | HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, |
| @@ -186,18 +186,6 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_t | |||
| 186 | auto& owner_process = *requesting_thread.GetOwnerProcess(); | 186 | auto& owner_process = *requesting_thread.GetOwnerProcess(); |
| 187 | auto& handle_table = owner_process.GetHandleTable(); | 187 | auto& handle_table = owner_process.GetHandleTable(); |
| 188 | 188 | ||
| 189 | // The data_size already includes the payload header, the padding and the domain header. | ||
| 190 | std::size_t size{}; | ||
| 191 | |||
| 192 | if (IsTipc()) { | ||
| 193 | size = cmd_buf.size(); | ||
| 194 | } else { | ||
| 195 | size = data_payload_offset + data_size - sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4; | ||
| 196 | if (Session()->IsDomain()) { | ||
| 197 | size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | for (auto& object : copy_objects) { | 189 | for (auto& object : copy_objects) { |
| 202 | Handle handle{}; | 190 | Handle handle{}; |
| 203 | if (object) { | 191 | if (object) { |
| @@ -222,7 +210,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_t | |||
| 222 | if (Session()->IsDomain()) { | 210 | if (Session()->IsDomain()) { |
| 223 | current_offset = domain_offset - static_cast<u32>(domain_objects.size()); | 211 | current_offset = domain_offset - static_cast<u32>(domain_objects.size()); |
| 224 | for (const auto& object : domain_objects) { | 212 | for (const auto& object : domain_objects) { |
| 225 | server_session->AppendDomainRequestHandler(object); | 213 | server_session->AppendDomainHandler(object); |
| 226 | cmd_buf[current_offset++] = | 214 | cmd_buf[current_offset++] = |
| 227 | static_cast<u32_le>(server_session->NumDomainRequestHandlers()); | 215 | static_cast<u32_le>(server_session->NumDomainRequestHandlers()); |
| 228 | } | 216 | } |
| @@ -230,7 +218,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_t | |||
| 230 | 218 | ||
| 231 | // Copy the translated command buffer back into the thread's command buffer area. | 219 | // Copy the translated command buffer back into the thread's command buffer area. |
| 232 | memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), cmd_buf.data(), | 220 | memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), cmd_buf.data(), |
| 233 | size * sizeof(u32)); | 221 | write_size * sizeof(u32)); |
| 234 | 222 | ||
| 235 | return RESULT_SUCCESS; | 223 | return RESULT_SUCCESS; |
| 236 | } | 224 | } |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index e1b128281..51cd1a898 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | #include <type_traits> | 12 | #include <type_traits> |
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #include <boost/container/small_vector.hpp> | 14 | #include <boost/container/small_vector.hpp> |
| 15 | |||
| 16 | #include "common/assert.h" | ||
| 15 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 16 | #include "common/concepts.h" | 18 | #include "common/concepts.h" |
| 17 | #include "common/swap.h" | 19 | #include "common/swap.h" |
| @@ -84,6 +86,69 @@ public: | |||
| 84 | void ClientDisconnected(KServerSession* session); | 86 | void ClientDisconnected(KServerSession* session); |
| 85 | }; | 87 | }; |
| 86 | 88 | ||
| 89 | using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>; | ||
| 90 | |||
| 91 | /** | ||
| 92 | * Manages the underlying HLE requests for a session, and whether (or not) the session should be | ||
| 93 | * treated as a domain. This is managed separately from server sessions, as this state is shared | ||
| 94 | * when objects are cloned. | ||
| 95 | */ | ||
| 96 | class SessionRequestManager final { | ||
| 97 | public: | ||
| 98 | SessionRequestManager() = default; | ||
| 99 | |||
| 100 | bool IsDomain() const { | ||
| 101 | return is_domain; | ||
| 102 | } | ||
| 103 | |||
| 104 | void ConvertToDomain() { | ||
| 105 | domain_handlers = {session_handler}; | ||
| 106 | is_domain = true; | ||
| 107 | } | ||
| 108 | |||
| 109 | std::size_t DomainHandlerCount() const { | ||
| 110 | return domain_handlers.size(); | ||
| 111 | } | ||
| 112 | |||
| 113 | bool HasSessionHandler() const { | ||
| 114 | return session_handler != nullptr; | ||
| 115 | } | ||
| 116 | |||
| 117 | SessionRequestHandler& SessionHandler() { | ||
| 118 | return *session_handler; | ||
| 119 | } | ||
| 120 | |||
| 121 | const SessionRequestHandler& SessionHandler() const { | ||
| 122 | return *session_handler; | ||
| 123 | } | ||
| 124 | |||
| 125 | void CloseDomainHandler(std::size_t index) { | ||
| 126 | if (index < DomainHandlerCount()) { | ||
| 127 | domain_handlers[index] = nullptr; | ||
| 128 | } else { | ||
| 129 | UNREACHABLE_MSG("Unexpected handler index {}", index); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | SessionRequestHandlerPtr DomainHandler(std::size_t index) const { | ||
| 134 | ASSERT_MSG(index < DomainHandlerCount(), "Unexpected handler index {}", index); | ||
| 135 | return domain_handlers.at(index); | ||
| 136 | } | ||
| 137 | |||
| 138 | void AppendDomainHandler(SessionRequestHandlerPtr&& handler) { | ||
| 139 | domain_handlers.emplace_back(std::move(handler)); | ||
| 140 | } | ||
| 141 | |||
| 142 | void SetSessionHandler(SessionRequestHandlerPtr&& handler) { | ||
| 143 | session_handler = std::move(handler); | ||
| 144 | } | ||
| 145 | |||
| 146 | private: | ||
| 147 | bool is_domain{}; | ||
| 148 | SessionRequestHandlerPtr session_handler; | ||
| 149 | std::vector<SessionRequestHandlerPtr> domain_handlers; | ||
| 150 | }; | ||
| 151 | |||
| 87 | /** | 152 | /** |
| 88 | * Class containing information about an in-flight IPC request being handled by an HLE service | 153 | * Class containing information about an in-flight IPC request being handled by an HLE service |
| 89 | * implementation. Services should avoid using old global APIs (e.g. Kernel::GetCommandBuffer()) and | 154 | * implementation. Services should avoid using old global APIs (e.g. Kernel::GetCommandBuffer()) and |
| @@ -239,18 +304,17 @@ public: | |||
| 239 | copy_objects.emplace_back(object); | 304 | copy_objects.emplace_back(object); |
| 240 | } | 305 | } |
| 241 | 306 | ||
| 242 | void AddDomainObject(std::shared_ptr<SessionRequestHandler> object) { | 307 | void AddDomainObject(SessionRequestHandlerPtr object) { |
| 243 | domain_objects.emplace_back(std::move(object)); | 308 | domain_objects.emplace_back(std::move(object)); |
| 244 | } | 309 | } |
| 245 | 310 | ||
| 246 | template <typename T> | 311 | template <typename T> |
| 247 | std::shared_ptr<T> GetDomainRequestHandler(std::size_t index) const { | 312 | std::shared_ptr<T> GetDomainHandler(std::size_t index) const { |
| 248 | return std::static_pointer_cast<T>(domain_request_handlers.at(index)); | 313 | return std::static_pointer_cast<T>(manager->DomainHandler(index)); |
| 249 | } | 314 | } |
| 250 | 315 | ||
| 251 | void SetDomainRequestHandlers( | 316 | void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) { |
| 252 | const std::vector<std::shared_ptr<SessionRequestHandler>>& handlers) { | 317 | manager = std::move(manager_); |
| 253 | domain_request_handlers = handlers; | ||
| 254 | } | 318 | } |
| 255 | 319 | ||
| 256 | /// Clears the list of objects so that no lingering objects are written accidentally to the | 320 | /// Clears the list of objects so that no lingering objects are written accidentally to the |
| @@ -297,7 +361,7 @@ private: | |||
| 297 | boost::container::small_vector<Handle, 8> copy_handles; | 361 | boost::container::small_vector<Handle, 8> copy_handles; |
| 298 | boost::container::small_vector<KAutoObject*, 8> move_objects; | 362 | boost::container::small_vector<KAutoObject*, 8> move_objects; |
| 299 | boost::container::small_vector<KAutoObject*, 8> copy_objects; | 363 | boost::container::small_vector<KAutoObject*, 8> copy_objects; |
| 300 | boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; | 364 | boost::container::small_vector<SessionRequestHandlerPtr, 8> domain_objects; |
| 301 | 365 | ||
| 302 | std::optional<IPC::CommandHeader> command_header; | 366 | std::optional<IPC::CommandHeader> command_header; |
| 303 | std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header; | 367 | std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header; |
| @@ -311,12 +375,12 @@ private: | |||
| 311 | 375 | ||
| 312 | u32_le command{}; | 376 | u32_le command{}; |
| 313 | u64 pid{}; | 377 | u64 pid{}; |
| 378 | u32 write_size{}; | ||
| 314 | u32 data_payload_offset{}; | 379 | u32 data_payload_offset{}; |
| 315 | u32 handles_offset{}; | 380 | u32 handles_offset{}; |
| 316 | u32 domain_offset{}; | 381 | u32 domain_offset{}; |
| 317 | u32 data_size{}; | ||
| 318 | 382 | ||
| 319 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; | 383 | std::shared_ptr<SessionRequestManager> manager; |
| 320 | bool is_thread_waiting{}; | 384 | bool is_thread_waiting{}; |
| 321 | 385 | ||
| 322 | KernelCore& kernel; | 386 | KernelCore& kernel; |
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index d00ce3ddd..8501156e8 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h | |||
| @@ -31,6 +31,9 @@ public: | |||
| 31 | const KPort* GetParent() const { | 31 | const KPort* GetParent() const { |
| 32 | return parent; | 32 | return parent; |
| 33 | } | 33 | } |
| 34 | KPort* GetParent() { | ||
| 35 | return parent; | ||
| 36 | } | ||
| 34 | 37 | ||
| 35 | s32 GetNumSessions() const { | 38 | s32 GetNumSessions() const { |
| 36 | return num_sessions; | 39 | return num_sessions; |
diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp index feb2bb11f..723a1b571 100644 --- a/src/core/hle/kernel/k_port.cpp +++ b/src/core/hle/kernel/k_port.cpp | |||
| @@ -56,11 +56,8 @@ ResultCode KPort::EnqueueSession(KServerSession* session) { | |||
| 56 | 56 | ||
| 57 | R_UNLESS(state == State::Normal, ResultPortClosed); | 57 | R_UNLESS(state == State::Normal, ResultPortClosed); |
| 58 | 58 | ||
| 59 | if (server.HasHLEHandler()) { | 59 | server.GetSessionRequestHandler()->ClientConnected(session); |
| 60 | server.GetHLEHandler()->ClientConnected(session); | 60 | server.EnqueueSession(session); |
| 61 | } else { | ||
| 62 | server.EnqueueSession(session); | ||
| 63 | } | ||
| 64 | 61 | ||
| 65 | return RESULT_SUCCESS; | 62 | return RESULT_SUCCESS; |
| 66 | } | 63 | } |
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h index e76792253..d1a757ec3 100644 --- a/src/core/hle/kernel/k_server_port.h +++ b/src/core/hle/kernel/k_server_port.h | |||
| @@ -32,26 +32,24 @@ public: | |||
| 32 | explicit KServerPort(KernelCore& kernel_); | 32 | explicit KServerPort(KernelCore& kernel_); |
| 33 | virtual ~KServerPort() override; | 33 | virtual ~KServerPort() override; |
| 34 | 34 | ||
| 35 | using HLEHandler = std::shared_ptr<SessionRequestHandler>; | ||
| 36 | |||
| 37 | void Initialize(KPort* parent_, std::string&& name_); | 35 | void Initialize(KPort* parent_, std::string&& name_); |
| 38 | 36 | ||
| 39 | /// Whether or not this server port has an HLE handler available. | 37 | /// Whether or not this server port has an HLE handler available. |
| 40 | bool HasHLEHandler() const { | 38 | bool HasSessionRequestHandler() const { |
| 41 | return hle_handler != nullptr; | 39 | return session_handler != nullptr; |
| 42 | } | 40 | } |
| 43 | 41 | ||
| 44 | /// Gets the HLE handler for this port. | 42 | /// Gets the HLE handler for this port. |
| 45 | HLEHandler GetHLEHandler() const { | 43 | SessionRequestHandlerPtr GetSessionRequestHandler() const { |
| 46 | return hle_handler; | 44 | return session_handler; |
| 47 | } | 45 | } |
| 48 | 46 | ||
| 49 | /** | 47 | /** |
| 50 | * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port | 48 | * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port |
| 51 | * will inherit a reference to this handler. | 49 | * will inherit a reference to this handler. |
| 52 | */ | 50 | */ |
| 53 | void SetHleHandler(HLEHandler hle_handler_) { | 51 | void SetSessionHandler(SessionRequestHandlerPtr&& handler) { |
| 54 | hle_handler = std::move(hle_handler_); | 52 | session_handler = std::move(handler); |
| 55 | } | 53 | } |
| 56 | 54 | ||
| 57 | void EnqueueSession(KServerSession* pending_session); | 55 | void EnqueueSession(KServerSession* pending_session); |
| @@ -73,7 +71,7 @@ private: | |||
| 73 | 71 | ||
| 74 | private: | 72 | private: |
| 75 | SessionList session_list; | 73 | SessionList session_list; |
| 76 | HLEHandler hle_handler; | 74 | SessionRequestHandlerPtr session_handler; |
| 77 | KPort* parent{}; | 75 | KPort* parent{}; |
| 78 | }; | 76 | }; |
| 79 | 77 | ||
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 8850d9af5..457fdfd60 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp | |||
| @@ -23,7 +23,8 @@ | |||
| 23 | 23 | ||
| 24 | namespace Kernel { | 24 | namespace Kernel { |
| 25 | 25 | ||
| 26 | KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | 26 | KServerSession::KServerSession(KernelCore& kernel_) |
| 27 | : KSynchronizationObject{kernel_}, manager{std::make_shared<SessionRequestManager>()} {} | ||
| 27 | 28 | ||
| 28 | KServerSession::~KServerSession() { | 29 | KServerSession::~KServerSession() { |
| 29 | kernel.ReleaseServiceThread(service_thread); | 30 | kernel.ReleaseServiceThread(service_thread); |
| @@ -43,14 +44,8 @@ void KServerSession::Destroy() { | |||
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | void KServerSession::OnClientClosed() { | 46 | void KServerSession::OnClientClosed() { |
| 46 | // We keep a shared pointer to the hle handler to keep it alive throughout | 47 | if (manager->HasSessionHandler()) { |
| 47 | // the call to ClientDisconnected, as ClientDisconnected invalidates the | 48 | manager->SessionHandler().ClientDisconnected(this); |
| 48 | // hle_handler member itself during the course of the function executing. | ||
| 49 | std::shared_ptr<SessionRequestHandler> handler = hle_handler; | ||
| 50 | if (handler) { | ||
| 51 | // Note that after this returns, this server session's hle_handler is | ||
| 52 | // invalidated (set to null). | ||
| 53 | handler->ClientDisconnected(this); | ||
| 54 | } | 49 | } |
| 55 | } | 50 | } |
| 56 | 51 | ||
| @@ -66,12 +61,12 @@ bool KServerSession::IsSignaled() const { | |||
| 66 | return false; | 61 | return false; |
| 67 | } | 62 | } |
| 68 | 63 | ||
| 69 | void KServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) { | 64 | void KServerSession::AppendDomainHandler(SessionRequestHandlerPtr handler) { |
| 70 | domain_request_handlers.push_back(std::move(handler)); | 65 | manager->AppendDomainHandler(std::move(handler)); |
| 71 | } | 66 | } |
| 72 | 67 | ||
| 73 | std::size_t KServerSession::NumDomainRequestHandlers() const { | 68 | std::size_t KServerSession::NumDomainRequestHandlers() const { |
| 74 | return domain_request_handlers.size(); | 69 | return manager->DomainHandlerCount(); |
| 75 | } | 70 | } |
| 76 | 71 | ||
| 77 | ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { | 72 | ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { |
| @@ -80,14 +75,14 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co | |||
| 80 | } | 75 | } |
| 81 | 76 | ||
| 82 | // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs | 77 | // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs |
| 83 | context.SetDomainRequestHandlers(domain_request_handlers); | 78 | context.SetSessionRequestManager(manager); |
| 84 | 79 | ||
| 85 | // If there is a DomainMessageHeader, then this is CommandType "Request" | 80 | // If there is a DomainMessageHeader, then this is CommandType "Request" |
| 86 | const auto& domain_message_header = context.GetDomainMessageHeader(); | 81 | const auto& domain_message_header = context.GetDomainMessageHeader(); |
| 87 | const u32 object_id{domain_message_header.object_id}; | 82 | const u32 object_id{domain_message_header.object_id}; |
| 88 | switch (domain_message_header.command) { | 83 | switch (domain_message_header.command) { |
| 89 | case IPC::DomainMessageHeader::CommandType::SendMessage: | 84 | case IPC::DomainMessageHeader::CommandType::SendMessage: |
| 90 | if (object_id > domain_request_handlers.size()) { | 85 | if (object_id > manager->DomainHandlerCount()) { |
| 91 | LOG_CRITICAL(IPC, | 86 | LOG_CRITICAL(IPC, |
| 92 | "object_id {} is too big! This probably means a recent service call " | 87 | "object_id {} is too big! This probably means a recent service call " |
| 93 | "to {} needed to return a new interface!", | 88 | "to {} needed to return a new interface!", |
| @@ -95,12 +90,12 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co | |||
| 95 | UNREACHABLE(); | 90 | UNREACHABLE(); |
| 96 | return RESULT_SUCCESS; // Ignore error if asserts are off | 91 | return RESULT_SUCCESS; // Ignore error if asserts are off |
| 97 | } | 92 | } |
| 98 | return domain_request_handlers[object_id - 1]->HandleSyncRequest(*this, context); | 93 | return manager->DomainHandler(object_id - 1)->HandleSyncRequest(*this, context); |
| 99 | 94 | ||
| 100 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { | 95 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { |
| 101 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); | 96 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); |
| 102 | 97 | ||
| 103 | domain_request_handlers[object_id - 1] = nullptr; | 98 | manager->CloseDomainHandler(object_id - 1); |
| 104 | 99 | ||
| 105 | IPC::ResponseBuilder rb{context, 2}; | 100 | IPC::ResponseBuilder rb{context, 2}; |
| 106 | rb.Push(RESULT_SUCCESS); | 101 | rb.Push(RESULT_SUCCESS); |
| @@ -133,14 +128,14 @@ ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { | |||
| 133 | if (IsDomain() && context.HasDomainMessageHeader()) { | 128 | if (IsDomain() && context.HasDomainMessageHeader()) { |
| 134 | result = HandleDomainSyncRequest(context); | 129 | result = HandleDomainSyncRequest(context); |
| 135 | // If there is no domain header, the regular session handler is used | 130 | // If there is no domain header, the regular session handler is used |
| 136 | } else if (hle_handler != nullptr) { | 131 | } else if (manager->HasSessionHandler()) { |
| 137 | // If this ServerSession has an associated HLE handler, forward the request to it. | 132 | // If this ServerSession has an associated HLE handler, forward the request to it. |
| 138 | result = hle_handler->HandleSyncRequest(*this, context); | 133 | result = manager->SessionHandler().HandleSyncRequest(*this, context); |
| 139 | } | 134 | } |
| 140 | 135 | ||
| 141 | if (convert_to_domain) { | 136 | if (convert_to_domain) { |
| 142 | ASSERT_MSG(IsSession(), "ServerSession is already a domain instance."); | 137 | ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance."); |
| 143 | domain_request_handlers = {hle_handler}; | 138 | manager->ConvertToDomain(); |
| 144 | convert_to_domain = false; | 139 | convert_to_domain = false; |
| 145 | } | 140 | } |
| 146 | 141 | ||
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index 597d76d38..dd4de2904 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <boost/intrusive/list.hpp> | 12 | #include <boost/intrusive/list.hpp> |
| 13 | 13 | ||
| 14 | #include "common/threadsafe_queue.h" | 14 | #include "common/threadsafe_queue.h" |
| 15 | #include "core/hle/kernel/hle_ipc.h" | ||
| 15 | #include "core/hle/kernel/k_synchronization_object.h" | 16 | #include "core/hle/kernel/k_synchronization_object.h" |
| 16 | #include "core/hle/kernel/service_thread.h" | 17 | #include "core/hle/kernel/service_thread.h" |
| 17 | #include "core/hle/result.h" | 18 | #include "core/hle/result.h" |
| @@ -64,8 +65,8 @@ public: | |||
| 64 | * instead of the regular IPC machinery. (The regular IPC machinery is currently not | 65 | * instead of the regular IPC machinery. (The regular IPC machinery is currently not |
| 65 | * implemented.) | 66 | * implemented.) |
| 66 | */ | 67 | */ |
| 67 | void SetHleHandler(std::shared_ptr<SessionRequestHandler> hle_handler_) { | 68 | void SetSessionHandler(SessionRequestHandlerPtr handler) { |
| 68 | hle_handler = std::move(hle_handler_); | 69 | manager->SetSessionHandler(std::move(handler)); |
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | /** | 72 | /** |
| @@ -82,7 +83,7 @@ public: | |||
| 82 | 83 | ||
| 83 | /// Adds a new domain request handler to the collection of request handlers within | 84 | /// Adds a new domain request handler to the collection of request handlers within |
| 84 | /// this ServerSession instance. | 85 | /// this ServerSession instance. |
| 85 | void AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler); | 86 | void AppendDomainHandler(SessionRequestHandlerPtr handler); |
| 86 | 87 | ||
| 87 | /// Retrieves the total number of domain request handlers that have been | 88 | /// Retrieves the total number of domain request handlers that have been |
| 88 | /// appended to this ServerSession instance. | 89 | /// appended to this ServerSession instance. |
| @@ -90,12 +91,7 @@ public: | |||
| 90 | 91 | ||
| 91 | /// Returns true if the session has been converted to a domain, otherwise False | 92 | /// Returns true if the session has been converted to a domain, otherwise False |
| 92 | bool IsDomain() const { | 93 | bool IsDomain() const { |
| 93 | return !IsSession(); | 94 | return manager->IsDomain(); |
| 94 | } | ||
| 95 | |||
| 96 | /// Returns true if this session has not been converted to a domain, otherwise false. | ||
| 97 | bool IsSession() const { | ||
| 98 | return domain_request_handlers.empty(); | ||
| 99 | } | 95 | } |
| 100 | 96 | ||
| 101 | /// Converts the session to a domain at the end of the current command | 97 | /// Converts the session to a domain at the end of the current command |
| @@ -103,6 +99,21 @@ public: | |||
| 103 | convert_to_domain = true; | 99 | convert_to_domain = true; |
| 104 | } | 100 | } |
| 105 | 101 | ||
| 102 | /// Gets the session request manager, which forwards requests to the underlying service | ||
| 103 | std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() { | ||
| 104 | return manager; | ||
| 105 | } | ||
| 106 | |||
| 107 | /// Gets the session request manager, which forwards requests to the underlying service | ||
| 108 | const std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() const { | ||
| 109 | return manager; | ||
| 110 | } | ||
| 111 | |||
| 112 | /// Sets the session request manager, which forwards requests to the underlying service | ||
| 113 | void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) { | ||
| 114 | manager = std::move(manager_); | ||
| 115 | } | ||
| 116 | |||
| 106 | private: | 117 | private: |
| 107 | /// Queues a sync request from the emulated application. | 118 | /// Queues a sync request from the emulated application. |
| 108 | ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); | 119 | ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); |
| @@ -114,11 +125,8 @@ private: | |||
| 114 | /// object handle. | 125 | /// object handle. |
| 115 | ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); | 126 | ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); |
| 116 | 127 | ||
| 117 | /// This session's HLE request handler (applicable when not a domain) | 128 | /// This session's HLE request handlers |
| 118 | std::shared_ptr<SessionRequestHandler> hle_handler; | 129 | std::shared_ptr<SessionRequestManager> manager; |
| 119 | |||
| 120 | /// This is the list of domain request handlers (after conversion to a domain) | ||
| 121 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; | ||
| 122 | 130 | ||
| 123 | /// When set to True, converts the session to a domain at the end of the command | 131 | /// When set to True, converts the session to a domain at the end of the command |
| 124 | bool convert_to_domain{}; | 132 | bool convert_to_domain{}; |
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index 16901e19c..a981fd1f6 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h | |||
| @@ -66,6 +66,10 @@ public: | |||
| 66 | return port; | 66 | return port; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | KClientPort* GetParent() { | ||
| 70 | return port; | ||
| 71 | } | ||
| 72 | |||
| 69 | private: | 73 | private: |
| 70 | enum class State : u8 { | 74 | enum class State : u8 { |
| 71 | Invalid = 0, | 75 | Invalid = 0, |