Merge pull request #6414 from bunnei/fix-service-threads

hle: kernel: Refactor to allocate a ServiceThread per service handler.
This commit is contained in:
bunnei 2021-06-06 22:52:07 -07:00 committed by GitHub
commit 28eb8c83d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 101 additions and 87 deletions

View File

@ -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());

View File

@ -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;
}; };
/** /**

View File

@ -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>

View File

@ -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) {

View File

@ -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 {

View File

@ -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();

View File

@ -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{};

View File

@ -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_);
} }

View File

@ -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_);
} }

View File

@ -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_);
} }

View File

@ -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 {

View File

@ -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;

View File

@ -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{};
}; };

View File

@ -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.

View File

@ -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;

View File

@ -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();
} }

View File

@ -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());

View File

@ -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);

View File

@ -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,

View File

@ -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) {

View File

@ -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,