diff options
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r-- | src/core/hle/kernel/client_session.h | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/domain.cpp | 63 | ||||
-rw-r--r-- | src/core/hle/kernel/domain.h | 45 | ||||
-rw-r--r-- | src/core/hle/kernel/handle_table.cpp | 10 | ||||
-rw-r--r-- | src/core/hle/kernel/handle_table.h | 7 | ||||
-rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 11 | ||||
-rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 27 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 16 | ||||
-rw-r--r-- | src/core/hle/kernel/server_session.cpp | 47 | ||||
-rw-r--r-- | src/core/hle/kernel/server_session.h | 18 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/sync_object.h | 35 |
12 files changed, 79 insertions, 209 deletions
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index d6ab4f893..2258f95bc 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h @@ -7,7 +7,7 @@ #include <memory> #include <string> #include "common/common_types.h" -#include "core/hle/kernel/sync_object.h" +#include "core/hle/kernel/kernel.h" #include "core/hle/result.h" namespace Kernel { @@ -16,7 +16,7 @@ class ServerSession; class Session; class Thread; -class ClientSession final : public SyncObject { +class ClientSession final : public Object { public: friend class ServerSession; @@ -33,7 +33,7 @@ public: return HANDLE_TYPE; } - ResultCode SendSyncRequest(SharedPtr<Thread> thread) override; + ResultCode SendSyncRequest(SharedPtr<Thread> thread); std::string name; ///< Name of client port (optional) diff --git a/src/core/hle/kernel/domain.cpp b/src/core/hle/kernel/domain.cpp deleted file mode 100644 index 5035e9c08..000000000 --- a/src/core/hle/kernel/domain.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/domain.h" -#include "core/hle/kernel/handle_table.h" -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/kernel/process.h" -#include "core/hle/kernel/session.h" -#include "core/hle/kernel/thread.h" - -namespace Kernel { - -ResultVal<SharedPtr<Domain>> Domain::Create(std::string name) { - SharedPtr<Domain> domain(new Domain); - domain->name = std::move(name); - return MakeResult(std::move(domain)); -} - -ResultVal<SharedPtr<Domain>> Domain::CreateFromSession(const Session& session) { - auto res = Create(session.port->GetName() + "_Domain"); - auto& domain = res.Unwrap(); - domain->request_handlers.push_back(std::move(session.server->hle_handler)); - Kernel::g_handle_table.ConvertSessionToDomain(session, domain); - return res; -} - -ResultCode Domain::SendSyncRequest(SharedPtr<Thread> thread) { - Kernel::HLERequestContext context(this); - u32* cmd_buf = (u32*)Memory::GetPointer(Kernel::GetCurrentThread()->GetTLSAddress()); - context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process, - Kernel::g_handle_table); - - auto& domain_message_header = context.GetDomainMessageHeader(); - if (domain_message_header) { - // If there is a DomainMessageHeader, then this is CommandType "Request" - const u32 object_id{context.GetDomainMessageHeader()->object_id}; - switch (domain_message_header->command) { - case IPC::DomainMessageHeader::CommandType::SendMessage: - return request_handlers[object_id - 1]->HandleSyncRequest(context); - - case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { - LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x%08X", object_id); - - request_handlers[object_id - 1] = nullptr; - - IPC::RequestBuilder rb{context, 2}; - rb.Push(RESULT_SUCCESS); - - return RESULT_SUCCESS; - } - } - - LOG_CRITICAL(IPC, "Unknown domain command=%d", domain_message_header->command.Value()); - UNIMPLEMENTED(); - } - return request_handlers.front()->HandleSyncRequest(context); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/domain.h b/src/core/hle/kernel/domain.h deleted file mode 100644 index 3fec3b0b2..000000000 --- a/src/core/hle/kernel/domain.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <memory> -#include <string> -#include <vector> -#include "core/hle/kernel/sync_object.h" -#include "core/hle/result.h" - -namespace Kernel { - -class Session; -class SessionRequestHandler; - -class Domain final : public SyncObject { -public: - std::string GetTypeName() const override { - return "Domain"; - } - - static const HandleType HANDLE_TYPE = HandleType::Domain; - HandleType GetHandleType() const override { - return HANDLE_TYPE; - } - - static ResultVal<SharedPtr<Domain>> CreateFromSession(const Session& server); - - ResultCode SendSyncRequest(SharedPtr<Thread> thread) override; - - /// The name of this domain (optional) - std::string name; - - std::vector<std::shared_ptr<SessionRequestHandler>> request_handlers; - -private: - Domain() = default; - ~Domain() override = default; - - static ResultVal<SharedPtr<Domain>> Create(std::string name = "Unknown"); -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index 74d3d0514..3beb55753 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -5,12 +5,10 @@ #include <utility> #include "common/assert.h" #include "common/logging/log.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" -#include "core/hle/kernel/session.h" #include "core/hle/kernel/thread.h" namespace Kernel { @@ -55,14 +53,6 @@ ResultVal<Handle> HandleTable::Duplicate(Handle handle) { return Create(std::move(object)); } -void HandleTable::ConvertSessionToDomain(const Session& session, SharedPtr<Object> domain) { - for (auto& object : objects) { - if (DynamicObjectCast<ClientSession>(object) == session.client) { - object = domain; - } - } -} - ResultCode HandleTable::Close(Handle handle) { if (!IsValid(handle)) return ERR_INVALID_HANDLE; diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h index 935cc22b5..ba968c666 100644 --- a/src/core/hle/kernel/handle_table.h +++ b/src/core/hle/kernel/handle_table.h @@ -17,8 +17,6 @@ enum KernelHandle : Handle { CurrentProcess = 0xFFFF8001, }; -class Session; - /** * This class allows the creation of Handles, which are references to objects that can be tested * for validity and looked up. Here they are used to pass references to kernel objects to/from the @@ -62,11 +60,6 @@ public: ResultVal<Handle> Duplicate(Handle handle); /** - * Convert all handles of the specified Session to the specified Domain. - */ - void ConvertSessionToDomain(const Session& session, SharedPtr<Object> domain); - - /** * Closes a handle, removing it from the table and decreasing the object's ref-count. * @return `RESULT_SUCCESS` or one of the following errors: * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index ecf32c18a..db104e8a2 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -7,7 +7,6 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/domain.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/kernel.h" @@ -26,10 +25,6 @@ void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_s boost::range::remove_erase(connected_sessions, server_session); } -HLERequestContext::HLERequestContext(SharedPtr<Kernel::Domain> domain) : domain(std::move(domain)) { - cmd_buf[0] = 0; -} - HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session) : server_session(std::move(server_session)) { cmd_buf[0] = 0; @@ -87,7 +82,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { // Padding to align to 16 bytes rp.AlignWithPadding(); - if (IsDomain() && (command_header->type == IPC::CommandType::Request || !incoming)) { + if (Session()->IsDomain() && (command_header->type == IPC::CommandType::Request || !incoming)) { // If this is an incoming message, only CommandType "Request" has a domain header // All outgoing domain messages have the domain header domain_message_header = @@ -200,12 +195,12 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, P // TODO(Subv): Translate the X/A/B/W buffers. - if (IsDomain()) { + if (Session()->IsDomain()) { ASSERT(domain_message_header->num_objects == domain_objects.size()); // Write the domain objects to the command buffer, these go after the raw untranslated data. // TODO(Subv): This completely ignores C buffers. size_t domain_offset = size - domain_message_header->num_objects; - auto& request_handlers = domain->request_handlers; + auto& request_handlers = server_session->domain_request_handlers; for (auto& object : domain_objects) { request_handlers.emplace_back(object); diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 80fa48d7f..da8335b35 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -86,7 +86,6 @@ protected: */ class HLERequestContext { public: - HLERequestContext(SharedPtr<Kernel::Domain> domain); HLERequestContext(SharedPtr<Kernel::ServerSession> session); ~HLERequestContext(); @@ -96,17 +95,10 @@ public: } /** - * Returns the domain through which this request was made. - */ - const SharedPtr<Kernel::Domain>& Domain() const { - return domain; - } - - /** * Returns the session through which this request was made. This can be used as a map key to * access per-client data on services. */ - const SharedPtr<Kernel::ServerSession>& ServerSession() const { + const SharedPtr<Kernel::ServerSession>& Session() const { return server_session; } @@ -151,10 +143,6 @@ public: return domain_message_header; } - bool IsDomain() const { - return domain != nullptr; - } - template <typename T> SharedPtr<T> GetCopyObject(size_t index) { ASSERT(index < copy_objects.size()); @@ -187,9 +175,20 @@ public: domain_objects.clear(); } + size_t NumMoveObjects() const { + return move_objects.size(); + } + + size_t NumCopyObjects() const { + return copy_objects.size(); + } + + size_t NumDomainObjects() const { + return domain_objects.size(); + } + private: std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; - SharedPtr<Kernel::Domain> domain; SharedPtr<Kernel::ServerSession> server_session; // TODO(yuriks): Check common usage of this and optimize size accordingly boost::container::small_vector<SharedPtr<Object>, 8> move_objects; diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 4d9549e45..c77e58f3c 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -31,7 +31,6 @@ enum class HandleType : u32 { ServerPort, ClientSession, ServerSession, - Domain, }; enum { @@ -84,27 +83,12 @@ public: case HandleType::CodeSet: case HandleType::ClientPort: case HandleType::ClientSession: - case HandleType::Domain: return false; } UNREACHABLE(); } - /** - * Check if svcSendSyncRequest can be called on the object - * @return True svcSendSyncRequest can be called on the object, otherwise false - */ - bool IsSyncable() const { - switch (GetHandleType()) { - case HandleType::ClientSession: - case HandleType::Domain: - return true; - } - - UNREACHABLE(); - } - public: static unsigned int next_object_id; diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 09d02a691..54481f7f1 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -4,6 +4,7 @@ #include <tuple> +#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" #include "core/hle/kernel/handle_table.h" @@ -61,6 +62,38 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) { // from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or // similar. + Kernel::HLERequestContext context(this); + u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress()); + context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process, + Kernel::g_handle_table); + + // If the session has been converted to a domain, handle the doomain request + if (IsDomain()) { + auto& domain_message_header = context.GetDomainMessageHeader(); + if (domain_message_header) { + // If there is a DomainMessageHeader, then this is CommandType "Request" + const u32 object_id{context.GetDomainMessageHeader()->object_id}; + switch (domain_message_header->command) { + case IPC::DomainMessageHeader::CommandType::SendMessage: + return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); + + case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { + LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x%08X", object_id); + + domain_request_handlers[object_id - 1] = nullptr; + + IPC::ResponseBuilder rb{context, 2}; + rb.Push(RESULT_SUCCESS); + return RESULT_SUCCESS; + } + } + + LOG_CRITICAL(IPC, "Unknown domain command=%d", domain_message_header->command.Value()); + ASSERT(false); + } + // If there is no domain header, the regular session handler is used + } + // If this ServerSession has an associated HLE handler, forward the request to it. ResultCode result{RESULT_SUCCESS}; if (hle_handler != nullptr) { @@ -69,11 +102,6 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) { if (translate_result.IsError()) return translate_result; - Kernel::HLERequestContext context(this); - u32* cmd_buf = (u32*)Memory::GetPointer(Kernel::GetCurrentThread()->GetTLSAddress()); - context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process, - Kernel::g_handle_table); - result = hle_handler->HandleSyncRequest(context); } else { // Add the thread to the list of threads that have issued a sync request with this @@ -84,6 +112,15 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) { // If this ServerSession does not have an HLE implementation, just wake up the threads waiting // on it. WakeupAllWaitingThreads(); + + // Handle scenario when ConvertToDomain command was issued, as we must do the conversion at the + // end of the command such that only commands following this one are handled as domains + if (convert_to_domain) { + ASSERT_MSG(domain_request_handlers.empty(), "already a domain"); + domain_request_handlers = {hle_handler}; + convert_to_domain = false; + } + return result; } diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 6ff4ef8c1..144692106 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -79,7 +79,10 @@ public: std::string name; ///< The name of this session (optional) std::shared_ptr<Session> parent; ///< The parent session, which links to the client endpoint. std::shared_ptr<SessionRequestHandler> - hle_handler; ///< This session's HLE request handler (optional) + hle_handler; ///< This session's HLE request handler (applicable when not a domain) + + /// This is the list of domain request handlers (after conversion to a domain) + std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; /// List of threads that are pending a response after a sync request. This list is processed in /// a LIFO manner, thus, the last request will be dispatched first. @@ -91,6 +94,16 @@ public: /// TODO(Subv): Find a better name for this. SharedPtr<Thread> currently_handling; + /// Returns true if the session has been converted to a domain, otherwise False + bool IsDomain() const { + return !domain_request_handlers.empty(); + } + + /// Converts the session to a domain at the end of the current command + void ConvertToDomain() { + convert_to_domain = true; + } + private: ServerSession(); ~ServerSession() override; @@ -102,6 +115,9 @@ private: * @return The created server session */ static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown"); + + /// When set to True, converts the session to a domain at the end of the command + bool convert_to_domain{}; }; /** diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 516309036..4c0276cf0 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -20,7 +20,6 @@ #include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc_wrap.h" -#include "core/hle/kernel/sync_object.h" #include "core/hle/kernel/thread.h" #include "core/hle/lock.h" #include "core/hle/result.h" @@ -87,7 +86,7 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address /// Makes a blocking IPC call to an OS service. static ResultCode SendSyncRequest(Handle handle) { - SharedPtr<SyncObject> session = g_handle_table.Get<SyncObject>(handle); + SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle); if (!session) { LOG_ERROR(Kernel_SVC, "called with invalid handle=0x%08X", handle); return ERR_INVALID_HANDLE; diff --git a/src/core/hle/kernel/sync_object.h b/src/core/hle/kernel/sync_object.h deleted file mode 100644 index f2befa2ea..000000000 --- a/src/core/hle/kernel/sync_object.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <boost/smart_ptr/intrusive_ptr.hpp> -#include "core/hle/kernel/kernel.h" -#include "core/hle/result.h" - -namespace Kernel { - -class Thread; - -/// Class that represents a Kernel object that svcSendSyncRequest can be called on -class SyncObject : public Object { -public: - /** - * Handle a sync request from the emulated application. - * @param thread Thread that initiated the request. - * @returns ResultCode from the operation. - */ - virtual ResultCode SendSyncRequest(SharedPtr<Thread> thread) = 0; -}; - -// Specialization of DynamicObjectCast for SyncObjects -template <> -inline SharedPtr<SyncObject> DynamicObjectCast<SyncObject>(SharedPtr<Object> object) { - if (object != nullptr && object->IsSyncable()) { - return boost::static_pointer_cast<SyncObject>(std::move(object)); - } - return nullptr; -} - -} // namespace Kernel |