hle: kernel: Implement CloneCurrentObject and improve session management.

This commit is contained in:
bunnei 2021-05-15 23:49:03 -07:00
parent c40e7593f5
commit 7361eac10f
13 changed files with 184 additions and 99 deletions

View file

@ -107,7 +107,7 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)
ASSERT(!port_installed);
auto port = service_manager.RegisterService(service_name, max_sessions).Unwrap();
port->SetHleHandler(shared_from_this());
port->SetSessionHandler(shared_from_this());
port_installed = true;
}
@ -118,7 +118,7 @@ Kernel::KClientPort& ServiceFrameworkBase::CreatePort(Kernel::KernelCore& kernel
auto* port = Kernel::KPort::Create(kernel);
port->Initialize(max_sessions, false, service_name);
port->GetServerPort().SetHleHandler(shared_from_this());
port->GetServerPort().SetSessionHandler(shared_from_this());
port_installed = true;

View file

@ -4,8 +4,13 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_client_port.h"
#include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h"
#include "core/hle/kernel/k_server_port.h"
#include "core/hle/kernel/k_server_session.h"
#include "core/hle/kernel/k_session.h"
#include "core/hle/service/sm/controller.h"
@ -13,7 +18,7 @@
namespace Service::SM {
void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
ASSERT_MSG(ctx.Session()->IsSession(), "Session is already a domain");
ASSERT_MSG(!ctx.Session()->IsDomain(), "Session is already a domain");
LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId());
ctx.Session()->ConvertToDomain();
@ -29,16 +34,36 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service, "called");
auto session = ctx.Session()->GetParent();
auto& kernel = system.Kernel();
auto* session = ctx.Session()->GetParent();
auto* port = session->GetParent()->GetParent();
// Open a reference to the session to simulate a new one being created.
session->Open();
session->GetClientSession().Open();
session->GetServerSession().Open();
// Reserve a new session from the process resource limit.
Kernel::KScopedResourceReservation session_reservation(
kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions);
if (!session_reservation.Succeeded()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(Kernel::ResultLimitReached);
}
// 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.
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(RESULT_SUCCESS);
rb.PushMoveObjects(session->GetClientSession());
rb.PushMoveObjects(clone->GetClientSession());
}
void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) {

View file

@ -150,31 +150,31 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
IPC::RequestParser rp{ctx};
std::string name(PopServiceName(rp));
// Find the named port.
auto result = service_manager.GetServicePort(name);
if (result.Failed()) {
LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw);
return result.Code();
}
auto* port = result.Unwrap();
// Reserve a new session from the process resource limit.
Kernel::KScopedResourceReservation session_reservation(
kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions);
R_UNLESS(session_reservation.Succeeded(), Kernel::ResultLimitReached);
// Create a new session.
auto* session = Kernel::KSession::Create(kernel);
session->Initialize(&port->GetClientPort(), std::move(name));
// Commit the session reservation.
session_reservation.Commit();
if (port->GetServerPort().GetHLEHandler()) {
port->GetServerPort().GetHLEHandler()->ClientConnected(&session->GetServerSession());
} else {
port->EnqueueSession(&session->GetServerSession());
}
// Enqueue the session with the named port.
port->EnqueueSession(&session->GetServerSession());
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
return MakeResult(&session->GetClientSession());
}

View file

@ -73,7 +73,7 @@ public:
if (port == nullptr) {
return nullptr;
}
return std::static_pointer_cast<T>(port->GetServerPort().GetHLEHandler());
return std::static_pointer_cast<T>(port->GetServerPort().GetSessionRequestHandler());
}
void InvokeControlRequest(Kernel::HLERequestContext& context);