Merge pull request #6414 from bunnei/fix-service-threads
hle: kernel: Refactor to allocate a ServiceThread per service handler.
This commit is contained in:
		| @@ -30,9 +30,16 @@ | |||||||
|  |  | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  |  | ||||||
| SessionRequestHandler::SessionRequestHandler() = default; | SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_) | ||||||
|  |     : kernel{kernel_}, service_thread{kernel.CreateServiceThread(service_name_)} {} | ||||||
|  |  | ||||||
| SessionRequestHandler::~SessionRequestHandler() = default; | SessionRequestHandler::~SessionRequestHandler() { | ||||||
|  |     kernel.ReleaseServiceThread(service_thread); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SessionRequestManager::SessionRequestManager(KernelCore& kernel_) : kernel{kernel_} {} | ||||||
|  |  | ||||||
|  | SessionRequestManager::~SessionRequestManager() = default; | ||||||
|  |  | ||||||
| void SessionRequestHandler::ClientConnected(KServerSession* session) { | void SessionRequestHandler::ClientConnected(KServerSession* session) { | ||||||
|     session->SetSessionHandler(shared_from_this()); |     session->SetSessionHandler(shared_from_this()); | ||||||
|   | |||||||
| @@ -46,6 +46,7 @@ class KThread; | |||||||
| class KReadableEvent; | class KReadableEvent; | ||||||
| class KSession; | class KSession; | ||||||
| class KWritableEvent; | class KWritableEvent; | ||||||
|  | class ServiceThread; | ||||||
|  |  | ||||||
| enum class ThreadWakeupReason; | enum class ThreadWakeupReason; | ||||||
|  |  | ||||||
| @@ -56,7 +57,7 @@ enum class ThreadWakeupReason; | |||||||
|  */ |  */ | ||||||
| class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> { | class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> { | ||||||
| public: | public: | ||||||
|     SessionRequestHandler(); |     SessionRequestHandler(KernelCore& kernel, const char* service_name_); | ||||||
|     virtual ~SessionRequestHandler(); |     virtual ~SessionRequestHandler(); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -83,6 +84,14 @@ public: | |||||||
|      * @param server_session ServerSession associated with the connection. |      * @param server_session ServerSession associated with the connection. | ||||||
|      */ |      */ | ||||||
|     void ClientDisconnected(KServerSession* session); |     void ClientDisconnected(KServerSession* session); | ||||||
|  |  | ||||||
|  |     std::shared_ptr<ServiceThread> GetServiceThread() const { | ||||||
|  |         return service_thread.lock(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  |     KernelCore& kernel; | ||||||
|  |     std::weak_ptr<ServiceThread> service_thread; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>; | using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>; | ||||||
| @@ -94,7 +103,8 @@ using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>; | |||||||
|  */ |  */ | ||||||
| class SessionRequestManager final { | class SessionRequestManager final { | ||||||
| public: | public: | ||||||
|     SessionRequestManager() = default; |     explicit SessionRequestManager(KernelCore& kernel); | ||||||
|  |     ~SessionRequestManager(); | ||||||
|  |  | ||||||
|     bool IsDomain() const { |     bool IsDomain() const { | ||||||
|         return is_domain; |         return is_domain; | ||||||
| @@ -142,10 +152,18 @@ public: | |||||||
|         session_handler = std::move(handler); |         session_handler = std::move(handler); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     std::shared_ptr<ServiceThread> GetServiceThread() const { | ||||||
|  |         return session_handler->GetServiceThread(); | ||||||
|  |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     bool is_domain{}; |     bool is_domain{}; | ||||||
|     SessionRequestHandlerPtr session_handler; |     SessionRequestHandlerPtr session_handler; | ||||||
|     std::vector<SessionRequestHandlerPtr> domain_handlers; |     std::vector<SessionRequestHandlerPtr> domain_handlers; | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     KernelCore& kernel; | ||||||
|  |     std::weak_ptr<ServiceThread> service_thread; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -7,10 +7,11 @@ | |||||||
| #include <atomic> | #include <atomic> | ||||||
| #include <string> | #include <string> | ||||||
|  |  | ||||||
|  | #include <boost/intrusive/rbtree.hpp> | ||||||
|  |  | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_funcs.h" | #include "common/common_funcs.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/intrusive_red_black_tree.h" |  | ||||||
| #include "core/hle/kernel/k_class_token.h" | #include "core/hle/kernel/k_class_token.h" | ||||||
|  |  | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| @@ -175,7 +176,7 @@ private: | |||||||
|  |  | ||||||
| class KAutoObjectWithListContainer; | class KAutoObjectWithListContainer; | ||||||
|  |  | ||||||
| class KAutoObjectWithList : public KAutoObject { | class KAutoObjectWithList : public KAutoObject, public boost::intrusive::set_base_hook<> { | ||||||
| public: | public: | ||||||
|     explicit KAutoObjectWithList(KernelCore& kernel_) : KAutoObject(kernel_) {} |     explicit KAutoObjectWithList(KernelCore& kernel_) : KAutoObject(kernel_) {} | ||||||
|  |  | ||||||
| @@ -192,6 +193,10 @@ public: | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     friend bool operator<(const KAutoObjectWithList& left, const KAutoObjectWithList& right) { | ||||||
|  |         return &left < &right; | ||||||
|  |     } | ||||||
|  |  | ||||||
| public: | public: | ||||||
|     virtual u64 GetId() const { |     virtual u64 GetId() const { | ||||||
|         return reinterpret_cast<u64>(this); |         return reinterpret_cast<u64>(this); | ||||||
| @@ -203,8 +208,6 @@ public: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|     friend class KAutoObjectWithListContainer; |     friend class KAutoObjectWithListContainer; | ||||||
|  |  | ||||||
|     Common::IntrusiveRedBlackTreeNode list_node; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
|   | |||||||
| @@ -9,13 +9,13 @@ namespace Kernel { | |||||||
| void KAutoObjectWithListContainer::Register(KAutoObjectWithList* obj) { | void KAutoObjectWithListContainer::Register(KAutoObjectWithList* obj) { | ||||||
|     KScopedLightLock lk(m_lock); |     KScopedLightLock lk(m_lock); | ||||||
|  |  | ||||||
|     m_object_list.insert(*obj); |     m_object_list.insert_unique(*obj); | ||||||
| } | } | ||||||
|  |  | ||||||
| void KAutoObjectWithListContainer::Unregister(KAutoObjectWithList* obj) { | void KAutoObjectWithListContainer::Unregister(KAutoObjectWithList* obj) { | ||||||
|     KScopedLightLock lk(m_lock); |     KScopedLightLock lk(m_lock); | ||||||
|  |  | ||||||
|     m_object_list.erase(m_object_list.iterator_to(*obj)); |     m_object_list.erase(*obj); | ||||||
| } | } | ||||||
|  |  | ||||||
| size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess* owner) { | size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess* owner) { | ||||||
|   | |||||||
| @@ -6,6 +6,8 @@ | |||||||
|  |  | ||||||
| #include <atomic> | #include <atomic> | ||||||
|  |  | ||||||
|  | #include <boost/intrusive/rbtree.hpp> | ||||||
|  |  | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_funcs.h" | #include "common/common_funcs.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| @@ -23,8 +25,7 @@ class KAutoObjectWithListContainer { | |||||||
|     YUZU_NON_MOVEABLE(KAutoObjectWithListContainer); |     YUZU_NON_MOVEABLE(KAutoObjectWithListContainer); | ||||||
|  |  | ||||||
| public: | public: | ||||||
|     using ListType = Common::IntrusiveRedBlackTreeMemberTraits< |     using ListType = boost::intrusive::rbtree<KAutoObjectWithList>; | ||||||
|         &KAutoObjectWithList::list_node>::TreeType<KAutoObjectWithList>; |  | ||||||
|  |  | ||||||
| public: | public: | ||||||
|     class ListAccessor : public KScopedLightLock { |     class ListAccessor : public KScopedLightLock { | ||||||
|   | |||||||
| @@ -16,11 +16,11 @@ namespace Kernel { | |||||||
| KClientPort::KClientPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | KClientPort::KClientPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | ||||||
| KClientPort::~KClientPort() = default; | KClientPort::~KClientPort() = default; | ||||||
|  |  | ||||||
| void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_) { | void KClientPort::Initialize(KPort* parent_port_, s32 max_sessions_, std::string&& name_) { | ||||||
|     // Set member variables. |     // Set member variables. | ||||||
|     num_sessions = 0; |     num_sessions = 0; | ||||||
|     peak_sessions = 0; |     peak_sessions = 0; | ||||||
|     parent = parent_; |     parent = parent_port_; | ||||||
|     max_sessions = max_sessions_; |     max_sessions = max_sessions_; | ||||||
|     name = std::move(name_); |     name = std::move(name_); | ||||||
| } | } | ||||||
| @@ -56,7 +56,8 @@ bool KClientPort::IsSignaled() const { | |||||||
|     return num_sessions < max_sessions; |     return num_sessions < max_sessions; | ||||||
| } | } | ||||||
|  |  | ||||||
| ResultCode KClientPort::CreateSession(KClientSession** out) { | ResultCode KClientPort::CreateSession(KClientSession** out, | ||||||
|  |                                       std::shared_ptr<SessionRequestManager> session_manager) { | ||||||
|     // Reserve a new session from the resource limit. |     // Reserve a new session from the resource limit. | ||||||
|     KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), |     KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), | ||||||
|                                                    LimitableResource::Sessions); |                                                    LimitableResource::Sessions); | ||||||
| @@ -101,7 +102,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Initialize the session. |     // Initialize the session. | ||||||
|     session->Initialize(this, parent->GetName()); |     session->Initialize(this, parent->GetName(), session_manager); | ||||||
|  |  | ||||||
|     // Commit the session reservation. |     // Commit the session reservation. | ||||||
|     session_reservation.Commit(); |     session_reservation.Commit(); | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ namespace Kernel { | |||||||
| class KClientSession; | class KClientSession; | ||||||
| class KernelCore; | class KernelCore; | ||||||
| class KPort; | class KPort; | ||||||
|  | class SessionRequestManager; | ||||||
|  |  | ||||||
| class KClientPort final : public KSynchronizationObject { | class KClientPort final : public KSynchronizationObject { | ||||||
|     KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject); |     KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject); | ||||||
| @@ -52,7 +53,8 @@ public: | |||||||
|     void Destroy() override; |     void Destroy() override; | ||||||
|     bool IsSignaled() const override; |     bool IsSignaled() const override; | ||||||
|  |  | ||||||
|     ResultCode CreateSession(KClientSession** out); |     ResultCode CreateSession(KClientSession** out, | ||||||
|  |                              std::shared_ptr<SessionRequestManager> session_manager = nullptr); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     std::atomic<s32> num_sessions{}; |     std::atomic<s32> num_sessions{}; | ||||||
|   | |||||||
| @@ -36,9 +36,9 @@ public: | |||||||
|     explicit KClientSession(KernelCore& kernel_); |     explicit KClientSession(KernelCore& kernel_); | ||||||
|     ~KClientSession() override; |     ~KClientSession() override; | ||||||
|  |  | ||||||
|     void Initialize(KSession* parent_, std::string&& name_) { |     void Initialize(KSession* parent_session_, std::string&& name_) { | ||||||
|         // Set member variables. |         // Set member variables. | ||||||
|         parent = parent_; |         parent = parent_session_; | ||||||
|         name = std::move(name_); |         name = std::move(name_); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,9 +21,9 @@ public: | |||||||
|     explicit KReadableEvent(KernelCore& kernel_); |     explicit KReadableEvent(KernelCore& kernel_); | ||||||
|     ~KReadableEvent() override; |     ~KReadableEvent() override; | ||||||
|  |  | ||||||
|     void Initialize(KEvent* parent_, std::string&& name_) { |     void Initialize(KEvent* parent_event_, std::string&& name_) { | ||||||
|         is_signaled = false; |         is_signaled = false; | ||||||
|         parent = parent_; |         parent = parent_event_; | ||||||
|         name = std::move(name_); |         name = std::move(name_); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,9 +17,9 @@ namespace Kernel { | |||||||
| KServerPort::KServerPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | KServerPort::KServerPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | ||||||
| KServerPort::~KServerPort() = default; | KServerPort::~KServerPort() = default; | ||||||
|  |  | ||||||
| void KServerPort::Initialize(KPort* parent_, std::string&& name_) { | void KServerPort::Initialize(KPort* parent_port_, std::string&& name_) { | ||||||
|     // Set member variables. |     // Set member variables. | ||||||
|     parent = parent_; |     parent = parent_port_; | ||||||
|     name = std::move(name_); |     name = std::move(name_); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ public: | |||||||
|     explicit KServerPort(KernelCore& kernel_); |     explicit KServerPort(KernelCore& kernel_); | ||||||
|     ~KServerPort() override; |     ~KServerPort() override; | ||||||
|  |  | ||||||
|     void Initialize(KPort* parent_, std::string&& name_); |     void Initialize(KPort* parent_port_, std::string&& name_); | ||||||
|  |  | ||||||
|     /// Whether or not this server port has an HLE handler available. |     /// Whether or not this server port has an HLE handler available. | ||||||
|     bool HasSessionRequestHandler() const { |     bool HasSessionRequestHandler() const { | ||||||
|   | |||||||
| @@ -13,8 +13,10 @@ | |||||||
| #include "core/hle/kernel/hle_ipc.h" | #include "core/hle/kernel/hle_ipc.h" | ||||||
| #include "core/hle/kernel/k_client_port.h" | #include "core/hle/kernel/k_client_port.h" | ||||||
| #include "core/hle/kernel/k_handle_table.h" | #include "core/hle/kernel/k_handle_table.h" | ||||||
|  | #include "core/hle/kernel/k_port.h" | ||||||
| #include "core/hle/kernel/k_process.h" | #include "core/hle/kernel/k_process.h" | ||||||
| #include "core/hle/kernel/k_scheduler.h" | #include "core/hle/kernel/k_scheduler.h" | ||||||
|  | #include "core/hle/kernel/k_server_port.h" | ||||||
| #include "core/hle/kernel/k_server_session.h" | #include "core/hle/kernel/k_server_session.h" | ||||||
| #include "core/hle/kernel/k_session.h" | #include "core/hle/kernel/k_session.h" | ||||||
| #include "core/hle/kernel/k_thread.h" | #include "core/hle/kernel/k_thread.h" | ||||||
| @@ -23,18 +25,21 @@ | |||||||
|  |  | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  |  | ||||||
| KServerSession::KServerSession(KernelCore& kernel_) | KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | ||||||
|     : KSynchronizationObject{kernel_}, manager{std::make_shared<SessionRequestManager>()} {} |  | ||||||
|  |  | ||||||
| KServerSession::~KServerSession() { | KServerSession::~KServerSession() {} | ||||||
|     kernel.ReleaseServiceThread(service_thread); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void KServerSession::Initialize(KSession* parent_, std::string&& name_) { | void KServerSession::Initialize(KSession* parent_session_, std::string&& name_, | ||||||
|  |                                 std::shared_ptr<SessionRequestManager> manager_) { | ||||||
|     // Set member variables. |     // Set member variables. | ||||||
|     parent = parent_; |     parent = parent_session_; | ||||||
|     name = std::move(name_); |     name = std::move(name_); | ||||||
|     service_thread = kernel.CreateServiceThread(name); |  | ||||||
|  |     if (manager_) { | ||||||
|  |         manager = manager_; | ||||||
|  |     } else { | ||||||
|  |         manager = std::make_shared<SessionRequestManager>(kernel); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void KServerSession::Destroy() { | void KServerSession::Destroy() { | ||||||
| @@ -114,9 +119,11 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor | |||||||
|  |  | ||||||
|     context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); |     context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); | ||||||
|  |  | ||||||
|     if (auto strong_ptr = service_thread.lock()) { |     if (auto strong_ptr = manager->GetServiceThread(); strong_ptr) { | ||||||
|         strong_ptr->QueueSyncRequest(*parent, std::move(context)); |         strong_ptr->QueueSyncRequest(*parent, std::move(context)); | ||||||
|         return ResultSuccess; |         return ResultSuccess; | ||||||
|  |     } else { | ||||||
|  |         ASSERT_MSG(false, "strong_ptr was nullptr!"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return ResultSuccess; |     return ResultSuccess; | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ class HLERequestContext; | |||||||
| class KernelCore; | class KernelCore; | ||||||
| class KSession; | class KSession; | ||||||
| class SessionRequestHandler; | class SessionRequestHandler; | ||||||
|  | class SessionRequestManager; | ||||||
| class KThread; | class KThread; | ||||||
|  |  | ||||||
| class KServerSession final : public KSynchronizationObject, | class KServerSession final : public KSynchronizationObject, | ||||||
| @@ -46,7 +47,8 @@ public: | |||||||
|  |  | ||||||
|     void Destroy() override; |     void Destroy() override; | ||||||
|  |  | ||||||
|     void Initialize(KSession* parent_, std::string&& name_); |     void Initialize(KSession* parent_session_, std::string&& name_, | ||||||
|  |                     std::shared_ptr<SessionRequestManager> manager_); | ||||||
|  |  | ||||||
|     KSession* GetParent() { |     KSession* GetParent() { | ||||||
|         return parent; |         return parent; | ||||||
| @@ -104,16 +106,6 @@ public: | |||||||
|         return manager; |         return manager; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Gets the session request manager, which forwards requests to the underlying service |  | ||||||
|     const std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() const { |  | ||||||
|         return manager; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Sets the session request manager, which forwards requests to the underlying service |  | ||||||
|     void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) { |  | ||||||
|         manager = std::move(manager_); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     /// Queues a sync request from the emulated application. |     /// Queues a sync request from the emulated application. | ||||||
|     ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); |     ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); | ||||||
| @@ -131,9 +123,6 @@ private: | |||||||
|     /// When set to True, converts the session to a domain at the end of the command |     /// When set to True, converts the session to a domain at the end of the command | ||||||
|     bool convert_to_domain{}; |     bool convert_to_domain{}; | ||||||
|  |  | ||||||
|     /// Thread to dispatch service requests |  | ||||||
|     std::weak_ptr<ServiceThread> service_thread; |  | ||||||
|  |  | ||||||
|     /// KSession that owns this KServerSession |     /// KSession that owns this KServerSession | ||||||
|     KSession* parent{}; |     KSession* parent{}; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -15,7 +15,8 @@ KSession::KSession(KernelCore& kernel_) | |||||||
|     : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {} |     : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {} | ||||||
| KSession::~KSession() = default; | KSession::~KSession() = default; | ||||||
|  |  | ||||||
| void KSession::Initialize(KClientPort* port_, const std::string& name_) { | void KSession::Initialize(KClientPort* port_, const std::string& name_, | ||||||
|  |                           std::shared_ptr<SessionRequestManager> manager_) { | ||||||
|     // Increment reference count. |     // Increment reference count. | ||||||
|     // Because reference count is one on creation, this will result |     // Because reference count is one on creation, this will result | ||||||
|     // in a reference count of two. Thus, when both server and client are closed |     // in a reference count of two. Thus, when both server and client are closed | ||||||
| @@ -27,7 +28,7 @@ void KSession::Initialize(KClientPort* port_, const std::string& name_) { | |||||||
|     KAutoObject::Create(std::addressof(client)); |     KAutoObject::Create(std::addressof(client)); | ||||||
|  |  | ||||||
|     // Initialize our sub sessions. |     // Initialize our sub sessions. | ||||||
|     server.Initialize(this, name_ + ":Server"); |     server.Initialize(this, name_ + ":Server", manager_); | ||||||
|     client.Initialize(this, name_ + ":Client"); |     client.Initialize(this, name_ + ":Client"); | ||||||
|  |  | ||||||
|     // Set state and name. |     // Set state and name. | ||||||
|   | |||||||
| @@ -13,6 +13,8 @@ | |||||||
|  |  | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  |  | ||||||
|  | class SessionRequestManager; | ||||||
|  |  | ||||||
| class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList> { | class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList> { | ||||||
|     KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject); |     KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject); | ||||||
|  |  | ||||||
| @@ -20,7 +22,8 @@ public: | |||||||
|     explicit KSession(KernelCore& kernel_); |     explicit KSession(KernelCore& kernel_); | ||||||
|     ~KSession() override; |     ~KSession() override; | ||||||
|  |  | ||||||
|     void Initialize(KClientPort* port_, const std::string& name_); |     void Initialize(KClientPort* port_, const std::string& name_, | ||||||
|  |                     std::shared_ptr<SessionRequestManager> manager_ = nullptr); | ||||||
|  |  | ||||||
|     void Finalize() override; |     void Finalize() override; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,8 +13,8 @@ KWritableEvent::KWritableEvent(KernelCore& kernel_) | |||||||
|  |  | ||||||
| KWritableEvent::~KWritableEvent() = default; | KWritableEvent::~KWritableEvent() = default; | ||||||
|  |  | ||||||
| void KWritableEvent::Initialize(KEvent* parent_, std::string&& name_) { | void KWritableEvent::Initialize(KEvent* parent_event_, std::string&& name_) { | ||||||
|     parent = parent_; |     parent = parent_event_; | ||||||
|     name = std::move(name_); |     name = std::move(name_); | ||||||
|     parent->GetReadableEvent().Open(); |     parent->GetReadableEvent().Open(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -254,8 +254,6 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { | |||||||
|     LOG_DEBUG(Service_NS, "called"); |     LOG_DEBUG(Service_NS, "called"); | ||||||
|  |  | ||||||
|     // Create shared font memory object |     // Create shared font memory object | ||||||
|     auto& kernel = system.Kernel(); |  | ||||||
|  |  | ||||||
|     std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(), |     std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(), | ||||||
|                 impl->shared_font->size()); |                 impl->shared_font->size()); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -93,8 +93,8 @@ namespace Service { | |||||||
|  |  | ||||||
| ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_, | ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_, | ||||||
|                                            u32 max_sessions_, InvokerFn* handler_invoker_) |                                            u32 max_sessions_, InvokerFn* handler_invoker_) | ||||||
|     : system{system_}, service_name{service_name_}, max_sessions{max_sessions_}, |     : SessionRequestHandler(system_.Kernel(), service_name_), system{system_}, | ||||||
|       handler_invoker{handler_invoker_} {} |       service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {} | ||||||
|  |  | ||||||
| ServiceFrameworkBase::~ServiceFrameworkBase() { | ServiceFrameworkBase::~ServiceFrameworkBase() { | ||||||
|     // Wait for other threads to release access before destroying |     // Wait for other threads to release access before destroying | ||||||
| @@ -111,7 +111,7 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) | |||||||
|     port_installed = true; |     port_installed = true; | ||||||
| } | } | ||||||
|  |  | ||||||
| Kernel::KClientPort& ServiceFrameworkBase::CreatePort(Kernel::KernelCore& kernel) { | Kernel::KClientPort& ServiceFrameworkBase::CreatePort() { | ||||||
|     const auto guard = LockService(); |     const auto guard = LockService(); | ||||||
|  |  | ||||||
|     ASSERT(!port_installed); |     ASSERT(!port_installed); | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ namespace Kernel { | |||||||
| class HLERequestContext; | class HLERequestContext; | ||||||
| class KClientPort; | class KClientPort; | ||||||
| class KServerSession; | class KServerSession; | ||||||
|  | class ServiceThread; | ||||||
| } // namespace Kernel | } // namespace Kernel | ||||||
|  |  | ||||||
| namespace Service { | namespace Service { | ||||||
| @@ -41,7 +42,7 @@ class ServiceManager; | |||||||
|  |  | ||||||
| static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) | static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) | ||||||
| /// Arbitrary default number of maximum connections to an HLE service. | /// Arbitrary default number of maximum connections to an HLE service. | ||||||
| static const u32 DefaultMaxSessions = 10; | static const u32 DefaultMaxSessions = 64; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This is an non-templated base of ServiceFramework to reduce code bloat and compilation times, it |  * This is an non-templated base of ServiceFramework to reduce code bloat and compilation times, it | ||||||
| @@ -74,7 +75,7 @@ public: | |||||||
|     void InvokeRequestTipc(Kernel::HLERequestContext& ctx); |     void InvokeRequestTipc(Kernel::HLERequestContext& ctx); | ||||||
|  |  | ||||||
|     /// Creates a port pair and registers it on the kernel's global port registry. |     /// Creates a port pair and registers it on the kernel's global port registry. | ||||||
|     Kernel::KClientPort& CreatePort(Kernel::KernelCore& kernel); |     Kernel::KClientPort& CreatePort(); | ||||||
|  |  | ||||||
|     /// Handles a synchronization request for the service. |     /// Handles a synchronization request for the service. | ||||||
|     ResultCode HandleSyncRequest(Kernel::KServerSession& session, |     ResultCode HandleSyncRequest(Kernel::KServerSession& session, | ||||||
|   | |||||||
| @@ -28,42 +28,25 @@ void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { | |||||||
| } | } | ||||||
|  |  | ||||||
| void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { | void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { | ||||||
|     // TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong |  | ||||||
|     // and that we probably want to actually make an entirely new Session, but we still need to |  | ||||||
|     // verify this on hardware. |  | ||||||
|  |  | ||||||
|     LOG_DEBUG(Service, "called"); |     LOG_DEBUG(Service, "called"); | ||||||
|  |  | ||||||
|     auto& kernel = system.Kernel(); |     auto& parent_session = *ctx.Session()->GetParent(); | ||||||
|     auto* session = ctx.Session()->GetParent(); |     auto& parent_port = parent_session.GetParent()->GetParent()->GetClientPort(); | ||||||
|     auto* port = session->GetParent()->GetParent(); |     auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager(); | ||||||
|  |  | ||||||
|     // Reserve a new session from the process resource limit. |     // Create a session. | ||||||
|     Kernel::KScopedResourceReservation session_reservation( |     Kernel::KClientSession* session{}; | ||||||
|         kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions); |     const ResultCode result = parent_port.CreateSession(std::addressof(session), session_manager); | ||||||
|     if (!session_reservation.Succeeded()) { |     if (result.IsError()) { | ||||||
|  |         LOG_CRITICAL(Service, "CreateSession failed with error 0x{:08X}", result.raw); | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|         rb.Push(Kernel::ResultLimitReached); |         rb.Push(result); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create a new session. |  | ||||||
|     auto* clone = Kernel::KSession::Create(kernel); |  | ||||||
|     clone->Initialize(&port->GetClientPort(), session->GetName()); |  | ||||||
|  |  | ||||||
|     // Commit the session reservation. |  | ||||||
|     session_reservation.Commit(); |  | ||||||
|  |  | ||||||
|     // Enqueue the session with the named port. |  | ||||||
|     port->EnqueueSession(&clone->GetServerSession()); |  | ||||||
|  |  | ||||||
|     // Set the session request manager. |  | ||||||
|     clone->GetServerSession().SetSessionRequestManager( |  | ||||||
|         session->GetServerSession().GetSessionRequestManager()); |  | ||||||
|  |  | ||||||
|     // We succeeded. |     // We succeeded. | ||||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |     IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
|     rb.PushMoveObjects(clone->GetClientSession()); |     rb.PushMoveObjects(session); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { | void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { | ||||||
|   | |||||||
| @@ -46,7 +46,7 @@ Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core | |||||||
|     self.sm_interface = sm; |     self.sm_interface = sm; | ||||||
|     self.controller_interface = std::make_unique<Controller>(system); |     self.controller_interface = std::make_unique<Controller>(system); | ||||||
|  |  | ||||||
|     return sm->CreatePort(system.Kernel()); |     return sm->CreatePort(); | ||||||
| } | } | ||||||
|  |  | ||||||
| ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, | ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user