2023-02-18 13:26:48 -08:00
|
|
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
#include "common/scope_exit.h"
|
|
|
|
|
|
|
|
#include "core/core.h"
|
|
|
|
#include "core/hle/kernel/k_client_port.h"
|
|
|
|
#include "core/hle/kernel/k_client_session.h"
|
|
|
|
#include "core/hle/kernel/k_event.h"
|
|
|
|
#include "core/hle/kernel/k_object_name.h"
|
|
|
|
#include "core/hle/kernel/k_port.h"
|
|
|
|
#include "core/hle/kernel/k_server_port.h"
|
|
|
|
#include "core/hle/kernel/k_server_session.h"
|
|
|
|
#include "core/hle/kernel/k_synchronization_object.h"
|
|
|
|
#include "core/hle/kernel/svc_results.h"
|
2023-02-19 11:42:12 -08:00
|
|
|
#include "core/hle/service/hle_ipc.h"
|
|
|
|
#include "core/hle/service/ipc_helpers.h"
|
2023-02-18 13:26:48 -08:00
|
|
|
#include "core/hle/service/server_manager.h"
|
|
|
|
#include "core/hle/service/sm/sm.h"
|
|
|
|
|
|
|
|
namespace Service {
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
enum class UserDataTag {
|
2023-02-18 13:26:48 -08:00
|
|
|
Port,
|
|
|
|
Session,
|
2023-02-19 05:44:54 -08:00
|
|
|
DeferEvent,
|
2023-02-18 13:26:48 -08:00
|
|
|
};
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
class Port : public MultiWaitHolder, public Common::IntrusiveListBaseNode<Port> {
|
|
|
|
public:
|
|
|
|
explicit Port(Kernel::KServerPort* server_port, SessionRequestHandlerFactory&& handler_factory)
|
|
|
|
: MultiWaitHolder(server_port), m_handler_factory(std::move(handler_factory)) {
|
|
|
|
this->SetUserData(static_cast<uintptr_t>(UserDataTag::Port));
|
|
|
|
}
|
|
|
|
|
|
|
|
~Port() {
|
|
|
|
this->GetNativeHandle()->Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
SessionRequestHandlerPtr CreateHandler() {
|
|
|
|
return m_handler_factory();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const SessionRequestHandlerFactory m_handler_factory;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Session : public MultiWaitHolder, public Common::IntrusiveListBaseNode<Session> {
|
|
|
|
public:
|
|
|
|
explicit Session(Kernel::KServerSession* server_session,
|
|
|
|
std::shared_ptr<SessionRequestManager>&& manager)
|
|
|
|
: MultiWaitHolder(server_session), m_manager(std::move(manager)) {
|
|
|
|
this->SetUserData(static_cast<uintptr_t>(UserDataTag::Session));
|
|
|
|
}
|
|
|
|
|
|
|
|
~Session() {
|
|
|
|
this->GetNativeHandle()->Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<SessionRequestManager>& GetManager() {
|
|
|
|
return m_manager;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<HLERequestContext>& GetContext() {
|
|
|
|
return m_context;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::shared_ptr<SessionRequestManager> m_manager;
|
|
|
|
std::shared_ptr<HLERequestContext> m_context;
|
|
|
|
};
|
|
|
|
|
|
|
|
ServerManager::ServerManager(Core::System& system) : m_system{system}, m_selection_mutex{system} {
|
2023-02-18 13:26:48 -08:00
|
|
|
// Initialize event.
|
2024-02-07 09:09:26 -08:00
|
|
|
m_wakeup_event = Kernel::KEvent::Create(system.Kernel());
|
|
|
|
m_wakeup_event->Initialize(nullptr);
|
2023-04-29 18:16:09 -07:00
|
|
|
|
|
|
|
// Register event.
|
2024-02-07 09:09:26 -08:00
|
|
|
Kernel::KEvent::Register(system.Kernel(), m_wakeup_event);
|
|
|
|
|
|
|
|
// Link to holder.
|
|
|
|
m_wakeup_holder.emplace(std::addressof(m_wakeup_event->GetReadableEvent()));
|
|
|
|
m_wakeup_holder->LinkToMultiWait(std::addressof(m_deferred_list));
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ServerManager::~ServerManager() {
|
|
|
|
// Signal stop.
|
|
|
|
m_stop_source.request_stop();
|
2024-02-07 09:09:26 -08:00
|
|
|
m_wakeup_event->Signal();
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
// Wait for processing to stop.
|
2023-06-20 08:41:38 -07:00
|
|
|
m_stopped.Wait();
|
2023-02-18 13:26:48 -08:00
|
|
|
m_threads.clear();
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Clean up ports.
|
|
|
|
for (auto it = m_servers.begin(); it != m_servers.end(); it = m_servers.erase(it)) {
|
|
|
|
delete std::addressof(*it);
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up sessions.
|
2024-02-07 09:09:26 -08:00
|
|
|
for (auto it = m_sessions.begin(); it != m_sessions.end(); it = m_sessions.erase(it)) {
|
|
|
|
delete std::addressof(*it);
|
2023-02-19 05:44:54 -08:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Close wakeup event.
|
|
|
|
m_wakeup_event->GetReadableEvent().Close();
|
|
|
|
m_wakeup_event->Close();
|
2023-02-19 05:44:54 -08:00
|
|
|
|
|
|
|
if (m_deferral_event) {
|
|
|
|
m_deferral_event->GetReadableEvent().Close();
|
|
|
|
// Write event is owned by ServiceManager
|
|
|
|
}
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ServerManager::RunServer(std::unique_ptr<ServerManager>&& server_manager) {
|
|
|
|
server_manager->m_system.RunServer(std::move(server_manager));
|
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
Result ServerManager::RegisterSession(Kernel::KServerSession* server_session,
|
2023-02-19 11:42:12 -08:00
|
|
|
std::shared_ptr<SessionRequestManager> manager) {
|
2023-02-18 13:26:48 -08:00
|
|
|
// We are taking ownership of the server session, so don't open it.
|
2024-02-07 09:09:26 -08:00
|
|
|
auto* session = new Session(server_session, std::move(manager));
|
|
|
|
|
2023-02-18 13:26:48 -08:00
|
|
|
// Begin tracking the server session.
|
|
|
|
{
|
2024-02-07 09:09:26 -08:00
|
|
|
std::scoped_lock ll{m_deferred_list_mutex};
|
|
|
|
m_sessions.push_back(*session);
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Register to wait on the session.
|
|
|
|
this->LinkToDeferredList(session);
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
|
|
|
Result ServerManager::RegisterNamedService(const std::string& service_name,
|
2023-12-09 08:22:42 -08:00
|
|
|
SessionRequestHandlerFactory&& handler_factory,
|
2023-02-18 13:26:48 -08:00
|
|
|
u32 max_sessions) {
|
2023-12-17 17:46:41 -08:00
|
|
|
// Add the new server to sm: and get the moved server port.
|
|
|
|
Kernel::KServerPort* server_port{};
|
|
|
|
R_ASSERT(m_system.ServiceManager().RegisterService(std::addressof(server_port), service_name,
|
|
|
|
max_sessions, handler_factory));
|
2023-02-18 13:26:48 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// We are taking ownership of the server port, so don't open it.
|
|
|
|
auto* server = new Port(server_port, std::move(handler_factory));
|
|
|
|
|
2023-02-18 13:26:48 -08:00
|
|
|
// Begin tracking the server port.
|
|
|
|
{
|
2024-02-07 09:09:26 -08:00
|
|
|
std::scoped_lock ll{m_deferred_list_mutex};
|
|
|
|
m_servers.push_back(*server);
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Register to wait on the server port.
|
|
|
|
this->LinkToDeferredList(server);
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
2023-12-09 08:22:42 -08:00
|
|
|
Result ServerManager::RegisterNamedService(const std::string& service_name,
|
|
|
|
std::shared_ptr<SessionRequestHandler>&& handler,
|
|
|
|
u32 max_sessions) {
|
|
|
|
// Make the factory.
|
|
|
|
const auto HandlerFactory = [handler]() { return handler; };
|
|
|
|
|
|
|
|
// Register the service with the new factory.
|
|
|
|
R_RETURN(this->RegisterNamedService(service_name, std::move(HandlerFactory), max_sessions));
|
|
|
|
}
|
|
|
|
|
2023-02-18 13:26:48 -08:00
|
|
|
Result ServerManager::ManageNamedPort(const std::string& service_name,
|
2023-12-09 08:22:42 -08:00
|
|
|
SessionRequestHandlerFactory&& handler_factory,
|
2023-02-18 13:26:48 -08:00
|
|
|
u32 max_sessions) {
|
|
|
|
// Create a new port.
|
|
|
|
auto* port = Kernel::KPort::Create(m_system.Kernel());
|
2023-03-06 17:34:25 -08:00
|
|
|
port->Initialize(max_sessions, false, 0);
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
// Register the port.
|
|
|
|
Kernel::KPort::Register(m_system.Kernel(), port);
|
|
|
|
|
|
|
|
// Ensure that our reference to the port is closed if we fail to register it.
|
|
|
|
SCOPE_EXIT({
|
|
|
|
port->GetClientPort().Close();
|
|
|
|
port->GetServerPort().Close();
|
|
|
|
});
|
|
|
|
|
|
|
|
// Register the object name with the kernel.
|
|
|
|
R_TRY(Kernel::KObjectName::NewFromName(m_system.Kernel(), std::addressof(port->GetClientPort()),
|
|
|
|
service_name.c_str()));
|
|
|
|
|
|
|
|
// Open a new reference to the server port.
|
|
|
|
port->GetServerPort().Open();
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Transfer ownership into a new port object.
|
|
|
|
auto* server = new Port(std::addressof(port->GetServerPort()), std::move(handler_factory));
|
|
|
|
|
|
|
|
// Begin tracking the port.
|
2023-02-18 13:26:48 -08:00
|
|
|
{
|
2024-02-07 09:09:26 -08:00
|
|
|
std::scoped_lock ll{m_deferred_list_mutex};
|
|
|
|
m_servers.push_back(*server);
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Register to wait on the port.
|
|
|
|
this->LinkToDeferredList(server);
|
|
|
|
|
2023-02-18 13:26:48 -08:00
|
|
|
// We succeeded.
|
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
2023-02-19 05:44:54 -08:00
|
|
|
Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) {
|
|
|
|
// Create a new event.
|
|
|
|
m_deferral_event = Kernel::KEvent::Create(m_system.Kernel());
|
|
|
|
ASSERT(m_deferral_event != nullptr);
|
|
|
|
|
|
|
|
// Initialize the event.
|
|
|
|
m_deferral_event->Initialize(nullptr);
|
|
|
|
|
2023-04-29 18:16:09 -07:00
|
|
|
// Register the event.
|
|
|
|
Kernel::KEvent::Register(m_system.Kernel(), m_deferral_event);
|
|
|
|
|
2023-02-19 05:44:54 -08:00
|
|
|
// Set the output.
|
|
|
|
*out_event = m_deferral_event;
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Register to wait on the event.
|
|
|
|
m_deferral_holder.emplace(std::addressof(m_deferral_event->GetReadableEvent()));
|
|
|
|
m_deferral_holder->SetUserData(static_cast<uintptr_t>(UserDataTag::DeferEvent));
|
|
|
|
this->LinkToDeferredList(std::addressof(*m_deferral_holder));
|
|
|
|
|
2023-02-19 05:44:54 -08:00
|
|
|
// We succeeded.
|
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
2023-02-18 13:26:48 -08:00
|
|
|
void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_threads) {
|
|
|
|
for (size_t i = 0; i < num_threads; i++) {
|
|
|
|
auto thread_name = fmt::format("{}:{}", name, i + 1);
|
|
|
|
m_threads.emplace_back(m_system.Kernel().RunOnHostCoreThread(
|
|
|
|
std::move(thread_name), [&] { this->LoopProcessImpl(); }));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Result ServerManager::LoopProcess() {
|
2023-06-20 08:41:38 -07:00
|
|
|
SCOPE_EXIT({ m_stopped.Set(); });
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
R_RETURN(this->LoopProcessImpl());
|
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
void ServerManager::LinkToDeferredList(MultiWaitHolder* holder) {
|
|
|
|
// Link.
|
|
|
|
{
|
|
|
|
std::scoped_lock lk{m_deferred_list_mutex};
|
|
|
|
holder->LinkToMultiWait(std::addressof(m_deferred_list));
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Signal the wakeup event.
|
|
|
|
m_wakeup_event->Signal();
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
void ServerManager::LinkDeferred() {
|
|
|
|
std::scoped_lock lk{m_deferred_list_mutex};
|
|
|
|
m_multi_wait.MoveAll(std::addressof(m_deferred_list));
|
|
|
|
}
|
2023-02-18 13:26:48 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
MultiWaitHolder* ServerManager::WaitSignaled() {
|
2023-02-18 13:26:48 -08:00
|
|
|
// Ensure we are the only thread waiting for this server.
|
2024-02-07 09:09:26 -08:00
|
|
|
std::scoped_lock lk{m_selection_mutex};
|
2023-02-18 13:26:48 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
while (true) {
|
|
|
|
this->LinkDeferred();
|
2023-02-18 13:26:48 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// If we're done, return before we start waiting.
|
|
|
|
if (m_stop_source.stop_requested()) {
|
|
|
|
return nullptr;
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
auto* selected = m_multi_wait.WaitAny(m_system.Kernel());
|
|
|
|
if (selected == std::addressof(*m_wakeup_holder)) {
|
|
|
|
// Clear and restart if we were woken up.
|
|
|
|
m_wakeup_event->Clear();
|
|
|
|
} else {
|
|
|
|
// Unlink and handle the event.
|
|
|
|
selected->UnlinkFromMultiWait();
|
|
|
|
return selected;
|
2023-02-19 05:44:54 -08:00
|
|
|
}
|
2024-02-07 09:09:26 -08:00
|
|
|
}
|
|
|
|
}
|
2023-02-19 05:44:54 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
Result ServerManager::Process(MultiWaitHolder* holder) {
|
|
|
|
switch (static_cast<UserDataTag>(holder->GetUserData())) {
|
|
|
|
case UserDataTag::Session:
|
|
|
|
R_RETURN(this->OnSessionEvent(static_cast<Session*>(holder)));
|
|
|
|
case UserDataTag::Port:
|
|
|
|
R_RETURN(this->OnPortEvent(static_cast<Port*>(holder)));
|
|
|
|
case UserDataTag::DeferEvent:
|
|
|
|
R_RETURN(this->OnDeferralEvent());
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
2023-02-18 13:26:48 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
bool ServerManager::WaitAndProcessImpl() {
|
|
|
|
if (auto* signaled_holder = this->WaitSignaled(); signaled_holder != nullptr) {
|
|
|
|
R_ASSERT(this->Process(signaled_holder));
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
2024-02-07 09:09:26 -08:00
|
|
|
}
|
2023-02-18 13:26:48 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
Result ServerManager::LoopProcessImpl() {
|
|
|
|
while (!m_stop_source.stop_requested()) {
|
|
|
|
this->WaitAndProcessImpl();
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
2024-02-07 09:09:26 -08:00
|
|
|
|
|
|
|
R_SUCCEED();
|
2023-02-18 13:26:48 -08:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
Result ServerManager::OnPortEvent(Port* server) {
|
2023-02-18 13:26:48 -08:00
|
|
|
// Accept a new server session.
|
2024-02-07 09:09:26 -08:00
|
|
|
auto* server_port = static_cast<Kernel::KServerPort*>(server->GetNativeHandle());
|
|
|
|
Kernel::KServerSession* server_session = server_port->AcceptSession();
|
|
|
|
ASSERT(server_session != nullptr);
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
// Create the session manager and install the handler.
|
2023-02-19 11:42:12 -08:00
|
|
|
auto manager = std::make_shared<SessionRequestManager>(m_system.Kernel(), *this);
|
2024-02-07 09:09:26 -08:00
|
|
|
manager->SetSessionHandler(server->CreateHandler());
|
2023-02-18 13:26:48 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Create and register the new session.
|
|
|
|
this->RegisterSession(server_session, std::move(manager));
|
2023-02-18 13:26:48 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Resume tracking the port.
|
|
|
|
this->LinkToDeferredList(server);
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
// We succeeded.
|
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
Result ServerManager::OnSessionEvent(Session* session) {
|
|
|
|
Result res = ResultSuccess;
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
// Try to receive a message.
|
2024-02-07 09:09:26 -08:00
|
|
|
auto* server_session = static_cast<Kernel::KServerSession*>(session->GetNativeHandle());
|
|
|
|
res = server_session->ReceiveRequestHLE(&session->GetContext(), session->GetManager());
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
// If the session has been closed, we're done.
|
2024-02-07 09:09:26 -08:00
|
|
|
if (res == Kernel::ResultSessionClosed) {
|
|
|
|
this->DestroySession(session);
|
2023-02-18 13:26:48 -08:00
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
R_ASSERT(res);
|
2023-02-19 05:44:54 -08:00
|
|
|
|
|
|
|
// Complete the sync request with deferral handling.
|
2024-02-07 09:09:26 -08:00
|
|
|
R_RETURN(this->CompleteSyncRequest(session));
|
2023-02-19 05:44:54 -08:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
Result ServerManager::CompleteSyncRequest(Session* session) {
|
|
|
|
Result res = ResultSuccess;
|
|
|
|
Result service_res = ResultSuccess;
|
2023-02-19 05:44:54 -08:00
|
|
|
|
|
|
|
// Mark the request as not deferred.
|
2024-02-07 09:09:26 -08:00
|
|
|
session->GetContext()->SetIsDeferred(false);
|
2023-02-19 05:44:54 -08:00
|
|
|
|
2023-02-18 13:26:48 -08:00
|
|
|
// Complete the request. We have exclusive access to this session.
|
2024-02-07 09:09:26 -08:00
|
|
|
auto* server_session = static_cast<Kernel::KServerSession*>(session->GetNativeHandle());
|
|
|
|
service_res =
|
|
|
|
session->GetManager()->CompleteSyncRequest(server_session, *session->GetContext());
|
2023-02-19 05:44:54 -08:00
|
|
|
|
|
|
|
// If we've been deferred, we're done.
|
2024-02-07 09:09:26 -08:00
|
|
|
if (session->GetContext()->GetIsDeferred()) {
|
|
|
|
// Insert into deferred session list.
|
|
|
|
std::scoped_lock ll{m_deferred_list_mutex};
|
|
|
|
m_deferred_sessions.push_back(session);
|
2023-02-19 05:44:54 -08:00
|
|
|
|
|
|
|
// Finish.
|
|
|
|
R_SUCCEED();
|
|
|
|
}
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
// Send the reply.
|
2024-02-07 09:09:26 -08:00
|
|
|
res = server_session->SendReplyHLE();
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
// If the session has been closed, we're done.
|
2024-02-07 09:09:26 -08:00
|
|
|
if (res == Kernel::ResultSessionClosed || service_res == IPC::ResultSessionClosed) {
|
|
|
|
this->DestroySession(session);
|
2023-02-18 13:26:48 -08:00
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
R_ASSERT(res);
|
|
|
|
R_ASSERT(service_res);
|
2023-02-18 13:26:48 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// We succeeded, so we can process future messages on this session.
|
|
|
|
this->LinkToDeferredList(session);
|
2023-02-18 13:26:48 -08:00
|
|
|
|
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
Result ServerManager::OnDeferralEvent() {
|
|
|
|
// Clear event before grabbing the list.
|
|
|
|
m_deferral_event->Clear();
|
2023-02-19 05:44:54 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Get and clear list.
|
|
|
|
const auto deferrals = [&] {
|
|
|
|
std::scoped_lock lk{m_deferred_list_mutex};
|
|
|
|
return std::move(m_deferred_sessions);
|
|
|
|
}();
|
2023-02-19 05:44:54 -08:00
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
// Relink deferral event.
|
|
|
|
this->LinkToDeferredList(std::addressof(*m_deferral_holder));
|
|
|
|
|
|
|
|
// For each session, try again to complete the request.
|
|
|
|
for (auto* session : deferrals) {
|
|
|
|
R_ASSERT(this->CompleteSyncRequest(session));
|
2023-02-19 05:44:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
2024-02-07 09:09:26 -08:00
|
|
|
void ServerManager::DestroySession(Session* session) {
|
|
|
|
// Unlink.
|
|
|
|
{
|
|
|
|
std::scoped_lock lk{m_deferred_list_mutex};
|
|
|
|
m_sessions.erase(m_sessions.iterator_to(*session));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free the session.
|
|
|
|
delete session;
|
|
|
|
}
|
|
|
|
|
2023-02-18 13:26:48 -08:00
|
|
|
} // namespace Service
|