kernel: Implement a more accurate IPC dispatch.

This commit is contained in:
bunnei 2019-11-25 18:28:48 -05:00
parent e3ee017e91
commit c3d3b173d3
19 changed files with 246 additions and 167 deletions

View file

@ -30,10 +30,7 @@ void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(RESULT_SUCCESS);
std::shared_ptr<Kernel::ClientSession> session{ctx.Session()->GetParent()->client};
rb.PushMoveObjects(session);
LOG_DEBUG(Service, "session={}", session->GetObjectId());
rb.PushMoveObjects(ctx.Session()->GetParent()->Client());
}
void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) {

View file

@ -36,10 +36,11 @@ static ResultCode ValidateServiceName(const std::string& name) {
return RESULT_SUCCESS;
}
void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self) {
void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self,
Kernel::KernelCore& kernel) {
ASSERT(self->sm_interface.expired());
auto sm = std::make_shared<SM>(self);
auto sm = std::make_shared<SM>(self, kernel);
sm->InstallAsNamedPort();
self->sm_interface = sm;
self->controller_interface = std::make_unique<Controller>();
@ -114,8 +115,6 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
std::string name(name_buf.begin(), end);
// TODO(yuriks): Permission checks go here
auto client_port = service_manager->GetServicePort(name);
if (client_port.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
@ -127,14 +126,22 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
return;
}
auto session = client_port.Unwrap()->Connect();
ASSERT(session.Succeeded());
if (session.Succeeded()) {
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, (*session)->GetObjectId());
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(session.Code());
rb.PushMoveObjects(std::move(session).Unwrap());
auto [client, server] = Kernel::Session::Create(kernel, name);
const auto& server_port = client_port.Unwrap()->GetServerPort();
if (server_port->GetHLEHandler()) {
server_port->GetHLEHandler()->ClientConnected(server);
} else {
server_port->AppendPendingSession(server);
}
// Wake the threads waiting on the ServerPort
server_port->WakeupAllWaitingThreads();
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, client->GetObjectId());
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(RESULT_SUCCESS);
rb.PushMoveObjects(std::move(client));
}
void SM::RegisterService(Kernel::HLERequestContext& ctx) {
@ -178,8 +185,8 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) {
rb.Push(service_manager->UnregisterService(name));
}
SM::SM(std::shared_ptr<ServiceManager> service_manager)
: ServiceFramework("sm:", 4), service_manager(std::move(service_manager)) {
SM::SM(std::shared_ptr<ServiceManager> service_manager, Kernel::KernelCore& kernel)
: ServiceFramework{"sm:", 4}, service_manager{std::move(service_manager)}, kernel{kernel} {
static const FunctionInfo functions[] = {
{0x00000000, &SM::Initialize, "Initialize"},
{0x00000001, &SM::GetService, "GetService"},

View file

@ -18,6 +18,7 @@
namespace Kernel {
class ClientPort;
class ClientSession;
class KernelCore;
class ServerPort;
class SessionRequestHandler;
} // namespace Kernel
@ -29,7 +30,7 @@ class Controller;
/// Interface to "sm:" service
class SM final : public ServiceFramework<SM> {
public:
explicit SM(std::shared_ptr<ServiceManager> service_manager);
explicit SM(std::shared_ptr<ServiceManager> service_manager, Kernel::KernelCore& kernel);
~SM() override;
private:
@ -39,11 +40,12 @@ private:
void UnregisterService(Kernel::HLERequestContext& ctx);
std::shared_ptr<ServiceManager> service_manager;
Kernel::KernelCore& kernel;
};
class ServiceManager {
public:
static void InstallInterfaces(std::shared_ptr<ServiceManager> self);
static void InstallInterfaces(std::shared_ptr<ServiceManager> self, Kernel::KernelCore& kernel);
ServiceManager();
~ServiceManager();