diff options
| author | 2022-10-20 18:07:30 -0400 | |
|---|---|---|
| committer | 2022-10-20 18:07:30 -0400 | |
| commit | a6628e8dba0432031a5bc470e5716c831128a357 (patch) | |
| tree | 533eef88596325c5f14b3caf5350cb9a09265afa | |
| parent | Merge pull request #9099 from Docteh/undocked (diff) | |
| parent | kernel: remove most SessionRequestManager handling from KServerSession (diff) | |
| download | yuzu-a6628e8dba0432031a5bc470e5716c831128a357.tar.gz yuzu-a6628e8dba0432031a5bc470e5716c831128a357.tar.xz yuzu-a6628e8dba0432031a5bc470e5716c831128a357.zip | |
Merge pull request #9078 from liamwhite/session-request
kernel: Session request cleanup
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/ipc_helpers.h | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 110 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/init/init_slab_setup.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_client_session.cpp | 15 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_linked_list.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_buffer.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_session.cpp | 232 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_session.h | 41 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_session_request.cpp | 61 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_session_request.h | 307 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_shared_memory_info.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread_local_page.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/slab_helpers.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm_controller.cpp | 5 |
17 files changed, 608 insertions, 200 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e7fe675cb..055bea641 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -243,6 +243,8 @@ add_library(core STATIC | |||
| 243 | hle/kernel/k_server_session.h | 243 | hle/kernel/k_server_session.h |
| 244 | hle/kernel/k_session.cpp | 244 | hle/kernel/k_session.cpp |
| 245 | hle/kernel/k_session.h | 245 | hle/kernel/k_session.h |
| 246 | hle/kernel/k_session_request.cpp | ||
| 247 | hle/kernel/k_session_request.h | ||
| 246 | hle/kernel/k_shared_memory.cpp | 248 | hle/kernel/k_shared_memory.cpp |
| 247 | hle/kernel/k_shared_memory.h | 249 | hle/kernel/k_shared_memory.h |
| 248 | hle/kernel/k_shared_memory_info.h | 250 | hle/kernel/k_shared_memory_info.h |
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 0cc26a211..aa27be767 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -86,13 +86,13 @@ public: | |||
| 86 | u32 num_domain_objects{}; | 86 | u32 num_domain_objects{}; |
| 87 | const bool always_move_handles{ | 87 | const bool always_move_handles{ |
| 88 | (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; | 88 | (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; |
| 89 | if (!ctx.Session()->IsDomain() || always_move_handles) { | 89 | if (!ctx.Session()->GetSessionRequestManager()->IsDomain() || always_move_handles) { |
| 90 | num_handles_to_move = num_objects_to_move; | 90 | num_handles_to_move = num_objects_to_move; |
| 91 | } else { | 91 | } else { |
| 92 | num_domain_objects = num_objects_to_move; | 92 | num_domain_objects = num_objects_to_move; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | if (ctx.Session()->IsDomain()) { | 95 | if (ctx.Session()->GetSessionRequestManager()->IsDomain()) { |
| 96 | raw_data_size += | 96 | raw_data_size += |
| 97 | static_cast<u32>(sizeof(DomainMessageHeader) / sizeof(u32) + num_domain_objects); | 97 | static_cast<u32>(sizeof(DomainMessageHeader) / sizeof(u32) + num_domain_objects); |
| 98 | ctx.write_size += num_domain_objects; | 98 | ctx.write_size += num_domain_objects; |
| @@ -125,7 +125,8 @@ public: | |||
| 125 | if (!ctx.IsTipc()) { | 125 | if (!ctx.IsTipc()) { |
| 126 | AlignWithPadding(); | 126 | AlignWithPadding(); |
| 127 | 127 | ||
| 128 | if (ctx.Session()->IsDomain() && ctx.HasDomainMessageHeader()) { | 128 | if (ctx.Session()->GetSessionRequestManager()->IsDomain() && |
| 129 | ctx.HasDomainMessageHeader()) { | ||
| 129 | IPC::DomainMessageHeader domain_header{}; | 130 | IPC::DomainMessageHeader domain_header{}; |
| 130 | domain_header.num_objects = num_domain_objects; | 131 | domain_header.num_objects = num_domain_objects; |
| 131 | PushRaw(domain_header); | 132 | PushRaw(domain_header); |
| @@ -145,7 +146,7 @@ public: | |||
| 145 | 146 | ||
| 146 | template <class T> | 147 | template <class T> |
| 147 | void PushIpcInterface(std::shared_ptr<T> iface) { | 148 | void PushIpcInterface(std::shared_ptr<T> iface) { |
| 148 | if (context->Session()->IsDomain()) { | 149 | if (context->Session()->GetSessionRequestManager()->IsDomain()) { |
| 149 | context->AddDomainObject(std::move(iface)); | 150 | context->AddDomainObject(std::move(iface)); |
| 150 | } else { | 151 | } else { |
| 151 | kernel.CurrentProcess()->GetResourceLimit()->Reserve( | 152 | kernel.CurrentProcess()->GetResourceLimit()->Reserve( |
| @@ -386,7 +387,7 @@ public: | |||
| 386 | 387 | ||
| 387 | template <class T> | 388 | template <class T> |
| 388 | std::weak_ptr<T> PopIpcInterface() { | 389 | std::weak_ptr<T> PopIpcInterface() { |
| 389 | ASSERT(context->Session()->IsDomain()); | 390 | ASSERT(context->Session()->GetSessionRequestManager()->IsDomain()); |
| 390 | ASSERT(context->GetDomainMessageHeader().input_object_count > 0); | 391 | ASSERT(context->GetDomainMessageHeader().input_object_count > 0); |
| 391 | return context->GetDomainHandler<T>(Pop<u32>() - 1); | 392 | return context->GetDomainHandler<T>(Pop<u32>() - 1); |
| 392 | } | 393 | } |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 5b3feec66..e4f43a053 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include "core/hle/kernel/k_server_session.h" | 19 | #include "core/hle/kernel/k_server_session.h" |
| 20 | #include "core/hle/kernel/k_thread.h" | 20 | #include "core/hle/kernel/k_thread.h" |
| 21 | #include "core/hle/kernel/kernel.h" | 21 | #include "core/hle/kernel/kernel.h" |
| 22 | #include "core/hle/kernel/service_thread.h" | ||
| 22 | #include "core/memory.h" | 23 | #include "core/memory.h" |
| 23 | 24 | ||
| 24 | namespace Kernel { | 25 | namespace Kernel { |
| @@ -56,16 +57,103 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co | |||
| 56 | } | 57 | } |
| 57 | } | 58 | } |
| 58 | 59 | ||
| 60 | Result SessionRequestManager::CompleteSyncRequest(KServerSession* server_session, | ||
| 61 | HLERequestContext& context) { | ||
| 62 | Result result = ResultSuccess; | ||
| 63 | |||
| 64 | // If the session has been converted to a domain, handle the domain request | ||
| 65 | if (this->HasSessionRequestHandler(context)) { | ||
| 66 | if (IsDomain() && context.HasDomainMessageHeader()) { | ||
| 67 | result = HandleDomainSyncRequest(server_session, context); | ||
| 68 | // If there is no domain header, the regular session handler is used | ||
| 69 | } else if (this->HasSessionHandler()) { | ||
| 70 | // If this manager has an associated HLE handler, forward the request to it. | ||
| 71 | result = this->SessionHandler().HandleSyncRequest(*server_session, context); | ||
| 72 | } | ||
| 73 | } else { | ||
| 74 | ASSERT_MSG(false, "Session handler is invalid, stubbing response!"); | ||
| 75 | IPC::ResponseBuilder rb(context, 2); | ||
| 76 | rb.Push(ResultSuccess); | ||
| 77 | } | ||
| 78 | |||
| 79 | if (convert_to_domain) { | ||
| 80 | ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance."); | ||
| 81 | this->ConvertToDomain(); | ||
| 82 | convert_to_domain = false; | ||
| 83 | } | ||
| 84 | |||
| 85 | return result; | ||
| 86 | } | ||
| 87 | |||
| 88 | Result SessionRequestManager::HandleDomainSyncRequest(KServerSession* server_session, | ||
| 89 | HLERequestContext& context) { | ||
| 90 | if (!context.HasDomainMessageHeader()) { | ||
| 91 | return ResultSuccess; | ||
| 92 | } | ||
| 93 | |||
| 94 | // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs | ||
| 95 | context.SetSessionRequestManager(server_session->GetSessionRequestManager()); | ||
| 96 | |||
| 97 | // If there is a DomainMessageHeader, then this is CommandType "Request" | ||
| 98 | const auto& domain_message_header = context.GetDomainMessageHeader(); | ||
| 99 | const u32 object_id{domain_message_header.object_id}; | ||
| 100 | switch (domain_message_header.command) { | ||
| 101 | case IPC::DomainMessageHeader::CommandType::SendMessage: | ||
| 102 | if (object_id > this->DomainHandlerCount()) { | ||
| 103 | LOG_CRITICAL(IPC, | ||
| 104 | "object_id {} is too big! This probably means a recent service call " | ||
| 105 | "needed to return a new interface!", | ||
| 106 | object_id); | ||
| 107 | ASSERT(false); | ||
| 108 | return ResultSuccess; // Ignore error if asserts are off | ||
| 109 | } | ||
| 110 | if (auto strong_ptr = this->DomainHandler(object_id - 1).lock()) { | ||
| 111 | return strong_ptr->HandleSyncRequest(*server_session, context); | ||
| 112 | } else { | ||
| 113 | ASSERT(false); | ||
| 114 | return ResultSuccess; | ||
| 115 | } | ||
| 116 | |||
| 117 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { | ||
| 118 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); | ||
| 119 | |||
| 120 | this->CloseDomainHandler(object_id - 1); | ||
| 121 | |||
| 122 | IPC::ResponseBuilder rb{context, 2}; | ||
| 123 | rb.Push(ResultSuccess); | ||
| 124 | return ResultSuccess; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | LOG_CRITICAL(IPC, "Unknown domain command={}", domain_message_header.command.Value()); | ||
| 129 | ASSERT(false); | ||
| 130 | return ResultSuccess; | ||
| 131 | } | ||
| 132 | |||
| 133 | Result SessionRequestManager::QueueSyncRequest(KSession* parent, | ||
| 134 | std::shared_ptr<HLERequestContext>&& context) { | ||
| 135 | // Ensure we have a session request handler | ||
| 136 | if (this->HasSessionRequestHandler(*context)) { | ||
| 137 | if (auto strong_ptr = this->GetServiceThread().lock()) { | ||
| 138 | strong_ptr->QueueSyncRequest(*parent, std::move(context)); | ||
| 139 | } else { | ||
| 140 | ASSERT_MSG(false, "strong_ptr is nullptr!"); | ||
| 141 | } | ||
| 142 | } else { | ||
| 143 | ASSERT_MSG(false, "handler is invalid!"); | ||
| 144 | } | ||
| 145 | |||
| 146 | return ResultSuccess; | ||
| 147 | } | ||
| 148 | |||
| 59 | void SessionRequestHandler::ClientConnected(KServerSession* session) { | 149 | void SessionRequestHandler::ClientConnected(KServerSession* session) { |
| 60 | session->ClientConnected(shared_from_this()); | 150 | session->GetSessionRequestManager()->SetSessionHandler(shared_from_this()); |
| 61 | 151 | ||
| 62 | // Ensure our server session is tracked globally. | 152 | // Ensure our server session is tracked globally. |
| 63 | kernel.RegisterServerObject(session); | 153 | kernel.RegisterServerObject(session); |
| 64 | } | 154 | } |
| 65 | 155 | ||
| 66 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { | 156 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) {} |
| 67 | session->ClientDisconnected(); | ||
| 68 | } | ||
| 69 | 157 | ||
| 70 | HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, | 158 | HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, |
| 71 | KServerSession* server_session_, KThread* thread_) | 159 | KServerSession* server_session_, KThread* thread_) |
| @@ -126,7 +214,7 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 126 | // Padding to align to 16 bytes | 214 | // Padding to align to 16 bytes |
| 127 | rp.AlignWithPadding(); | 215 | rp.AlignWithPadding(); |
| 128 | 216 | ||
| 129 | if (Session()->IsDomain() && | 217 | if (Session()->GetSessionRequestManager()->IsDomain() && |
| 130 | ((command_header->type == IPC::CommandType::Request || | 218 | ((command_header->type == IPC::CommandType::Request || |
| 131 | command_header->type == IPC::CommandType::RequestWithContext) || | 219 | command_header->type == IPC::CommandType::RequestWithContext) || |
| 132 | !incoming)) { | 220 | !incoming)) { |
| @@ -135,7 +223,7 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 135 | if (incoming || domain_message_header) { | 223 | if (incoming || domain_message_header) { |
| 136 | domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); | 224 | domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); |
| 137 | } else { | 225 | } else { |
| 138 | if (Session()->IsDomain()) { | 226 | if (Session()->GetSessionRequestManager()->IsDomain()) { |
| 139 | LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); | 227 | LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); |
| 140 | } | 228 | } |
| 141 | } | 229 | } |
| @@ -228,12 +316,12 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_threa | |||
| 228 | // Write the domain objects to the command buffer, these go after the raw untranslated data. | 316 | // Write the domain objects to the command buffer, these go after the raw untranslated data. |
| 229 | // TODO(Subv): This completely ignores C buffers. | 317 | // TODO(Subv): This completely ignores C buffers. |
| 230 | 318 | ||
| 231 | if (Session()->IsDomain()) { | 319 | if (server_session->GetSessionRequestManager()->IsDomain()) { |
| 232 | current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size()); | 320 | current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size()); |
| 233 | for (const auto& object : outgoing_domain_objects) { | 321 | for (auto& object : outgoing_domain_objects) { |
| 234 | server_session->AppendDomainHandler(object); | 322 | server_session->GetSessionRequestManager()->AppendDomainHandler(std::move(object)); |
| 235 | cmd_buf[current_offset++] = | 323 | cmd_buf[current_offset++] = static_cast<u32_le>( |
| 236 | static_cast<u32_le>(server_session->NumDomainRequestHandlers()); | 324 | server_session->GetSessionRequestManager()->DomainHandlerCount()); |
| 237 | } | 325 | } |
| 238 | } | 326 | } |
| 239 | 327 | ||
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index e258e2cdf..a0522bca0 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -121,6 +121,10 @@ public: | |||
| 121 | is_domain = true; | 121 | is_domain = true; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | void ConvertToDomainOnRequestEnd() { | ||
| 125 | convert_to_domain = true; | ||
| 126 | } | ||
| 127 | |||
| 124 | std::size_t DomainHandlerCount() const { | 128 | std::size_t DomainHandlerCount() const { |
| 125 | return domain_handlers.size(); | 129 | return domain_handlers.size(); |
| 126 | } | 130 | } |
| @@ -164,7 +168,12 @@ public: | |||
| 164 | 168 | ||
| 165 | bool HasSessionRequestHandler(const HLERequestContext& context) const; | 169 | bool HasSessionRequestHandler(const HLERequestContext& context) const; |
| 166 | 170 | ||
| 171 | Result HandleDomainSyncRequest(KServerSession* server_session, HLERequestContext& context); | ||
| 172 | Result CompleteSyncRequest(KServerSession* server_session, HLERequestContext& context); | ||
| 173 | Result QueueSyncRequest(KSession* parent, std::shared_ptr<HLERequestContext>&& context); | ||
| 174 | |||
| 167 | private: | 175 | private: |
| 176 | bool convert_to_domain{}; | ||
| 168 | bool is_domain{}; | 177 | bool is_domain{}; |
| 169 | SessionRequestHandlerPtr session_handler; | 178 | SessionRequestHandlerPtr session_handler; |
| 170 | std::vector<SessionRequestHandlerPtr> domain_handlers; | 179 | std::vector<SessionRequestHandlerPtr> domain_handlers; |
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index c84d36c8c..477e4e407 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include "core/hle/kernel/k_process.h" | 18 | #include "core/hle/kernel/k_process.h" |
| 19 | #include "core/hle/kernel/k_resource_limit.h" | 19 | #include "core/hle/kernel/k_resource_limit.h" |
| 20 | #include "core/hle/kernel/k_session.h" | 20 | #include "core/hle/kernel/k_session.h" |
| 21 | #include "core/hle/kernel/k_session_request.h" | ||
| 21 | #include "core/hle/kernel/k_shared_memory.h" | 22 | #include "core/hle/kernel/k_shared_memory.h" |
| 22 | #include "core/hle/kernel/k_shared_memory_info.h" | 23 | #include "core/hle/kernel/k_shared_memory_info.h" |
| 23 | #include "core/hle/kernel/k_system_control.h" | 24 | #include "core/hle/kernel/k_system_control.h" |
| @@ -34,6 +35,7 @@ namespace Kernel::Init { | |||
| 34 | HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \ | 35 | HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \ |
| 35 | HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \ | 36 | HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \ |
| 36 | HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \ | 37 | HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \ |
| 38 | HANDLER(KSessionRequest, (SLAB_COUNT(KSession) * 2), ##__VA_ARGS__) \ | ||
| 37 | HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ | 39 | HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ |
| 38 | HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \ | 40 | HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \ |
| 39 | HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ | 41 | HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ |
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp index 8892c5b7c..b4197a8d5 100644 --- a/src/core/hle/kernel/k_client_session.cpp +++ b/src/core/hle/kernel/k_client_session.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/scope_exit.h" | ||
| 4 | #include "core/hle/kernel/hle_ipc.h" | 5 | #include "core/hle/kernel/hle_ipc.h" |
| 5 | #include "core/hle/kernel/k_client_session.h" | 6 | #include "core/hle/kernel/k_client_session.h" |
| 6 | #include "core/hle/kernel/k_server_session.h" | 7 | #include "core/hle/kernel/k_server_session.h" |
| @@ -10,6 +11,8 @@ | |||
| 10 | 11 | ||
| 11 | namespace Kernel { | 12 | namespace Kernel { |
| 12 | 13 | ||
| 14 | static constexpr u32 MessageBufferSize = 0x100; | ||
| 15 | |||
| 13 | KClientSession::KClientSession(KernelCore& kernel_) | 16 | KClientSession::KClientSession(KernelCore& kernel_) |
| 14 | : KAutoObjectWithSlabHeapAndContainer{kernel_} {} | 17 | : KAutoObjectWithSlabHeapAndContainer{kernel_} {} |
| 15 | KClientSession::~KClientSession() = default; | 18 | KClientSession::~KClientSession() = default; |
| @@ -22,8 +25,16 @@ void KClientSession::Destroy() { | |||
| 22 | void KClientSession::OnServerClosed() {} | 25 | void KClientSession::OnServerClosed() {} |
| 23 | 26 | ||
| 24 | Result KClientSession::SendSyncRequest() { | 27 | Result KClientSession::SendSyncRequest() { |
| 25 | // Signal the server session that new data is available | 28 | // Create a session request. |
| 26 | return parent->GetServerSession().OnRequest(); | 29 | KSessionRequest* request = KSessionRequest::Create(kernel); |
| 30 | R_UNLESS(request != nullptr, ResultOutOfResource); | ||
| 31 | SCOPE_EXIT({ request->Close(); }); | ||
| 32 | |||
| 33 | // Initialize the request. | ||
| 34 | request->Initialize(nullptr, GetCurrentThread(kernel).GetTLSAddress(), MessageBufferSize); | ||
| 35 | |||
| 36 | // Send the request. | ||
| 37 | return parent->GetServerSession().OnRequest(request); | ||
| 27 | } | 38 | } |
| 28 | 39 | ||
| 29 | } // namespace Kernel | 40 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_linked_list.h b/src/core/hle/kernel/k_linked_list.h index 78859ced3..29ebd16b7 100644 --- a/src/core/hle/kernel/k_linked_list.h +++ b/src/core/hle/kernel/k_linked_list.h | |||
| @@ -16,6 +16,7 @@ class KLinkedListNode : public boost::intrusive::list_base_hook<>, | |||
| 16 | public KSlabAllocated<KLinkedListNode> { | 16 | public KSlabAllocated<KLinkedListNode> { |
| 17 | 17 | ||
| 18 | public: | 18 | public: |
| 19 | explicit KLinkedListNode(KernelCore&) {} | ||
| 19 | KLinkedListNode() = default; | 20 | KLinkedListNode() = default; |
| 20 | 21 | ||
| 21 | void Initialize(void* it) { | 22 | void Initialize(void* it) { |
diff --git a/src/core/hle/kernel/k_page_buffer.h b/src/core/hle/kernel/k_page_buffer.h index 7e50dc1d1..aef06e213 100644 --- a/src/core/hle/kernel/k_page_buffer.h +++ b/src/core/hle/kernel/k_page_buffer.h | |||
| @@ -13,6 +13,7 @@ namespace Kernel { | |||
| 13 | 13 | ||
| 14 | class KPageBuffer final : public KSlabAllocated<KPageBuffer> { | 14 | class KPageBuffer final : public KSlabAllocated<KPageBuffer> { |
| 15 | public: | 15 | public: |
| 16 | explicit KPageBuffer(KernelCore&) {} | ||
| 16 | KPageBuffer() = default; | 17 | KPageBuffer() = default; |
| 17 | 18 | ||
| 18 | static KPageBuffer* FromPhysicalAddress(Core::System& system, PAddr phys_addr); | 19 | static KPageBuffer* FromPhysicalAddress(Core::System& system, PAddr phys_addr); |
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 4252c9adb..faf03fcc8 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp | |||
| @@ -22,15 +22,12 @@ | |||
| 22 | #include "core/hle/kernel/k_thread.h" | 22 | #include "core/hle/kernel/k_thread.h" |
| 23 | #include "core/hle/kernel/k_thread_queue.h" | 23 | #include "core/hle/kernel/k_thread_queue.h" |
| 24 | #include "core/hle/kernel/kernel.h" | 24 | #include "core/hle/kernel/kernel.h" |
| 25 | #include "core/hle/kernel/service_thread.h" | ||
| 26 | #include "core/memory.h" | 25 | #include "core/memory.h" |
| 27 | 26 | ||
| 28 | namespace Kernel { | 27 | namespace Kernel { |
| 29 | 28 | ||
| 30 | using ThreadQueueImplForKServerSessionRequest = KThreadQueue; | 29 | using ThreadQueueImplForKServerSessionRequest = KThreadQueue; |
| 31 | 30 | ||
| 32 | static constexpr u32 MessageBufferSize = 0x100; | ||
| 33 | |||
| 34 | KServerSession::KServerSession(KernelCore& kernel_) | 31 | KServerSession::KServerSession(KernelCore& kernel_) |
| 35 | : KSynchronizationObject{kernel_}, m_lock{kernel_} {} | 32 | : KSynchronizationObject{kernel_}, m_lock{kernel_} {} |
| 36 | 33 | ||
| @@ -73,59 +70,7 @@ bool KServerSession::IsSignaled() const { | |||
| 73 | } | 70 | } |
| 74 | 71 | ||
| 75 | // Otherwise, we're signaled if we have a request and aren't handling one. | 72 | // Otherwise, we're signaled if we have a request and aren't handling one. |
| 76 | return !m_thread_request_list.empty() && m_current_thread_request == nullptr; | 73 | return !m_request_list.empty() && m_current_request == nullptr; |
| 77 | } | ||
| 78 | |||
| 79 | void KServerSession::AppendDomainHandler(SessionRequestHandlerPtr handler) { | ||
| 80 | manager->AppendDomainHandler(std::move(handler)); | ||
| 81 | } | ||
| 82 | |||
| 83 | std::size_t KServerSession::NumDomainRequestHandlers() const { | ||
| 84 | return manager->DomainHandlerCount(); | ||
| 85 | } | ||
| 86 | |||
| 87 | Result KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { | ||
| 88 | if (!context.HasDomainMessageHeader()) { | ||
| 89 | return ResultSuccess; | ||
| 90 | } | ||
| 91 | |||
| 92 | // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs | ||
| 93 | context.SetSessionRequestManager(manager); | ||
| 94 | |||
| 95 | // If there is a DomainMessageHeader, then this is CommandType "Request" | ||
| 96 | const auto& domain_message_header = context.GetDomainMessageHeader(); | ||
| 97 | const u32 object_id{domain_message_header.object_id}; | ||
| 98 | switch (domain_message_header.command) { | ||
| 99 | case IPC::DomainMessageHeader::CommandType::SendMessage: | ||
| 100 | if (object_id > manager->DomainHandlerCount()) { | ||
| 101 | LOG_CRITICAL(IPC, | ||
| 102 | "object_id {} is too big! This probably means a recent service call " | ||
| 103 | "to {} needed to return a new interface!", | ||
| 104 | object_id, name); | ||
| 105 | ASSERT(false); | ||
| 106 | return ResultSuccess; // Ignore error if asserts are off | ||
| 107 | } | ||
| 108 | if (auto strong_ptr = manager->DomainHandler(object_id - 1).lock()) { | ||
| 109 | return strong_ptr->HandleSyncRequest(*this, context); | ||
| 110 | } else { | ||
| 111 | ASSERT(false); | ||
| 112 | return ResultSuccess; | ||
| 113 | } | ||
| 114 | |||
| 115 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { | ||
| 116 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); | ||
| 117 | |||
| 118 | manager->CloseDomainHandler(object_id - 1); | ||
| 119 | |||
| 120 | IPC::ResponseBuilder rb{context, 2}; | ||
| 121 | rb.Push(ResultSuccess); | ||
| 122 | return ResultSuccess; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | LOG_CRITICAL(IPC, "Unknown domain command={}", domain_message_header.command.Value()); | ||
| 127 | ASSERT(false); | ||
| 128 | return ResultSuccess; | ||
| 129 | } | 74 | } |
| 130 | 75 | ||
| 131 | Result KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) { | 76 | Result KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) { |
| @@ -134,43 +79,11 @@ Result KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& m | |||
| 134 | 79 | ||
| 135 | context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); | 80 | context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); |
| 136 | 81 | ||
| 137 | // Ensure we have a session request handler | 82 | return manager->QueueSyncRequest(parent, std::move(context)); |
| 138 | if (manager->HasSessionRequestHandler(*context)) { | ||
| 139 | if (auto strong_ptr = manager->GetServiceThread().lock()) { | ||
| 140 | strong_ptr->QueueSyncRequest(*parent, std::move(context)); | ||
| 141 | } else { | ||
| 142 | ASSERT_MSG(false, "strong_ptr is nullptr!"); | ||
| 143 | } | ||
| 144 | } else { | ||
| 145 | ASSERT_MSG(false, "handler is invalid!"); | ||
| 146 | } | ||
| 147 | |||
| 148 | return ResultSuccess; | ||
| 149 | } | 83 | } |
| 150 | 84 | ||
| 151 | Result KServerSession::CompleteSyncRequest(HLERequestContext& context) { | 85 | Result KServerSession::CompleteSyncRequest(HLERequestContext& context) { |
| 152 | Result result = ResultSuccess; | 86 | Result result = manager->CompleteSyncRequest(this, context); |
| 153 | |||
| 154 | // If the session has been converted to a domain, handle the domain request | ||
| 155 | if (manager->HasSessionRequestHandler(context)) { | ||
| 156 | if (IsDomain() && context.HasDomainMessageHeader()) { | ||
| 157 | result = HandleDomainSyncRequest(context); | ||
| 158 | // If there is no domain header, the regular session handler is used | ||
| 159 | } else if (manager->HasSessionHandler()) { | ||
| 160 | // If this ServerSession has an associated HLE handler, forward the request to it. | ||
| 161 | result = manager->SessionHandler().HandleSyncRequest(*this, context); | ||
| 162 | } | ||
| 163 | } else { | ||
| 164 | ASSERT_MSG(false, "Session handler is invalid, stubbing response!"); | ||
| 165 | IPC::ResponseBuilder rb(context, 2); | ||
| 166 | rb.Push(ResultSuccess); | ||
| 167 | } | ||
| 168 | |||
| 169 | if (convert_to_domain) { | ||
| 170 | ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance."); | ||
| 171 | manager->ConvertToDomain(); | ||
| 172 | convert_to_domain = false; | ||
| 173 | } | ||
| 174 | 87 | ||
| 175 | // The calling thread is waiting for this request to complete, so wake it up. | 88 | // The calling thread is waiting for this request to complete, so wake it up. |
| 176 | context.GetThread().EndWait(result); | 89 | context.GetThread().EndWait(result); |
| @@ -178,7 +91,7 @@ Result KServerSession::CompleteSyncRequest(HLERequestContext& context) { | |||
| 178 | return result; | 91 | return result; |
| 179 | } | 92 | } |
| 180 | 93 | ||
| 181 | Result KServerSession::OnRequest() { | 94 | Result KServerSession::OnRequest(KSessionRequest* request) { |
| 182 | // Create the wait queue. | 95 | // Create the wait queue. |
| 183 | ThreadQueueImplForKServerSessionRequest wait_queue{kernel}; | 96 | ThreadQueueImplForKServerSessionRequest wait_queue{kernel}; |
| 184 | 97 | ||
| @@ -198,14 +111,13 @@ Result KServerSession::OnRequest() { | |||
| 198 | this->QueueSyncRequest(GetCurrentThreadPointer(kernel), memory); | 111 | this->QueueSyncRequest(GetCurrentThreadPointer(kernel), memory); |
| 199 | } else { | 112 | } else { |
| 200 | // Non-HLE request. | 113 | // Non-HLE request. |
| 201 | auto* thread{GetCurrentThreadPointer(kernel)}; | ||
| 202 | 114 | ||
| 203 | // Get whether we're empty. | 115 | // Get whether we're empty. |
| 204 | const bool was_empty = m_thread_request_list.empty(); | 116 | const bool was_empty = m_request_list.empty(); |
| 205 | 117 | ||
| 206 | // Add the thread to the list. | 118 | // Add the request to the list. |
| 207 | thread->Open(); | 119 | request->Open(); |
| 208 | m_thread_request_list.push_back(thread); | 120 | m_request_list.push_back(*request); |
| 209 | 121 | ||
| 210 | // If we were empty, signal. | 122 | // If we were empty, signal. |
| 211 | if (was_empty) { | 123 | if (was_empty) { |
| @@ -213,6 +125,9 @@ Result KServerSession::OnRequest() { | |||
| 213 | } | 125 | } |
| 214 | } | 126 | } |
| 215 | 127 | ||
| 128 | // If we have a request event, this is asynchronous, and we don't need to wait. | ||
| 129 | R_SUCCEED_IF(request->GetEvent() != nullptr); | ||
| 130 | |||
| 216 | // This is a synchronous request, so we should wait for our request to complete. | 131 | // This is a synchronous request, so we should wait for our request to complete. |
| 217 | GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); | 132 | GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); |
| 218 | GetCurrentThread(kernel).BeginWait(&wait_queue); | 133 | GetCurrentThread(kernel).BeginWait(&wait_queue); |
| @@ -223,32 +138,32 @@ Result KServerSession::OnRequest() { | |||
| 223 | 138 | ||
| 224 | Result KServerSession::SendReply() { | 139 | Result KServerSession::SendReply() { |
| 225 | // Lock the session. | 140 | // Lock the session. |
| 226 | KScopedLightLock lk(m_lock); | 141 | KScopedLightLock lk{m_lock}; |
| 227 | 142 | ||
| 228 | // Get the request. | 143 | // Get the request. |
| 229 | KThread* client_thread; | 144 | KSessionRequest* request; |
| 230 | { | 145 | { |
| 231 | KScopedSchedulerLock sl{kernel}; | 146 | KScopedSchedulerLock sl{kernel}; |
| 232 | 147 | ||
| 233 | // Get the current request. | 148 | // Get the current request. |
| 234 | client_thread = m_current_thread_request; | 149 | request = m_current_request; |
| 235 | R_UNLESS(client_thread != nullptr, ResultInvalidState); | 150 | R_UNLESS(request != nullptr, ResultInvalidState); |
| 236 | 151 | ||
| 237 | // Clear the current request, since we're processing it. | 152 | // Clear the current request, since we're processing it. |
| 238 | m_current_thread_request = nullptr; | 153 | m_current_request = nullptr; |
| 239 | if (!m_thread_request_list.empty()) { | 154 | if (!m_request_list.empty()) { |
| 240 | this->NotifyAvailable(); | 155 | this->NotifyAvailable(); |
| 241 | } | 156 | } |
| 242 | } | 157 | } |
| 243 | 158 | ||
| 244 | // Close reference to the request once we're done processing it. | 159 | // Close reference to the request once we're done processing it. |
| 245 | SCOPE_EXIT({ client_thread->Close(); }); | 160 | SCOPE_EXIT({ request->Close(); }); |
| 246 | 161 | ||
| 247 | // Extract relevant information from the request. | 162 | // Extract relevant information from the request. |
| 248 | // const uintptr_t client_message = request->GetAddress(); | 163 | const uintptr_t client_message = request->GetAddress(); |
| 249 | // const size_t client_buffer_size = request->GetSize(); | 164 | const size_t client_buffer_size = request->GetSize(); |
| 250 | // KThread *client_thread = request->GetThread(); | 165 | KThread* client_thread = request->GetThread(); |
| 251 | // KEvent *event = request->GetEvent(); | 166 | KEvent* event = request->GetEvent(); |
| 252 | 167 | ||
| 253 | // Check whether we're closed. | 168 | // Check whether we're closed. |
| 254 | const bool closed = (client_thread == nullptr || parent->IsClientClosed()); | 169 | const bool closed = (client_thread == nullptr || parent->IsClientClosed()); |
| @@ -261,8 +176,8 @@ Result KServerSession::SendReply() { | |||
| 261 | UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); | 176 | UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); |
| 262 | 177 | ||
| 263 | auto* src_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); | 178 | auto* src_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); |
| 264 | auto* dst_msg_buffer = memory.GetPointer(client_thread->GetTLSAddress()); | 179 | auto* dst_msg_buffer = memory.GetPointer(client_message); |
| 265 | std::memcpy(dst_msg_buffer, src_msg_buffer, MessageBufferSize); | 180 | std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size); |
| 266 | } else { | 181 | } else { |
| 267 | result = ResultSessionClosed; | 182 | result = ResultSessionClosed; |
| 268 | } | 183 | } |
| @@ -278,11 +193,30 @@ Result KServerSession::SendReply() { | |||
| 278 | 193 | ||
| 279 | // If there's a client thread, update it. | 194 | // If there's a client thread, update it. |
| 280 | if (client_thread != nullptr) { | 195 | if (client_thread != nullptr) { |
| 281 | // End the client thread's wait. | 196 | if (event != nullptr) { |
| 282 | KScopedSchedulerLock sl{kernel}; | 197 | // // Get the client process/page table. |
| 198 | // KProcess *client_process = client_thread->GetOwnerProcess(); | ||
| 199 | // KPageTable *client_page_table = &client_process->PageTable(); | ||
| 200 | |||
| 201 | // // If we need to, reply with an async error. | ||
| 202 | // if (R_FAILED(client_result)) { | ||
| 203 | // ReplyAsyncError(client_process, client_message, client_buffer_size, | ||
| 204 | // client_result); | ||
| 205 | // } | ||
| 206 | |||
| 207 | // // Unlock the client buffer. | ||
| 208 | // // NOTE: Nintendo does not check the result of this. | ||
| 209 | // client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size); | ||
| 210 | |||
| 211 | // Signal the event. | ||
| 212 | event->Signal(); | ||
| 213 | } else { | ||
| 214 | // End the client thread's wait. | ||
| 215 | KScopedSchedulerLock sl{kernel}; | ||
| 283 | 216 | ||
| 284 | if (!client_thread->IsTerminationRequested()) { | 217 | if (!client_thread->IsTerminationRequested()) { |
| 285 | client_thread->EndWait(client_result); | 218 | client_thread->EndWait(client_result); |
| 219 | } | ||
| 286 | } | 220 | } |
| 287 | } | 221 | } |
| 288 | 222 | ||
| @@ -291,10 +225,10 @@ Result KServerSession::SendReply() { | |||
| 291 | 225 | ||
| 292 | Result KServerSession::ReceiveRequest() { | 226 | Result KServerSession::ReceiveRequest() { |
| 293 | // Lock the session. | 227 | // Lock the session. |
| 294 | KScopedLightLock lk(m_lock); | 228 | KScopedLightLock lk{m_lock}; |
| 295 | 229 | ||
| 296 | // Get the request and client thread. | 230 | // Get the request and client thread. |
| 297 | // KSessionRequest *request; | 231 | KSessionRequest* request; |
| 298 | KThread* client_thread; | 232 | KThread* client_thread; |
| 299 | 233 | ||
| 300 | { | 234 | { |
| @@ -304,35 +238,41 @@ Result KServerSession::ReceiveRequest() { | |||
| 304 | R_UNLESS(!parent->IsClientClosed(), ResultSessionClosed); | 238 | R_UNLESS(!parent->IsClientClosed(), ResultSessionClosed); |
| 305 | 239 | ||
| 306 | // Ensure we aren't already servicing a request. | 240 | // Ensure we aren't already servicing a request. |
| 307 | R_UNLESS(m_current_thread_request == nullptr, ResultNotFound); | 241 | R_UNLESS(m_current_request == nullptr, ResultNotFound); |
| 308 | 242 | ||
| 309 | // Ensure we have a request to service. | 243 | // Ensure we have a request to service. |
| 310 | R_UNLESS(!m_thread_request_list.empty(), ResultNotFound); | 244 | R_UNLESS(!m_request_list.empty(), ResultNotFound); |
| 311 | 245 | ||
| 312 | // Pop the first request from the list. | 246 | // Pop the first request from the list. |
| 313 | client_thread = m_thread_request_list.front(); | 247 | request = &m_request_list.front(); |
| 314 | m_thread_request_list.pop_front(); | 248 | m_request_list.pop_front(); |
| 315 | 249 | ||
| 316 | // Get the thread for the request. | 250 | // Get the thread for the request. |
| 251 | client_thread = request->GetThread(); | ||
| 317 | R_UNLESS(client_thread != nullptr, ResultSessionClosed); | 252 | R_UNLESS(client_thread != nullptr, ResultSessionClosed); |
| 318 | 253 | ||
| 319 | // Open the client thread. | 254 | // Open the client thread. |
| 320 | client_thread->Open(); | 255 | client_thread->Open(); |
| 321 | } | 256 | } |
| 322 | 257 | ||
| 323 | // SCOPE_EXIT({ client_thread->Close(); }); | 258 | SCOPE_EXIT({ client_thread->Close(); }); |
| 324 | 259 | ||
| 325 | // Set the request as our current. | 260 | // Set the request as our current. |
| 326 | m_current_thread_request = client_thread; | 261 | m_current_request = request; |
| 262 | |||
| 263 | // Get the client address. | ||
| 264 | uintptr_t client_message = request->GetAddress(); | ||
| 265 | size_t client_buffer_size = request->GetSize(); | ||
| 266 | // bool recv_list_broken = false; | ||
| 327 | 267 | ||
| 328 | // Receive the message. | 268 | // Receive the message. |
| 329 | Core::Memory::Memory& memory{kernel.System().Memory()}; | 269 | Core::Memory::Memory& memory{kernel.System().Memory()}; |
| 330 | KThread* server_thread{GetCurrentThreadPointer(kernel)}; | 270 | KThread* server_thread{GetCurrentThreadPointer(kernel)}; |
| 331 | UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); | 271 | UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); |
| 332 | 272 | ||
| 333 | auto* src_msg_buffer = memory.GetPointer(client_thread->GetTLSAddress()); | 273 | auto* src_msg_buffer = memory.GetPointer(client_message); |
| 334 | auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); | 274 | auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); |
| 335 | std::memcpy(dst_msg_buffer, src_msg_buffer, MessageBufferSize); | 275 | std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size); |
| 336 | 276 | ||
| 337 | // We succeeded. | 277 | // We succeeded. |
| 338 | return ResultSuccess; | 278 | return ResultSuccess; |
| @@ -344,35 +284,34 @@ void KServerSession::CleanupRequests() { | |||
| 344 | // Clean up any pending requests. | 284 | // Clean up any pending requests. |
| 345 | while (true) { | 285 | while (true) { |
| 346 | // Get the next request. | 286 | // Get the next request. |
| 347 | // KSessionRequest *request = nullptr; | 287 | KSessionRequest* request = nullptr; |
| 348 | KThread* client_thread = nullptr; | ||
| 349 | { | 288 | { |
| 350 | KScopedSchedulerLock sl{kernel}; | 289 | KScopedSchedulerLock sl{kernel}; |
| 351 | 290 | ||
| 352 | if (m_current_thread_request) { | 291 | if (m_current_request) { |
| 353 | // Choose the current request if we have one. | 292 | // Choose the current request if we have one. |
| 354 | client_thread = m_current_thread_request; | 293 | request = m_current_request; |
| 355 | m_current_thread_request = nullptr; | 294 | m_current_request = nullptr; |
| 356 | } else if (!m_thread_request_list.empty()) { | 295 | } else if (!m_request_list.empty()) { |
| 357 | // Pop the request from the front of the list. | 296 | // Pop the request from the front of the list. |
| 358 | client_thread = m_thread_request_list.front(); | 297 | request = &m_request_list.front(); |
| 359 | m_thread_request_list.pop_front(); | 298 | m_request_list.pop_front(); |
| 360 | } | 299 | } |
| 361 | } | 300 | } |
| 362 | 301 | ||
| 363 | // If there's no request, we're done. | 302 | // If there's no request, we're done. |
| 364 | if (client_thread == nullptr) { | 303 | if (request == nullptr) { |
| 365 | break; | 304 | break; |
| 366 | } | 305 | } |
| 367 | 306 | ||
| 368 | // Close a reference to the request once it's cleaned up. | 307 | // Close a reference to the request once it's cleaned up. |
| 369 | SCOPE_EXIT({ client_thread->Close(); }); | 308 | SCOPE_EXIT({ request->Close(); }); |
| 370 | 309 | ||
| 371 | // Extract relevant information from the request. | 310 | // Extract relevant information from the request. |
| 372 | // const uintptr_t client_message = request->GetAddress(); | 311 | // const uintptr_t client_message = request->GetAddress(); |
| 373 | // const size_t client_buffer_size = request->GetSize(); | 312 | // const size_t client_buffer_size = request->GetSize(); |
| 374 | // KThread *client_thread = request->GetThread(); | 313 | KThread* client_thread = request->GetThread(); |
| 375 | // KEvent *event = request->GetEvent(); | 314 | KEvent* event = request->GetEvent(); |
| 376 | 315 | ||
| 377 | // KProcess *server_process = request->GetServerProcess(); | 316 | // KProcess *server_process = request->GetServerProcess(); |
| 378 | // KProcess *client_process = (client_thread != nullptr) ? | 317 | // KProcess *client_process = (client_thread != nullptr) ? |
| @@ -385,11 +324,24 @@ void KServerSession::CleanupRequests() { | |||
| 385 | 324 | ||
| 386 | // If there's a client thread, update it. | 325 | // If there's a client thread, update it. |
| 387 | if (client_thread != nullptr) { | 326 | if (client_thread != nullptr) { |
| 388 | // End the client thread's wait. | 327 | if (event != nullptr) { |
| 389 | KScopedSchedulerLock sl{kernel}; | 328 | // // We need to reply async. |
| 390 | 329 | // ReplyAsyncError(client_process, client_message, client_buffer_size, | |
| 391 | if (!client_thread->IsTerminationRequested()) { | 330 | // (R_SUCCEEDED(result) ? ResultSessionClosed : result)); |
| 392 | client_thread->EndWait(ResultSessionClosed); | 331 | |
| 332 | // // Unlock the client buffer. | ||
| 333 | // NOTE: Nintendo does not check the result of this. | ||
| 334 | // client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size); | ||
| 335 | |||
| 336 | // Signal the event. | ||
| 337 | event->Signal(); | ||
| 338 | } else { | ||
| 339 | // End the client thread's wait. | ||
| 340 | KScopedSchedulerLock sl{kernel}; | ||
| 341 | |||
| 342 | if (!client_thread->IsTerminationRequested()) { | ||
| 343 | client_thread->EndWait(ResultSessionClosed); | ||
| 344 | } | ||
| 393 | } | 345 | } |
| 394 | } | 346 | } |
| 395 | } | 347 | } |
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index 748d52826..32135473b 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include "core/hle/kernel/hle_ipc.h" | 13 | #include "core/hle/kernel/hle_ipc.h" |
| 14 | #include "core/hle/kernel/k_light_lock.h" | 14 | #include "core/hle/kernel/k_light_lock.h" |
| 15 | #include "core/hle/kernel/k_session_request.h" | ||
| 15 | #include "core/hle/kernel/k_synchronization_object.h" | 16 | #include "core/hle/kernel/k_synchronization_object.h" |
| 16 | #include "core/hle/result.h" | 17 | #include "core/hle/result.h" |
| 17 | 18 | ||
| @@ -57,44 +58,15 @@ public: | |||
| 57 | } | 58 | } |
| 58 | 59 | ||
| 59 | bool IsSignaled() const override; | 60 | bool IsSignaled() const override; |
| 60 | |||
| 61 | void OnClientClosed(); | 61 | void OnClientClosed(); |
| 62 | 62 | ||
| 63 | void ClientConnected(SessionRequestHandlerPtr handler) { | ||
| 64 | if (manager) { | ||
| 65 | manager->SetSessionHandler(std::move(handler)); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | void ClientDisconnected() { | ||
| 70 | manager = nullptr; | ||
| 71 | } | ||
| 72 | |||
| 73 | /// Adds a new domain request handler to the collection of request handlers within | ||
| 74 | /// this ServerSession instance. | ||
| 75 | void AppendDomainHandler(SessionRequestHandlerPtr handler); | ||
| 76 | |||
| 77 | /// Retrieves the total number of domain request handlers that have been | ||
| 78 | /// appended to this ServerSession instance. | ||
| 79 | std::size_t NumDomainRequestHandlers() const; | ||
| 80 | |||
| 81 | /// Returns true if the session has been converted to a domain, otherwise False | ||
| 82 | bool IsDomain() const { | ||
| 83 | return manager && manager->IsDomain(); | ||
| 84 | } | ||
| 85 | |||
| 86 | /// Converts the session to a domain at the end of the current command | ||
| 87 | void ConvertToDomain() { | ||
| 88 | convert_to_domain = true; | ||
| 89 | } | ||
| 90 | |||
| 91 | /// Gets the session request manager, which forwards requests to the underlying service | 63 | /// Gets the session request manager, which forwards requests to the underlying service |
| 92 | std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() { | 64 | std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() { |
| 93 | return manager; | 65 | return manager; |
| 94 | } | 66 | } |
| 95 | 67 | ||
| 96 | /// TODO: flesh these out to match the real kernel | 68 | /// TODO: flesh these out to match the real kernel |
| 97 | Result OnRequest(); | 69 | Result OnRequest(KSessionRequest* request); |
| 98 | Result SendReply(); | 70 | Result SendReply(); |
| 99 | Result ReceiveRequest(); | 71 | Result ReceiveRequest(); |
| 100 | 72 | ||
| @@ -108,10 +80,6 @@ private: | |||
| 108 | /// Completes a sync request from the emulated application. | 80 | /// Completes a sync request from the emulated application. |
| 109 | Result CompleteSyncRequest(HLERequestContext& context); | 81 | Result CompleteSyncRequest(HLERequestContext& context); |
| 110 | 82 | ||
| 111 | /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an | ||
| 112 | /// object handle. | ||
| 113 | Result HandleDomainSyncRequest(Kernel::HLERequestContext& context); | ||
| 114 | |||
| 115 | /// This session's HLE request handlers; if nullptr, this is not an HLE server | 83 | /// This session's HLE request handlers; if nullptr, this is not an HLE server |
| 116 | std::shared_ptr<SessionRequestManager> manager; | 84 | std::shared_ptr<SessionRequestManager> manager; |
| 117 | 85 | ||
| @@ -122,9 +90,8 @@ private: | |||
| 122 | KSession* parent{}; | 90 | KSession* parent{}; |
| 123 | 91 | ||
| 124 | /// List of threads which are pending a reply. | 92 | /// List of threads which are pending a reply. |
| 125 | /// FIXME: KSessionRequest | 93 | boost::intrusive::list<KSessionRequest> m_request_list; |
| 126 | std::list<KThread*> m_thread_request_list; | 94 | KSessionRequest* m_current_request; |
| 127 | KThread* m_current_thread_request{}; | ||
| 128 | 95 | ||
| 129 | KLightLock m_lock; | 96 | KLightLock m_lock; |
| 130 | }; | 97 | }; |
diff --git a/src/core/hle/kernel/k_session_request.cpp b/src/core/hle/kernel/k_session_request.cpp new file mode 100644 index 000000000..520da6aa7 --- /dev/null +++ b/src/core/hle/kernel/k_session_request.cpp | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/kernel/k_page_buffer.h" | ||
| 5 | #include "core/hle/kernel/k_session_request.h" | ||
| 6 | |||
| 7 | namespace Kernel { | ||
| 8 | |||
| 9 | Result KSessionRequest::SessionMappings::PushMap(VAddr client, VAddr server, size_t size, | ||
| 10 | KMemoryState state, size_t index) { | ||
| 11 | // At most 15 buffers of each type (4-bit descriptor counts). | ||
| 12 | ASSERT(index < ((1ul << 4) - 1) * 3); | ||
| 13 | |||
| 14 | // Get the mapping. | ||
| 15 | Mapping* mapping; | ||
| 16 | if (index < NumStaticMappings) { | ||
| 17 | mapping = &m_static_mappings[index]; | ||
| 18 | } else { | ||
| 19 | // Allocate a page for the extra mappings. | ||
| 20 | if (m_mappings == nullptr) { | ||
| 21 | KPageBuffer* page_buffer = KPageBuffer::Allocate(kernel); | ||
| 22 | R_UNLESS(page_buffer != nullptr, ResultOutOfMemory); | ||
| 23 | |||
| 24 | m_mappings = reinterpret_cast<Mapping*>(page_buffer); | ||
| 25 | } | ||
| 26 | |||
| 27 | mapping = &m_mappings[index - NumStaticMappings]; | ||
| 28 | } | ||
| 29 | |||
| 30 | // Set the mapping. | ||
| 31 | mapping->Set(client, server, size, state); | ||
| 32 | |||
| 33 | return ResultSuccess; | ||
| 34 | } | ||
| 35 | |||
| 36 | Result KSessionRequest::SessionMappings::PushSend(VAddr client, VAddr server, size_t size, | ||
| 37 | KMemoryState state) { | ||
| 38 | ASSERT(m_num_recv == 0); | ||
| 39 | ASSERT(m_num_exch == 0); | ||
| 40 | return this->PushMap(client, server, size, state, m_num_send++); | ||
| 41 | } | ||
| 42 | |||
| 43 | Result KSessionRequest::SessionMappings::PushReceive(VAddr client, VAddr server, size_t size, | ||
| 44 | KMemoryState state) { | ||
| 45 | ASSERT(m_num_exch == 0); | ||
| 46 | return this->PushMap(client, server, size, state, m_num_send + m_num_recv++); | ||
| 47 | } | ||
| 48 | |||
| 49 | Result KSessionRequest::SessionMappings::PushExchange(VAddr client, VAddr server, size_t size, | ||
| 50 | KMemoryState state) { | ||
| 51 | return this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch++); | ||
| 52 | } | ||
| 53 | |||
| 54 | void KSessionRequest::SessionMappings::Finalize() { | ||
| 55 | if (m_mappings) { | ||
| 56 | KPageBuffer::Free(kernel, reinterpret_cast<KPageBuffer*>(m_mappings)); | ||
| 57 | m_mappings = nullptr; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_session_request.h b/src/core/hle/kernel/k_session_request.h new file mode 100644 index 000000000..fcf521597 --- /dev/null +++ b/src/core/hle/kernel/k_session_request.h | |||
| @@ -0,0 +1,307 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/kernel/k_auto_object.h" | ||
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 8 | #include "core/hle/kernel/k_memory_block.h" | ||
| 9 | #include "core/hle/kernel/k_process.h" | ||
| 10 | #include "core/hle/kernel/k_thread.h" | ||
| 11 | #include "core/hle/kernel/slab_helpers.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | class KSessionRequest final : public KSlabAllocated<KSessionRequest>, | ||
| 16 | public KAutoObject, | ||
| 17 | public boost::intrusive::list_base_hook<> { | ||
| 18 | KERNEL_AUTOOBJECT_TRAITS(KSessionRequest, KAutoObject); | ||
| 19 | |||
| 20 | public: | ||
| 21 | class SessionMappings { | ||
| 22 | private: | ||
| 23 | static constexpr size_t NumStaticMappings = 8; | ||
| 24 | |||
| 25 | class Mapping { | ||
| 26 | public: | ||
| 27 | constexpr void Set(VAddr c, VAddr s, size_t sz, KMemoryState st) { | ||
| 28 | m_client_address = c; | ||
| 29 | m_server_address = s; | ||
| 30 | m_size = sz; | ||
| 31 | m_state = st; | ||
| 32 | } | ||
| 33 | |||
| 34 | constexpr VAddr GetClientAddress() const { | ||
| 35 | return m_client_address; | ||
| 36 | } | ||
| 37 | constexpr VAddr GetServerAddress() const { | ||
| 38 | return m_server_address; | ||
| 39 | } | ||
| 40 | constexpr size_t GetSize() const { | ||
| 41 | return m_size; | ||
| 42 | } | ||
| 43 | constexpr KMemoryState GetMemoryState() const { | ||
| 44 | return m_state; | ||
| 45 | } | ||
| 46 | |||
| 47 | private: | ||
| 48 | VAddr m_client_address; | ||
| 49 | VAddr m_server_address; | ||
| 50 | size_t m_size; | ||
| 51 | KMemoryState m_state; | ||
| 52 | }; | ||
| 53 | |||
| 54 | public: | ||
| 55 | explicit SessionMappings(KernelCore& kernel_) | ||
| 56 | : kernel(kernel_), m_mappings(nullptr), m_num_send(), m_num_recv(), m_num_exch() {} | ||
| 57 | |||
| 58 | void Initialize() {} | ||
| 59 | void Finalize(); | ||
| 60 | |||
| 61 | size_t GetSendCount() const { | ||
| 62 | return m_num_send; | ||
| 63 | } | ||
| 64 | size_t GetReceiveCount() const { | ||
| 65 | return m_num_recv; | ||
| 66 | } | ||
| 67 | size_t GetExchangeCount() const { | ||
| 68 | return m_num_exch; | ||
| 69 | } | ||
| 70 | |||
| 71 | Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state); | ||
| 72 | Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state); | ||
| 73 | Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state); | ||
| 74 | |||
| 75 | VAddr GetSendClientAddress(size_t i) const { | ||
| 76 | return GetSendMapping(i).GetClientAddress(); | ||
| 77 | } | ||
| 78 | VAddr GetSendServerAddress(size_t i) const { | ||
| 79 | return GetSendMapping(i).GetServerAddress(); | ||
| 80 | } | ||
| 81 | size_t GetSendSize(size_t i) const { | ||
| 82 | return GetSendMapping(i).GetSize(); | ||
| 83 | } | ||
| 84 | KMemoryState GetSendMemoryState(size_t i) const { | ||
| 85 | return GetSendMapping(i).GetMemoryState(); | ||
| 86 | } | ||
| 87 | |||
| 88 | VAddr GetReceiveClientAddress(size_t i) const { | ||
| 89 | return GetReceiveMapping(i).GetClientAddress(); | ||
| 90 | } | ||
| 91 | VAddr GetReceiveServerAddress(size_t i) const { | ||
| 92 | return GetReceiveMapping(i).GetServerAddress(); | ||
| 93 | } | ||
| 94 | size_t GetReceiveSize(size_t i) const { | ||
| 95 | return GetReceiveMapping(i).GetSize(); | ||
| 96 | } | ||
| 97 | KMemoryState GetReceiveMemoryState(size_t i) const { | ||
| 98 | return GetReceiveMapping(i).GetMemoryState(); | ||
| 99 | } | ||
| 100 | |||
| 101 | VAddr GetExchangeClientAddress(size_t i) const { | ||
| 102 | return GetExchangeMapping(i).GetClientAddress(); | ||
| 103 | } | ||
| 104 | VAddr GetExchangeServerAddress(size_t i) const { | ||
| 105 | return GetExchangeMapping(i).GetServerAddress(); | ||
| 106 | } | ||
| 107 | size_t GetExchangeSize(size_t i) const { | ||
| 108 | return GetExchangeMapping(i).GetSize(); | ||
| 109 | } | ||
| 110 | KMemoryState GetExchangeMemoryState(size_t i) const { | ||
| 111 | return GetExchangeMapping(i).GetMemoryState(); | ||
| 112 | } | ||
| 113 | |||
| 114 | private: | ||
| 115 | Result PushMap(VAddr client, VAddr server, size_t size, KMemoryState state, size_t index); | ||
| 116 | |||
| 117 | const Mapping& GetSendMapping(size_t i) const { | ||
| 118 | ASSERT(i < m_num_send); | ||
| 119 | |||
| 120 | const size_t index = i; | ||
| 121 | if (index < NumStaticMappings) { | ||
| 122 | return m_static_mappings[index]; | ||
| 123 | } else { | ||
| 124 | return m_mappings[index - NumStaticMappings]; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | const Mapping& GetReceiveMapping(size_t i) const { | ||
| 129 | ASSERT(i < m_num_recv); | ||
| 130 | |||
| 131 | const size_t index = m_num_send + i; | ||
| 132 | if (index < NumStaticMappings) { | ||
| 133 | return m_static_mappings[index]; | ||
| 134 | } else { | ||
| 135 | return m_mappings[index - NumStaticMappings]; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | const Mapping& GetExchangeMapping(size_t i) const { | ||
| 140 | ASSERT(i < m_num_exch); | ||
| 141 | |||
| 142 | const size_t index = m_num_send + m_num_recv + i; | ||
| 143 | if (index < NumStaticMappings) { | ||
| 144 | return m_static_mappings[index]; | ||
| 145 | } else { | ||
| 146 | return m_mappings[index - NumStaticMappings]; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | private: | ||
| 151 | KernelCore& kernel; | ||
| 152 | Mapping m_static_mappings[NumStaticMappings]; | ||
| 153 | Mapping* m_mappings; | ||
| 154 | u8 m_num_send; | ||
| 155 | u8 m_num_recv; | ||
| 156 | u8 m_num_exch; | ||
| 157 | }; | ||
| 158 | |||
| 159 | public: | ||
| 160 | explicit KSessionRequest(KernelCore& kernel_) | ||
| 161 | : KAutoObject(kernel_), m_mappings(kernel_), m_thread(nullptr), m_server(nullptr), | ||
| 162 | m_event(nullptr) {} | ||
| 163 | |||
| 164 | static KSessionRequest* Create(KernelCore& kernel) { | ||
| 165 | KSessionRequest* req = KSessionRequest::Allocate(kernel); | ||
| 166 | if (req != nullptr) [[likely]] { | ||
| 167 | KAutoObject::Create(req); | ||
| 168 | } | ||
| 169 | return req; | ||
| 170 | } | ||
| 171 | |||
| 172 | void Destroy() override { | ||
| 173 | this->Finalize(); | ||
| 174 | KSessionRequest::Free(kernel, this); | ||
| 175 | } | ||
| 176 | |||
| 177 | void Initialize(KEvent* event, uintptr_t address, size_t size) { | ||
| 178 | m_mappings.Initialize(); | ||
| 179 | |||
| 180 | m_thread = GetCurrentThreadPointer(kernel); | ||
| 181 | m_event = event; | ||
| 182 | m_address = address; | ||
| 183 | m_size = size; | ||
| 184 | |||
| 185 | m_thread->Open(); | ||
| 186 | if (m_event != nullptr) { | ||
| 187 | m_event->Open(); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | static void PostDestroy(uintptr_t arg) {} | ||
| 192 | |||
| 193 | KThread* GetThread() const { | ||
| 194 | return m_thread; | ||
| 195 | } | ||
| 196 | KEvent* GetEvent() const { | ||
| 197 | return m_event; | ||
| 198 | } | ||
| 199 | uintptr_t GetAddress() const { | ||
| 200 | return m_address; | ||
| 201 | } | ||
| 202 | size_t GetSize() const { | ||
| 203 | return m_size; | ||
| 204 | } | ||
| 205 | KProcess* GetServerProcess() const { | ||
| 206 | return m_server; | ||
| 207 | } | ||
| 208 | |||
| 209 | void SetServerProcess(KProcess* process) { | ||
| 210 | m_server = process; | ||
| 211 | m_server->Open(); | ||
| 212 | } | ||
| 213 | |||
| 214 | void ClearThread() { | ||
| 215 | m_thread = nullptr; | ||
| 216 | } | ||
| 217 | void ClearEvent() { | ||
| 218 | m_event = nullptr; | ||
| 219 | } | ||
| 220 | |||
| 221 | size_t GetSendCount() const { | ||
| 222 | return m_mappings.GetSendCount(); | ||
| 223 | } | ||
| 224 | size_t GetReceiveCount() const { | ||
| 225 | return m_mappings.GetReceiveCount(); | ||
| 226 | } | ||
| 227 | size_t GetExchangeCount() const { | ||
| 228 | return m_mappings.GetExchangeCount(); | ||
| 229 | } | ||
| 230 | |||
| 231 | Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state) { | ||
| 232 | return m_mappings.PushSend(client, server, size, state); | ||
| 233 | } | ||
| 234 | |||
| 235 | Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state) { | ||
| 236 | return m_mappings.PushReceive(client, server, size, state); | ||
| 237 | } | ||
| 238 | |||
| 239 | Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state) { | ||
| 240 | return m_mappings.PushExchange(client, server, size, state); | ||
| 241 | } | ||
| 242 | |||
| 243 | VAddr GetSendClientAddress(size_t i) const { | ||
| 244 | return m_mappings.GetSendClientAddress(i); | ||
| 245 | } | ||
| 246 | VAddr GetSendServerAddress(size_t i) const { | ||
| 247 | return m_mappings.GetSendServerAddress(i); | ||
| 248 | } | ||
| 249 | size_t GetSendSize(size_t i) const { | ||
| 250 | return m_mappings.GetSendSize(i); | ||
| 251 | } | ||
| 252 | KMemoryState GetSendMemoryState(size_t i) const { | ||
| 253 | return m_mappings.GetSendMemoryState(i); | ||
| 254 | } | ||
| 255 | |||
| 256 | VAddr GetReceiveClientAddress(size_t i) const { | ||
| 257 | return m_mappings.GetReceiveClientAddress(i); | ||
| 258 | } | ||
| 259 | VAddr GetReceiveServerAddress(size_t i) const { | ||
| 260 | return m_mappings.GetReceiveServerAddress(i); | ||
| 261 | } | ||
| 262 | size_t GetReceiveSize(size_t i) const { | ||
| 263 | return m_mappings.GetReceiveSize(i); | ||
| 264 | } | ||
| 265 | KMemoryState GetReceiveMemoryState(size_t i) const { | ||
| 266 | return m_mappings.GetReceiveMemoryState(i); | ||
| 267 | } | ||
| 268 | |||
| 269 | VAddr GetExchangeClientAddress(size_t i) const { | ||
| 270 | return m_mappings.GetExchangeClientAddress(i); | ||
| 271 | } | ||
| 272 | VAddr GetExchangeServerAddress(size_t i) const { | ||
| 273 | return m_mappings.GetExchangeServerAddress(i); | ||
| 274 | } | ||
| 275 | size_t GetExchangeSize(size_t i) const { | ||
| 276 | return m_mappings.GetExchangeSize(i); | ||
| 277 | } | ||
| 278 | KMemoryState GetExchangeMemoryState(size_t i) const { | ||
| 279 | return m_mappings.GetExchangeMemoryState(i); | ||
| 280 | } | ||
| 281 | |||
| 282 | private: | ||
| 283 | // NOTE: This is public and virtual in Nintendo's kernel. | ||
| 284 | void Finalize() { | ||
| 285 | m_mappings.Finalize(); | ||
| 286 | |||
| 287 | if (m_thread) { | ||
| 288 | m_thread->Close(); | ||
| 289 | } | ||
| 290 | if (m_event) { | ||
| 291 | m_event->Close(); | ||
| 292 | } | ||
| 293 | if (m_server) { | ||
| 294 | m_server->Close(); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | private: | ||
| 299 | SessionMappings m_mappings; | ||
| 300 | KThread* m_thread; | ||
| 301 | KProcess* m_server; | ||
| 302 | KEvent* m_event; | ||
| 303 | uintptr_t m_address; | ||
| 304 | size_t m_size; | ||
| 305 | }; | ||
| 306 | |||
| 307 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_shared_memory_info.h b/src/core/hle/kernel/k_shared_memory_info.h index e43db8515..2bb6b6d08 100644 --- a/src/core/hle/kernel/k_shared_memory_info.h +++ b/src/core/hle/kernel/k_shared_memory_info.h | |||
| @@ -15,7 +15,8 @@ class KSharedMemoryInfo final : public KSlabAllocated<KSharedMemoryInfo>, | |||
| 15 | public boost::intrusive::list_base_hook<> { | 15 | public boost::intrusive::list_base_hook<> { |
| 16 | 16 | ||
| 17 | public: | 17 | public: |
| 18 | explicit KSharedMemoryInfo() = default; | 18 | explicit KSharedMemoryInfo(KernelCore&) {} |
| 19 | KSharedMemoryInfo() = default; | ||
| 19 | 20 | ||
| 20 | constexpr void Initialize(KSharedMemory* shmem) { | 21 | constexpr void Initialize(KSharedMemory* shmem) { |
| 21 | shared_memory = shmem; | 22 | shared_memory = shmem; |
diff --git a/src/core/hle/kernel/k_thread_local_page.h b/src/core/hle/kernel/k_thread_local_page.h index 0a7f22680..5d466ace7 100644 --- a/src/core/hle/kernel/k_thread_local_page.h +++ b/src/core/hle/kernel/k_thread_local_page.h | |||
| @@ -26,7 +26,7 @@ public: | |||
| 26 | static_assert(RegionsPerPage > 0); | 26 | static_assert(RegionsPerPage > 0); |
| 27 | 27 | ||
| 28 | public: | 28 | public: |
| 29 | constexpr explicit KThreadLocalPage(VAddr addr = {}) : m_virt_addr(addr) { | 29 | constexpr explicit KThreadLocalPage(KernelCore&, VAddr addr = {}) : m_virt_addr(addr) { |
| 30 | m_is_region_free.fill(true); | 30 | m_is_region_free.fill(true); |
| 31 | } | 31 | } |
| 32 | 32 | ||
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 6eded9539..266be2bc4 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -47,6 +47,7 @@ class KResourceLimit; | |||
| 47 | class KScheduler; | 47 | class KScheduler; |
| 48 | class KServerSession; | 48 | class KServerSession; |
| 49 | class KSession; | 49 | class KSession; |
| 50 | class KSessionRequest; | ||
| 50 | class KSharedMemory; | 51 | class KSharedMemory; |
| 51 | class KSharedMemoryInfo; | 52 | class KSharedMemoryInfo; |
| 52 | class KThread; | 53 | class KThread; |
| @@ -360,6 +361,8 @@ public: | |||
| 360 | return slab_heap_container->page_buffer; | 361 | return slab_heap_container->page_buffer; |
| 361 | } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { | 362 | } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { |
| 362 | return slab_heap_container->thread_local_page; | 363 | return slab_heap_container->thread_local_page; |
| 364 | } else if constexpr (std::is_same_v<T, KSessionRequest>) { | ||
| 365 | return slab_heap_container->session_request; | ||
| 363 | } | 366 | } |
| 364 | } | 367 | } |
| 365 | 368 | ||
| @@ -422,6 +425,7 @@ private: | |||
| 422 | KSlabHeap<KCodeMemory> code_memory; | 425 | KSlabHeap<KCodeMemory> code_memory; |
| 423 | KSlabHeap<KPageBuffer> page_buffer; | 426 | KSlabHeap<KPageBuffer> page_buffer; |
| 424 | KSlabHeap<KThreadLocalPage> thread_local_page; | 427 | KSlabHeap<KThreadLocalPage> thread_local_page; |
| 428 | KSlabHeap<KSessionRequest> session_request; | ||
| 425 | }; | 429 | }; |
| 426 | 430 | ||
| 427 | std::unique_ptr<SlabHeapContainer> slab_heap_container; | 431 | std::unique_ptr<SlabHeapContainer> slab_heap_container; |
diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h index 299a981a8..06b51e919 100644 --- a/src/core/hle/kernel/slab_helpers.h +++ b/src/core/hle/kernel/slab_helpers.h | |||
| @@ -24,7 +24,7 @@ public: | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | static Derived* Allocate(KernelCore& kernel) { | 26 | static Derived* Allocate(KernelCore& kernel) { |
| 27 | return kernel.SlabHeap<Derived>().Allocate(); | 27 | return kernel.SlabHeap<Derived>().Allocate(kernel); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | static void Free(KernelCore& kernel, Derived* obj) { | 30 | static void Free(KernelCore& kernel, Derived* obj) { |
diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp index 2a4bd64ab..273f79568 100644 --- a/src/core/hle/service/sm/sm_controller.cpp +++ b/src/core/hle/service/sm/sm_controller.cpp | |||
| @@ -15,9 +15,10 @@ | |||
| 15 | namespace Service::SM { | 15 | namespace Service::SM { |
| 16 | 16 | ||
| 17 | void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { | 17 | void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { |
| 18 | ASSERT_MSG(!ctx.Session()->IsDomain(), "Session is already a domain"); | 18 | ASSERT_MSG(!ctx.Session()->GetSessionRequestManager()->IsDomain(), |
| 19 | "Session is already a domain"); | ||
| 19 | LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId()); | 20 | LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId()); |
| 20 | ctx.Session()->ConvertToDomain(); | 21 | ctx.Session()->GetSessionRequestManager()->ConvertToDomainOnRequestEnd(); |
| 21 | 22 | ||
| 22 | IPC::ResponseBuilder rb{ctx, 3}; | 23 | IPC::ResponseBuilder rb{ctx, 3}; |
| 23 | rb.Push(ResultSuccess); | 24 | rb.Push(ResultSuccess); |