3
0
Fork 0
forked from suyu/suyu

kernel/server_session: Make data members private

Makes it much nicer to locally reason about server session behavior, as
part of its functionality isn't placed around other classes.
This commit is contained in:
Lioncash 2019-03-05 18:51:16 -05:00
parent 7526b6fce3
commit 221613d4ea
5 changed files with 73 additions and 32 deletions

View file

@ -17,21 +17,11 @@ ClientSession::~ClientSession() {
// This destructor will be called automatically when the last ClientSession handle is closed by // This destructor will be called automatically when the last ClientSession handle is closed by
// the emulated application. // the emulated application.
// Local references to ServerSession and SessionRequestHandler are necessary to guarantee they // A local reference to the ServerSession is necessary to guarantee it
// will be kept alive until after ClientDisconnected() returns. // will be kept alive until after ClientDisconnected() returns.
SharedPtr<ServerSession> server = parent->server; SharedPtr<ServerSession> server = parent->server;
if (server) { if (server) {
std::shared_ptr<SessionRequestHandler> hle_handler = server->hle_handler; server->ClientDisconnected();
if (hle_handler)
hle_handler->ClientDisconnected(server);
// TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set
// their WaitSynchronization result to 0xC920181A.
// Clean up the list of client threads with pending requests, they are unneeded now that the
// client endpoint is closed.
server->pending_requesting_threads.clear();
server->currently_handling = nullptr;
} }
parent->client = nullptr; parent->client = nullptr;

View file

@ -264,11 +264,11 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) {
// Write the domain objects to the command buffer, these go after the raw untranslated data. // Write the domain objects to the command buffer, these go after the raw untranslated data.
// TODO(Subv): This completely ignores C buffers. // TODO(Subv): This completely ignores C buffers.
std::size_t domain_offset = size - domain_message_header->num_objects; std::size_t domain_offset = size - domain_message_header->num_objects;
auto& request_handlers = server_session->domain_request_handlers;
for (auto& object : domain_objects) { for (const auto& object : domain_objects) {
request_handlers.emplace_back(object); server_session->AppendDomainRequestHandler(object);
dst_cmdbuf[domain_offset++] = static_cast<u32_le>(request_handlers.size()); dst_cmdbuf[domain_offset++] =
static_cast<u32_le>(server_session->NumDomainRequestHandlers());
} }
} }

View file

@ -63,6 +63,34 @@ void ServerSession::Acquire(Thread* thread) {
pending_requesting_threads.pop_back(); pending_requesting_threads.pop_back();
} }
void ServerSession::ClientDisconnected() {
// We keep a shared pointer to the hle handler to keep it alive throughout
// the call to ClientDisconnected, as ClientDisconnected invalidates the
// hle_handler member itself during the course of the function executing.
std::shared_ptr<SessionRequestHandler> handler = hle_handler;
if (handler) {
// Note that after this returns, this server session's hle_handler is
// invalidated (set to null).
handler->ClientDisconnected(this);
}
// TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set
// their WaitSynchronization result to 0xC920181A.
// Clean up the list of client threads with pending requests, they are unneeded now that the
// client endpoint is closed.
pending_requesting_threads.clear();
currently_handling = nullptr;
}
void ServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) {
domain_request_handlers.push_back(std::move(handler));
}
std::size_t ServerSession::NumDomainRequestHandlers() const {
return domain_request_handlers.size();
}
ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) {
auto* const domain_message_header = context.GetDomainMessageHeader(); auto* const domain_message_header = context.GetDomainMessageHeader();
if (domain_message_header) { if (domain_message_header) {

View file

@ -46,6 +46,14 @@ public:
return HANDLE_TYPE; return HANDLE_TYPE;
} }
Session* GetParent() {
return parent.get();
}
const Session* GetParent() const {
return parent.get();
}
using SessionPair = std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>>; using SessionPair = std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>>;
/** /**
@ -78,23 +86,16 @@ public:
void Acquire(Thread* thread) override; void Acquire(Thread* thread) override;
std::string name; ///< The name of this session (optional) /// Called when a client disconnection occurs.
std::shared_ptr<Session> parent; ///< The parent session, which links to the client endpoint. void ClientDisconnected();
std::shared_ptr<SessionRequestHandler>
hle_handler; ///< This session's HLE request handler (applicable when not a domain)
/// This is the list of domain request handlers (after conversion to a domain) /// Adds a new domain request handler to the collection of request handlers within
std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; /// this ServerSession instance.
void AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler);
/// List of threads that are pending a response after a sync request. This list is processed in /// Retrieves the total number of domain request handlers that have been
/// a LIFO manner, thus, the last request will be dispatched first. /// appended to this ServerSession instance.
/// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test. std::size_t NumDomainRequestHandlers() const;
std::vector<SharedPtr<Thread>> pending_requesting_threads;
/// Thread whose request is currently being handled. A request is considered "handled" when a
/// response is sent via svcReplyAndReceive.
/// TODO(Subv): Find a better name for this.
SharedPtr<Thread> currently_handling;
/// Returns true if the session has been converted to a domain, otherwise False /// Returns true if the session has been converted to a domain, otherwise False
bool IsDomain() const { bool IsDomain() const {
@ -129,8 +130,30 @@ private:
/// object handle. /// object handle.
ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context);
/// The parent session, which links to the client endpoint.
std::shared_ptr<Session> parent;
/// This session's HLE request handler (applicable when not a domain)
std::shared_ptr<SessionRequestHandler> hle_handler;
/// This is the list of domain request handlers (after conversion to a domain)
std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers;
/// List of threads that are pending a response after a sync request. This list is processed in
/// a LIFO manner, thus, the last request will be dispatched first.
/// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test.
std::vector<SharedPtr<Thread>> pending_requesting_threads;
/// Thread whose request is currently being handled. A request is considered "handled" when a
/// response is sent via svcReplyAndReceive.
/// TODO(Subv): Find a better name for this.
SharedPtr<Thread> currently_handling;
/// 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{};
/// The name of this session (optional)
std::string name;
}; };
} // namespace Kernel } // namespace Kernel

View file

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