|
|
@@ -11,7 +11,8 @@
|
|
|
#include <string>
|
|
|
#include <type_traits>
|
|
|
#include <vector>
|
|
|
-#include <boost/container/small_vector.hpp>
|
|
|
+
|
|
|
+#include "common/assert.h"
|
|
|
#include "common/common_types.h"
|
|
|
#include "common/concepts.h"
|
|
|
#include "common/swap.h"
|
|
|
@@ -84,6 +85,69 @@ public:
|
|
|
void ClientDisconnected(KServerSession* session);
|
|
|
};
|
|
|
|
|
|
+using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Manages the underlying HLE requests for a session, and whether (or not) the session should be
|
|
|
+ * treated as a domain. This is managed separately from server sessions, as this state is shared
|
|
|
+ * when objects are cloned.
|
|
|
+ */
|
|
|
+class SessionRequestManager final {
|
|
|
+public:
|
|
|
+ SessionRequestManager() = default;
|
|
|
+
|
|
|
+ bool IsDomain() const {
|
|
|
+ return is_domain;
|
|
|
+ }
|
|
|
+
|
|
|
+ void ConvertToDomain() {
|
|
|
+ domain_handlers = {session_handler};
|
|
|
+ is_domain = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::size_t DomainHandlerCount() const {
|
|
|
+ return domain_handlers.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ bool HasSessionHandler() const {
|
|
|
+ return session_handler != nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ SessionRequestHandler& SessionHandler() {
|
|
|
+ return *session_handler;
|
|
|
+ }
|
|
|
+
|
|
|
+ const SessionRequestHandler& SessionHandler() const {
|
|
|
+ return *session_handler;
|
|
|
+ }
|
|
|
+
|
|
|
+ void CloseDomainHandler(std::size_t index) {
|
|
|
+ if (index < DomainHandlerCount()) {
|
|
|
+ domain_handlers[index] = nullptr;
|
|
|
+ } else {
|
|
|
+ UNREACHABLE_MSG("Unexpected handler index {}", index);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ SessionRequestHandlerPtr DomainHandler(std::size_t index) const {
|
|
|
+ ASSERT_MSG(index < DomainHandlerCount(), "Unexpected handler index {}", index);
|
|
|
+ return domain_handlers.at(index);
|
|
|
+ }
|
|
|
+
|
|
|
+ void AppendDomainHandler(SessionRequestHandlerPtr&& handler) {
|
|
|
+ domain_handlers.emplace_back(std::move(handler));
|
|
|
+ }
|
|
|
+
|
|
|
+ void SetSessionHandler(SessionRequestHandlerPtr&& handler) {
|
|
|
+ session_handler = std::move(handler);
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ bool is_domain{};
|
|
|
+ SessionRequestHandlerPtr session_handler;
|
|
|
+ std::vector<SessionRequestHandlerPtr> domain_handlers;
|
|
|
+};
|
|
|
+
|
|
|
/**
|
|
|
* Class containing information about an in-flight IPC request being handled by an HLE service
|
|
|
* implementation. Services should avoid using old global APIs (e.g. Kernel::GetCommandBuffer()) and
|
|
|
@@ -224,53 +288,32 @@ public:
|
|
|
bool CanWriteBuffer(std::size_t buffer_index = 0) const;
|
|
|
|
|
|
Handle GetCopyHandle(std::size_t index) const {
|
|
|
- return copy_handles.at(index);
|
|
|
+ return incoming_copy_handles.at(index);
|
|
|
}
|
|
|
|
|
|
Handle GetMoveHandle(std::size_t index) const {
|
|
|
- return move_handles.at(index);
|
|
|
+ return incoming_move_handles.at(index);
|
|
|
}
|
|
|
|
|
|
void AddMoveObject(KAutoObject* object) {
|
|
|
- move_objects.emplace_back(object);
|
|
|
+ outgoing_move_objects.emplace_back(object);
|
|
|
}
|
|
|
|
|
|
void AddCopyObject(KAutoObject* object) {
|
|
|
- copy_objects.emplace_back(object);
|
|
|
+ outgoing_copy_objects.emplace_back(object);
|
|
|
}
|
|
|
|
|
|
- void AddDomainObject(std::shared_ptr<SessionRequestHandler> object) {
|
|
|
- domain_objects.emplace_back(std::move(object));
|
|
|
+ void AddDomainObject(SessionRequestHandlerPtr object) {
|
|
|
+ outgoing_domain_objects.emplace_back(std::move(object));
|
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
|
- std::shared_ptr<T> GetDomainRequestHandler(std::size_t index) const {
|
|
|
- return std::static_pointer_cast<T>(domain_request_handlers.at(index));
|
|
|
- }
|
|
|
-
|
|
|
- void SetDomainRequestHandlers(
|
|
|
- const std::vector<std::shared_ptr<SessionRequestHandler>>& handlers) {
|
|
|
- domain_request_handlers = handlers;
|
|
|
- }
|
|
|
-
|
|
|
- /// Clears the list of objects so that no lingering objects are written accidentally to the
|
|
|
- /// response buffer.
|
|
|
- void ClearIncomingObjects() {
|
|
|
- move_objects.clear();
|
|
|
- copy_objects.clear();
|
|
|
- domain_objects.clear();
|
|
|
+ std::shared_ptr<T> GetDomainHandler(std::size_t index) const {
|
|
|
+ return std::static_pointer_cast<T>(manager->DomainHandler(index));
|
|
|
}
|
|
|
|
|
|
- std::size_t NumMoveObjects() const {
|
|
|
- return move_objects.size();
|
|
|
- }
|
|
|
-
|
|
|
- std::size_t NumCopyObjects() const {
|
|
|
- return copy_objects.size();
|
|
|
- }
|
|
|
-
|
|
|
- std::size_t NumDomainObjects() const {
|
|
|
- return domain_objects.size();
|
|
|
+ void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) {
|
|
|
+ manager = std::move(manager_);
|
|
|
}
|
|
|
|
|
|
std::string Description() const;
|
|
|
@@ -292,12 +335,12 @@ private:
|
|
|
Kernel::KServerSession* server_session{};
|
|
|
KThread* thread;
|
|
|
|
|
|
- // TODO(yuriks): Check common usage of this and optimize size accordingly
|
|
|
- boost::container::small_vector<Handle, 8> move_handles;
|
|
|
- boost::container::small_vector<Handle, 8> copy_handles;
|
|
|
- boost::container::small_vector<KAutoObject*, 8> move_objects;
|
|
|
- boost::container::small_vector<KAutoObject*, 8> copy_objects;
|
|
|
- boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects;
|
|
|
+ std::vector<Handle> incoming_move_handles;
|
|
|
+ std::vector<Handle> incoming_copy_handles;
|
|
|
+
|
|
|
+ std::vector<KAutoObject*> outgoing_move_objects;
|
|
|
+ std::vector<KAutoObject*> outgoing_copy_objects;
|
|
|
+ std::vector<SessionRequestHandlerPtr> outgoing_domain_objects;
|
|
|
|
|
|
std::optional<IPC::CommandHeader> command_header;
|
|
|
std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header;
|
|
|
@@ -311,12 +354,12 @@ private:
|
|
|
|
|
|
u32_le command{};
|
|
|
u64 pid{};
|
|
|
+ u32 write_size{};
|
|
|
u32 data_payload_offset{};
|
|
|
u32 handles_offset{};
|
|
|
u32 domain_offset{};
|
|
|
- u32 data_size{};
|
|
|
|
|
|
- std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers;
|
|
|
+ std::shared_ptr<SessionRequestManager> manager;
|
|
|
bool is_thread_waiting{};
|
|
|
|
|
|
KernelCore& kernel;
|