summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-04-14 02:48:37 +0200
committerbunnei <bunneidev@gmail.com>2021-05-06 01:40:51 +0200
commit7444963bbb300cff269e410948de7fa577f5ff16 (patch)
tree6e0000cb345dc02c8f2ca38958b7c90383f45b03 /src/core/hle/kernel
parenthle: kernel: svc: Migrate GetThreadContext, GetThreadCoreMask. (diff)
downloadyuzu-7444963bbb300cff269e410948de7fa577f5ff16.tar
yuzu-7444963bbb300cff269e410948de7fa577f5ff16.tar.gz
yuzu-7444963bbb300cff269e410948de7fa577f5ff16.tar.bz2
yuzu-7444963bbb300cff269e410948de7fa577f5ff16.tar.lz
yuzu-7444963bbb300cff269e410948de7fa577f5ff16.tar.xz
yuzu-7444963bbb300cff269e410948de7fa577f5ff16.tar.zst
yuzu-7444963bbb300cff269e410948de7fa577f5ff16.zip
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/client_port.cpp14
-rw-r--r--src/core/hle/kernel/client_port.h4
-rw-r--r--src/core/hle/kernel/client_session.cpp52
-rw-r--r--src/core/hle/kernel/handle_table.cpp5
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp23
-rw-r--r--src/core/hle/kernel/hle_ipc.h18
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp4
-rw-r--r--src/core/hle/kernel/k_client_session.cpp31
-rw-r--r--src/core/hle/kernel/k_client_session.h (renamed from src/core/hle/kernel/client_session.h)54
-rw-r--r--src/core/hle/kernel/k_server_session.cpp (renamed from src/core/hle/kernel/server_session.cpp)65
-rw-r--r--src/core/hle/kernel/k_server_session.h (renamed from src/core/hle/kernel/server_session.h)73
-rw-r--r--src/core/hle/kernel/k_session.cpp67
-rw-r--r--src/core/hle/kernel/k_session.h108
-rw-r--r--src/core/hle/kernel/kernel.h8
-rw-r--r--src/core/hle/kernel/server_port.cpp10
-rw-r--r--src/core/hle/kernel/server_port.h8
-rw-r--r--src/core/hle/kernel/service_thread.cpp29
-rw-r--r--src/core/hle/kernel/service_thread.h4
-rw-r--r--src/core/hle/kernel/session.cpp41
-rw-r--r--src/core/hle/kernel/session.h64
-rw-r--r--src/core/hle/kernel/svc.cpp18
21 files changed, 384 insertions, 316 deletions
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index d856b83e3..ce88da1c3 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -3,11 +3,10 @@
// Refer to the license.txt file included.
#include "core/hle/kernel/client_port.h"
-#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/k_session.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/server_port.h"
-#include "core/hle/kernel/session.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
@@ -19,21 +18,22 @@ std::shared_ptr<ServerPort> ClientPort::GetServerPort() const {
return server_port;
}
-ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
+ResultVal<KClientSession*> ClientPort::Connect() {
if (active_sessions >= max_sessions) {
return ResultOutOfSessions;
}
active_sessions++;
- auto [client, server] = Kernel::Session::Create(kernel, name);
+ auto* session = Kernel::KSession::Create(kernel);
+ session->Initialize(name + ":ClientPort");
if (server_port->HasHLEHandler()) {
- server_port->GetHLEHandler()->ClientConnected(client, std::move(server));
+ server_port->GetHLEHandler()->ClientConnected(session);
} else {
- server_port->AppendPendingSession(std::move(server));
+ server_port->AppendPendingSession(std::addressof(session->GetServerSession()));
}
- return MakeResult(std::move(client));
+ return MakeResult(std::addressof(session->GetClientSession()));
}
void ClientPort::ConnectionClosed() {
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 77559ebf9..0b20fef40 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -13,7 +13,7 @@
namespace Kernel {
-class ClientSession;
+class KClientSession;
class KernelCore;
class ServerPort;
@@ -43,7 +43,7 @@ public:
* waiting on it to awake.
* @returns ClientSession The client endpoint of the created Session pair, or error code.
*/
- ResultVal<std::shared_ptr<ClientSession>> Connect();
+ ResultVal<KClientSession*> Connect();
/**
* Signifies that a previously active connection has been closed,
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp
deleted file mode 100644
index fa9cad498..000000000
--- a/src/core/hle/kernel/client_session.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2019 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/kernel/client_session.h"
-#include "core/hle/kernel/hle_ipc.h"
-#include "core/hle/kernel/k_thread.h"
-#include "core/hle/kernel/server_session.h"
-#include "core/hle/kernel/session.h"
-#include "core/hle/kernel/svc_results.h"
-#include "core/hle/result.h"
-
-namespace Kernel {
-
-ClientSession::ClientSession(KernelCore& kernel) : KSynchronizationObject{kernel} {}
-
-ClientSession::~ClientSession() {
- // This destructor will be called automatically when the last ClientSession handle is closed by
- // the emulated application.
- if (parent->Server()) {
- parent->Server()->ClientDisconnected();
- }
-}
-
-bool ClientSession::IsSignaled() const {
- UNIMPLEMENTED();
- return true;
-}
-
-ResultVal<std::shared_ptr<ClientSession>> ClientSession::Create(KernelCore& kernel,
- std::shared_ptr<Session> parent,
- std::string name) {
- std::shared_ptr<ClientSession> client_session{std::make_shared<ClientSession>(kernel)};
-
- client_session->name = std::move(name);
- client_session->parent = std::move(parent);
-
- return MakeResult(std::move(client_session));
-}
-
-ResultCode ClientSession::SendSyncRequest(KThread* thread, Core::Memory::Memory& memory,
- Core::Timing::CoreTiming& core_timing) {
- // Keep ServerSession alive until we're done working with it.
- if (!parent->Server()) {
- return ResultSessionClosed;
- }
-
- // Signal the server session that new data is available
- return parent->Server()->HandleSyncRequest(std::move(thread), memory, core_timing);
-}
-
-} // namespace Kernel
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index adfcd3c5b..ddb1e6fb2 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -56,7 +56,10 @@ ResultVal<Handle> HandleTable::Create(Object* obj) {
case HandleType::Event:
case HandleType::Process:
case HandleType::ReadableEvent:
- case HandleType::WritableEvent: {
+ case HandleType::WritableEvent:
+ case HandleType::ClientSession:
+ case HandleType::ServerSession:
+ case HandleType::Session: {
Handle handle{};
Add(&handle, reinterpret_cast<KAutoObject*>(obj), {});
return MakeResult<Handle>(handle);
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 1e831aaca..d647d9dd3 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -19,12 +19,12 @@
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
+#include "core/hle/kernel/k_server_session.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/time_manager.h"
#include "core/memory.h"
@@ -35,24 +35,19 @@ SessionRequestHandler::SessionRequestHandler() = default;
SessionRequestHandler::~SessionRequestHandler() = default;
-void SessionRequestHandler::ClientConnected(std::shared_ptr<ClientSession> client_session,
- std::shared_ptr<ServerSession> server_session) {
- server_session->SetHleHandler(shared_from_this());
- client_sessions.push_back(std::move(client_session));
- server_sessions.push_back(std::move(server_session));
+void SessionRequestHandler::ClientConnected(KSession* session) {
+ session->GetServerSession().SetHleHandler(shared_from_this());
+ sessions.push_back(session);
}
-void SessionRequestHandler::ClientDisconnected(
- const std::shared_ptr<ServerSession>& server_session) {
- server_session->SetHleHandler(nullptr);
- boost::range::remove_erase(server_sessions, server_session);
+void SessionRequestHandler::ClientDisconnected(KSession* session) {
+ session->GetServerSession().SetHleHandler(nullptr);
+ boost::range::remove_erase(sessions, session);
}
HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_,
- std::shared_ptr<ServerSession> server_session_,
- KThread* thread_)
- : server_session(std::move(server_session_)),
- thread(thread_), kernel{kernel_}, memory{memory_} {
+ KServerSession* server_session_, KThread* thread_)
+ : server_session(server_session_), thread(thread_), kernel{kernel_}, memory{memory_} {
cmd_buf[0] = 0;
}
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 74a95bc76..dc5c3b47d 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -39,10 +39,10 @@ class HandleTable;
class HLERequestContext;
class KernelCore;
class Process;
-class ClientSession;
-class ServerSession;
+class KServerSession;
class KThread;
class KReadableEvent;
+class KSession;
class KWritableEvent;
enum class ThreadWakeupReason;
@@ -72,22 +72,20 @@ public:
* associated ServerSession alive for the duration of the connection.
* @param server_session Owning pointer to the ServerSession associated with the connection.
*/
- void ClientConnected(
- std::shared_ptr<ClientSession> client_session, std::shared_ptr<ServerSession> server_session);
+ void ClientConnected(KSession* session);
/**
* Signals that a client has just disconnected from this HLE handler and releases the
* associated ServerSession.
* @param server_session ServerSession associated with the connection.
*/
- void ClientDisconnected(const std::shared_ptr<ServerSession>& server_session);
+ void ClientDisconnected(KSession* session);
protected:
/// List of sessions that are connected to this handler.
/// A ServerSession whose server endpoint is an HLE implementation is kept alive by this list
/// for the duration of the connection.
- std::vector<std::shared_ptr<ClientSession>> client_sessions;
- std::vector<std::shared_ptr<ServerSession>> server_sessions;
+ std::vector<KSession*> sessions;
};
/**
@@ -112,7 +110,7 @@ protected:
class HLERequestContext {
public:
explicit HLERequestContext(KernelCore& kernel, Core::Memory::Memory& memory,
- std::shared_ptr<ServerSession> session, KThread* thread);
+ KServerSession* session, KThread* thread);
~HLERequestContext();
/// Returns a pointer to the IPC command buffer for this request.
@@ -124,7 +122,7 @@ public:
* Returns the session through which this request was made. This can be used as a map key to
* access per-client data on services.
*/
- const std::shared_ptr<Kernel::ServerSession>& Session() const {
+ Kernel::KServerSession* Session() {
return server_session;
}
@@ -288,7 +286,7 @@ private:
void ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming);
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
- std::shared_ptr<Kernel::ServerSession> server_session;
+ Kernel::KServerSession* server_session{};
KThread* thread;
// TODO(yuriks): Check common usage of this and optimize size accordingly
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index b292f7db2..84d509d52 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -12,6 +12,7 @@
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_memory_manager.h"
+#include "core/hle/kernel/k_session.h"
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/k_system_control.h"
#include "core/hle/kernel/k_thread.h"
@@ -27,7 +28,8 @@ namespace Kernel::Init {
HANDLER(Process, (SLAB_COUNT(Process)), ##__VA_ARGS__) \
HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \
HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \
- HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__)
+ HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \
+ HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__)
namespace {
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp
new file mode 100644
index 000000000..0618dc246
--- /dev/null
+++ b/src/core/hle/kernel/k_client_session.cpp
@@ -0,0 +1,31 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/k_client_session.h"
+#include "core/hle/kernel/k_server_session.h"
+#include "core/hle/kernel/k_session.h"
+#include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/svc_results.h"
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+KClientSession::KClientSession(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {}
+KClientSession::~KClientSession() = default;
+
+void KClientSession::Destroy() {
+ parent->OnClientClosed();
+ parent->Close();
+}
+
+void KClientSession::OnServerClosed() {}
+
+ResultCode KClientSession::SendSyncRequest(KThread* thread, Core::Memory::Memory& memory,
+ Core::Timing::CoreTiming& core_timing) {
+ // Signal the server session that new data is available
+ return parent->GetServerSession().HandleSyncRequest(thread, memory, core_timing);
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/k_client_session.h
index 7a1d15d0c..c4b193773 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/k_client_session.h
@@ -1,4 +1,4 @@
-// Copyright 2019 yuzu emulator team
+// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -7,7 +7,9 @@
#include <memory>
#include <string>
+#include "core/hle/kernel/k_auto_object.h"
#include "core/hle/kernel/k_synchronization_object.h"
+#include "core/hle/kernel/slab_helpers.h"
#include "core/hle/result.h"
union ResultCode;
@@ -23,43 +25,53 @@ class CoreTiming;
namespace Kernel {
class KernelCore;
-class Session;
+class KSession;
class KThread;
-class ClientSession final : public KSynchronizationObject {
-public:
- explicit ClientSession(KernelCore& kernel);
- ~ClientSession() override;
+class KClientSession final
+ : public KAutoObjectWithSlabHeapAndContainer<KClientSession, KAutoObjectWithList> {
+ KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject);
- friend class Session;
+public:
+ explicit KClientSession(KernelCore& kernel);
+ virtual ~KClientSession();
- std::string GetTypeName() const override {
- return "ClientSession";
+ void Initialize(KSession* parent_, std::string&& name_) {
+ // Set member variables.
+ parent = parent_;
+ name = std::move(name_);
}
- std::string GetName() const override {
- return name;
+ virtual void Destroy() override;
+ static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
+
+ constexpr KSession* GetParent() const {
+ return parent;
}
+ ResultCode SendSyncRequest(KThread* thread, Core::Memory::Memory& memory,
+ Core::Timing::CoreTiming& core_timing);
+
+ void OnServerClosed();
+
+ // DEPRECATED
+
static constexpr HandleType HANDLE_TYPE = HandleType::ClientSession;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
- ResultCode SendSyncRequest(KThread* thread, Core::Memory::Memory& memory,
- Core::Timing::CoreTiming& core_timing);
-
- bool IsSignaled() const override;
+ std::string GetTypeName() const override {
+ return "ClientSession";
+ }
- void Finalize() override {}
+ std::string GetName() const override {
+ return name;
+ }
private:
- static ResultVal<std::shared_ptr<ClientSession>> Create(KernelCore& kernel,
- std::shared_ptr<Session> parent,
- std::string name = "Unknown");
-
/// The parent session, which links to the server endpoint.
- std::shared_ptr<Session> parent;
+ KSession* parent{};
/// Name of the client session (optional)
std::string name;
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index bb247959c..8cd2c283c 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -11,43 +11,38 @@
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h"
-#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_server_session.h"
+#include "core/hle/kernel/k_session.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/server_session.h"
-#include "core/hle/kernel/session.h"
#include "core/memory.h"
namespace Kernel {
-ServerSession::ServerSession(KernelCore& kernel) : KSynchronizationObject{kernel} {}
+KServerSession::KServerSession(KernelCore& kernel) : KSynchronizationObject{kernel} {}
-ServerSession::~ServerSession() {
+KServerSession::~KServerSession() {
kernel.ReleaseServiceThread(service_thread);
}
-ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kernel,
- std::shared_ptr<Session> parent,
- std::string name) {
- std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)};
-
- session->name = std::move(name);
- session->parent = std::move(parent);
- session->service_thread = kernel.CreateServiceThread(session->name);
-
- return MakeResult(std::move(session));
+void KServerSession::Initialize(KSession* parent_, std::string&& name_) {
+ // Set member variables.
+ parent = parent_;
+ name = std::move(name_);
+ service_thread = kernel.CreateServiceThread(name);
}
-bool ServerSession::IsSignaled() const {
- // Closed sessions should never wait, an error will be returned from svcReplyAndReceive.
- return !parent->Client();
+void KServerSession::Destroy() {
+ parent->OnServerClosed();
+
+ parent->Close();
}
-void ServerSession::ClientDisconnected() {
+void KServerSession::OnClientClosed() {
// 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.
@@ -55,19 +50,31 @@ void ServerSession::ClientDisconnected() {
if (handler) {
// Note that after this returns, this server session's hle_handler is
// invalidated (set to null).
- handler->ClientDisconnected(SharedFrom(this));
+ handler->ClientDisconnected(parent);
+ }
+}
+
+bool KServerSession::IsSignaled() const {
+ ASSERT(kernel.GlobalSchedulerContext().IsLocked());
+
+ // If the client is closed, we're always signaled.
+ if (parent->IsClientClosed()) {
+ return true;
}
+
+ // Otherwise, we're signaled if we have a request and aren't handling one.
+ return false;
}
-void ServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) {
+void KServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) {
domain_request_handlers.push_back(std::move(handler));
}
-std::size_t ServerSession::NumDomainRequestHandlers() const {
+std::size_t KServerSession::NumDomainRequestHandlers() const {
return domain_request_handlers.size();
}
-ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) {
+ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) {
if (!context.HasDomainMessageHeader()) {
return RESULT_SUCCESS;
}
@@ -106,21 +113,21 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
return RESULT_SUCCESS;
}
-ResultCode ServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) {
+ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) {
u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(thread->GetTLSAddress()))};
- auto context = std::make_shared<HLERequestContext>(kernel, memory, SharedFrom(this), thread);
+ auto context = std::make_shared<HLERequestContext>(kernel, memory, this, thread);
context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
if (auto strong_ptr = service_thread.lock()) {
- strong_ptr->QueueSyncRequest(*this, std::move(context));
+ strong_ptr->QueueSyncRequest(*parent, std::move(context));
return RESULT_SUCCESS;
}
return RESULT_SUCCESS;
}
-ResultCode ServerSession::CompleteSyncRequest(HLERequestContext& context) {
+ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) {
ResultCode result = RESULT_SUCCESS;
// If the session has been converted to a domain, handle the domain request
if (IsDomain() && context.HasDomainMessageHeader()) {
@@ -149,8 +156,8 @@ ResultCode ServerSession::CompleteSyncRequest(HLERequestContext& context) {
return result;
}
-ResultCode ServerSession::HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory,
- Core::Timing::CoreTiming& core_timing) {
+ResultCode KServerSession::HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory,
+ Core::Timing::CoreTiming& core_timing) {
return QueueSyncRequest(thread, memory);
}
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/k_server_session.h
index 77ed18c60..ef81c4e30 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -27,55 +27,34 @@ namespace Kernel {
class HLERequestContext;
class KernelCore;
-class Session;
+class KSession;
class SessionRequestHandler;
class KThread;
-/**
- * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS
- * primitive for communication between different processes, and are used to implement service calls
- * to the various system services.
- *
- * To make a service call, the client must write the command header and parameters to the buffer
- * located at offset 0x80 of the TLS (Thread-Local Storage) area, then execute a SendSyncRequest
- * SVC call with its ClientSession handle. The kernel will read the command header, using it to
- * marshall the parameters to the process at the server endpoint of the session.
- * After the server replies to the request, the response is marshalled back to the caller's
- * TLS buffer and control is transferred back to it.
- */
-class ServerSession final : public KSynchronizationObject {
+class KServerSession final : public KSynchronizationObject {
+ KERNEL_AUTOOBJECT_TRAITS(KServerSession, KSynchronizationObject);
+
friend class ServiceThread;
public:
- explicit ServerSession(KernelCore& kernel);
- ~ServerSession() override;
+ explicit KServerSession(KernelCore& kernel);
+ virtual ~KServerSession() override;
- friend class Session;
+ virtual void Destroy() override;
- static ResultVal<std::shared_ptr<ServerSession>> Create(KernelCore& kernel,
- std::shared_ptr<Session> parent,
- std::string name = "Unknown");
+ void Initialize(KSession* parent_, std::string&& name_);
- std::string GetTypeName() const override {
- return "ServerSession";
- }
-
- std::string GetName() const override {
- return name;
+ constexpr KSession* GetParent() {
+ return parent;
}
- static constexpr HandleType HANDLE_TYPE = HandleType::ServerSession;
- HandleType GetHandleType() const override {
- return HANDLE_TYPE;
+ constexpr const KSession* GetParent() const {
+ return parent;
}
- Session* GetParent() {
- return parent.get();
- }
+ virtual bool IsSignaled() const override;
- const Session* GetParent() const {
- return parent.get();
- }
+ void OnClientClosed();
/**
* Sets the HLE handler for the session. This handler will be called to service IPC requests
@@ -98,9 +77,6 @@ public:
ResultCode HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory,
Core::Timing::CoreTiming& core_timing);
- /// Called when a client disconnection occurs.
- void ClientDisconnected();
-
/// Adds a new domain request handler to the collection of request handlers within
/// this ServerSession instance.
void AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler);
@@ -124,9 +100,20 @@ public:
convert_to_domain = true;
}
- bool IsSignaled() const override;
+ // DEPRECATED
- void Finalize() override {}
+ std::string GetTypeName() const override {
+ return "ServerSession";
+ }
+
+ std::string GetName() const override {
+ return name;
+ }
+
+ static constexpr HandleType HANDLE_TYPE = HandleType::ServerSession;
+ HandleType GetHandleType() const override {
+ return HANDLE_TYPE;
+ }
private:
/// Queues a sync request from the emulated application.
@@ -139,9 +126,6 @@ private:
/// object handle.
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;
@@ -156,6 +140,9 @@ private:
/// Thread to dispatch service requests
std::weak_ptr<ServiceThread> service_thread;
+
+ /// KSession that owns this KServerSession
+ KSession* parent{};
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp
new file mode 100644
index 000000000..ca1cf18cd
--- /dev/null
+++ b/src/core/hle/kernel/k_session.cpp
@@ -0,0 +1,67 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/assert.h"
+#include "core/hle/kernel/k_client_session.h"
+#include "core/hle/kernel/k_scoped_resource_reservation.h"
+#include "core/hle/kernel/k_server_session.h"
+#include "core/hle/kernel/k_session.h"
+
+namespace Kernel {
+
+KSession::KSession(KernelCore& kernel)
+ : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {}
+KSession::~KSession() = default;
+
+void KSession::Initialize(std::string&& name_) {
+ // Increment reference count.
+ // Because reference count is one on creation, this will result
+ // in a reference count of two. Thus, when both server and client are closed
+ // this object will be destroyed.
+ Open();
+
+ // Create our sub sessions.
+ KAutoObject::Create(std::addressof(server));
+ KAutoObject::Create(std::addressof(client));
+
+ // Initialize our sub sessions.
+ server.Initialize(this, name_ + ":Server");
+ client.Initialize(this, name_ + ":Client");
+
+ // Set state and name.
+ SetState(State::Normal);
+ name = std::move(name_);
+
+ // Set our owner process.
+ process = kernel.CurrentProcess();
+ process->Open();
+
+ // Mark initialized.
+ initialized = true;
+}
+
+void KSession::Finalize() {}
+
+void KSession::OnServerClosed() {
+ if (GetState() == State::Normal) {
+ SetState(State::ServerClosed);
+ client.OnServerClosed();
+ }
+}
+
+void KSession::OnClientClosed() {
+ if (GetState() == State::Normal) {
+ SetState(State::ClientClosed);
+ server.OnClientClosed();
+ }
+}
+
+void KSession::PostDestroy(uintptr_t arg) {
+ // Release the session count resource the owner process holds.
+ Process* owner = reinterpret_cast<Process*>(arg);
+ owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1);
+ owner->Close();
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h
new file mode 100644
index 000000000..1d24e80cd
--- /dev/null
+++ b/src/core/hle/kernel/k_session.h
@@ -0,0 +1,108 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <atomic>
+#include <string>
+
+#include "core/hle/kernel/k_client_session.h"
+#include "core/hle/kernel/k_server_session.h"
+#include "core/hle/kernel/slab_helpers.h"
+
+namespace Kernel {
+
+class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList> {
+ KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject);
+
+private:
+ enum class State : u8 {
+ Invalid = 0,
+ Normal = 1,
+ ClientClosed = 2,
+ ServerClosed = 3,
+ };
+
+public:
+ explicit KSession(KernelCore& kernel);
+ virtual ~KSession() override;
+
+ void Initialize(std::string&& name_);
+
+ virtual void Finalize() override;
+
+ virtual bool IsInitialized() const override {
+ return initialized;
+ }
+
+ virtual uintptr_t GetPostDestroyArgument() const override {
+ return reinterpret_cast<uintptr_t>(process);
+ }
+
+ static void PostDestroy(uintptr_t arg);
+
+ void OnServerClosed();
+
+ void OnClientClosed();
+
+ bool IsServerClosed() const {
+ return this->GetState() != State::Normal;
+ }
+
+ bool IsClientClosed() const {
+ return this->GetState() != State::Normal;
+ }
+
+ KClientSession& GetClientSession() {
+ return client;
+ }
+
+ KServerSession& GetServerSession() {
+ return server;
+ }
+
+ const KClientSession& GetClientSession() const {
+ return client;
+ }
+
+ const KServerSession& GetServerSession() const {
+ return server;
+ }
+
+ const ClientPort* GetParent() const {
+ return port;
+ }
+
+ // DEPRECATED
+
+ std::string GetName() const override {
+ return name;
+ }
+
+ static constexpr HandleType HANDLE_TYPE = HandleType::Session;
+ HandleType GetHandleType() const override {
+ return HANDLE_TYPE;
+ }
+
+private:
+ void SetState(State state) {
+ atomic_state = static_cast<u8>(state);
+ }
+
+ State GetState() const {
+ return static_cast<State>(atomic_state.load());
+ }
+
+private:
+ KServerSession server;
+ KClientSession client;
+ std::atomic<std::underlying_type<State>::type> atomic_state{
+ static_cast<std::underlying_type<State>::type>(State::Invalid)};
+ ClientPort* port{};
+ std::string name;
+ Process* process{};
+ bool initialized{};
+};
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 850436eb3..ecced1034 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -33,11 +33,13 @@ class ClientPort;
class GlobalSchedulerContext;
class HandleTable;
class KAutoObjectWithListContainer;
+class KClientSession;
class KEvent;
class KLinkedListNode;
class KMemoryManager;
class KResourceLimit;
class KScheduler;
+class KSession;
class KSharedMemory;
class KThread;
class KWritableEvent;
@@ -272,6 +274,10 @@ public:
return slab_heap_container->linked_list_node;
} else if constexpr (std::is_same_v<T, KWritableEvent>) {
return slab_heap_container->writeable_event;
+ } else if constexpr (std::is_same_v<T, KClientSession>) {
+ return slab_heap_container->client_session;
+ } else if constexpr (std::is_same_v<T, KSession>) {
+ return slab_heap_container->session;
}
}
@@ -312,6 +318,8 @@ private:
KSlabHeap<KSharedMemory> shared_memory;
KSlabHeap<KLinkedListNode> linked_list_node;
KSlabHeap<KWritableEvent> writeable_event;
+ KSlabHeap<KClientSession> client_session;
+ KSlabHeap<KSession> session;
};
std::unique_ptr<SlabHeapContainer> slab_heap_container;
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index 5d17346ad..8626b56fd 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -5,10 +5,10 @@
#include <tuple>
#include "common/assert.h"
#include "core/hle/kernel/client_port.h"
+#include "core/hle/kernel/k_server_session.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/server_port.h"
-#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
@@ -16,17 +16,17 @@ namespace Kernel {
ServerPort::ServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {}
ServerPort::~ServerPort() = default;
-ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() {
+ResultVal<KServerSession*> ServerPort::Accept() {
if (pending_sessions.empty()) {
return ResultNotFound;
}
- auto session = std::move(pending_sessions.back());
+ auto* session = pending_sessions.back();
pending_sessions.pop_back();
- return MakeResult(std::move(session));
+ return MakeResult(session);
}
-void ServerPort::AppendPendingSession(std::shared_ptr<ServerSession> pending_session) {
+void ServerPort::AppendPendingSession(KServerSession* pending_session) {
pending_sessions.push_back(std::move(pending_session));
if (pending_sessions.size() == 1) {
NotifyAvailable();
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index 29b4f2509..eebceaa2a 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -17,7 +17,7 @@ namespace Kernel {
class ClientPort;
class KernelCore;
-class ServerSession;
+class KServerSession;
class SessionRequestHandler;
class ServerPort final : public KSynchronizationObject {
@@ -55,7 +55,7 @@ public:
* Accepts a pending incoming connection on this port. If there are no pending sessions, will
* return ERR_NO_PENDING_SESSIONS.
*/
- ResultVal<std::shared_ptr<ServerSession>> Accept();
+ ResultVal<KServerSession*> Accept();
/// Whether or not this server port has an HLE handler available.
bool HasHLEHandler() const {
@@ -77,7 +77,7 @@ public:
/// Appends a ServerSession to the collection of ServerSessions
/// waiting to be accepted by this port.
- void AppendPendingSession(std::shared_ptr<ServerSession> pending_session);
+ void AppendPendingSession(KServerSession* pending_session);
bool IsSignaled() const override;
@@ -85,7 +85,7 @@ public:
private:
/// ServerSessions waiting to be accepted by the port
- std::vector<std::shared_ptr<ServerSession>> pending_sessions;
+ std::vector<KServerSession*> pending_sessions;
/// This session's HLE request handler template (optional)
/// ServerSessions created from this port inherit a reference to this handler.
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp
index ee46f3e21..04be8a502 100644
--- a/src/core/hle/kernel/service_thread.cpp
+++ b/src/core/hle/kernel/service_thread.cpp
@@ -13,8 +13,8 @@
#include "common/scope_exit.h"
#include "common/thread.h"
#include "core/core.h"
+#include "core/hle/kernel/k_session.h"
#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/service_thread.h"
#include "core/hle/lock.h"
#include "video_core/renderer_base.h"
@@ -26,7 +26,7 @@ public:
explicit Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name);
~Impl();
- void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context);
+ void QueueSyncRequest(KSession& session, std::shared_ptr<HLERequestContext>&& context);
private:
std::vector<std::thread> threads;
@@ -69,18 +69,27 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std
});
}
-void ServiceThread::Impl::QueueSyncRequest(ServerSession& session,
+void ServiceThread::Impl::QueueSyncRequest(KSession& session,
std::shared_ptr<HLERequestContext>&& context) {
{
std::unique_lock lock{queue_mutex};
- // ServerSession owns the service thread, so we cannot caption a strong pointer here in the
- // event that the ServerSession is terminated.
- std::weak_ptr<ServerSession> weak_ptr{SharedFrom(&session)};
- requests.emplace([weak_ptr, context{std::move(context)}]() {
- if (auto strong_ptr = weak_ptr.lock()) {
- strong_ptr->CompleteSyncRequest(*context);
+ // Open a reference to the session to ensure it is not closes while the service request
+ // completes asynchronously.
+ session.Open();
+
+ requests.emplace([session_ptr{&session}, context{std::move(context)}]() {
+ // Close the reference.
+ SCOPE_EXIT({ session_ptr->Close(); });
+
+ // If the session has been closed, we are done.
+ if (session_ptr->IsServerClosed()) {
+ return;
}
+
+ // Complete the service request.
+ KScopedAutoObject server_session{&session_ptr->GetServerSession()};
+ server_session->CompleteSyncRequest(*context);
});
}
condition.notify_one();
@@ -102,7 +111,7 @@ ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads, const
ServiceThread::~ServiceThread() = default;
-void ServiceThread::QueueSyncRequest(ServerSession& session,
+void ServiceThread::QueueSyncRequest(KSession& session,
std::shared_ptr<HLERequestContext>&& context) {
impl->QueueSyncRequest(session, std::move(context));
}
diff --git a/src/core/hle/kernel/service_thread.h b/src/core/hle/kernel/service_thread.h
index 025ab8fb5..6a7fd7c56 100644
--- a/src/core/hle/kernel/service_thread.h
+++ b/src/core/hle/kernel/service_thread.h
@@ -11,14 +11,14 @@ namespace Kernel {
class HLERequestContext;
class KernelCore;
-class ServerSession;
+class KSession;
class ServiceThread final {
public:
explicit ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name);
~ServiceThread();
- void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context);
+ void QueueSyncRequest(KSession& session, std::shared_ptr<HLERequestContext>&& context);
private:
class Impl;
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp
deleted file mode 100644
index 8830d4e91..000000000
--- a/src/core/hle/kernel/session.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "common/assert.h"
-#include "core/hle/kernel/client_session.h"
-#include "core/hle/kernel/k_scoped_resource_reservation.h"
-#include "core/hle/kernel/server_session.h"
-#include "core/hle/kernel/session.h"
-
-namespace Kernel {
-
-Session::Session(KernelCore& kernel) : KSynchronizationObject{kernel} {}
-Session::~Session() {
- // Release reserved resource when the Session pair was created.
- kernel.GetSystemResourceLimit()->Release(LimitableResource::Sessions, 1);
-}
-
-Session::SessionPair Session::Create(KernelCore& kernel, std::string name) {
- // Reserve a new session from the resource limit.
- KScopedResourceReservation session_reservation(kernel.GetSystemResourceLimit(),
- LimitableResource::Sessions);
- ASSERT(session_reservation.Succeeded());
- auto session{std::make_shared<Session>(kernel)};
- auto client_session{Kernel::ClientSession::Create(kernel, session, name + "_Client").Unwrap()};
- auto server_session{Kernel::ServerSession::Create(kernel, session, name + "_Server").Unwrap()};
-
- session->name = std::move(name);
- session->client = client_session;
- session->server = server_session;
-
- session_reservation.Commit();
- return std::make_pair(std::move(client_session), std::move(server_session));
-}
-
-bool Session::IsSignaled() const {
- UNIMPLEMENTED();
- return true;
-}
-
-} // namespace Kernel
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
deleted file mode 100644
index fa3c5651a..000000000
--- a/src/core/hle/kernel/session.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2019 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "core/hle/kernel/k_synchronization_object.h"
-
-namespace Kernel {
-
-class ClientSession;
-class ServerSession;
-
-/**
- * Parent structure to link the client and server endpoints of a session with their associated
- * client port.
- */
-class Session final : public KSynchronizationObject {
-public:
- explicit Session(KernelCore& kernel);
- ~Session() override;
-
- using SessionPair = std::pair<std::shared_ptr<ClientSession>, std::shared_ptr<ServerSession>>;
-
- static SessionPair Create(KernelCore& kernel, std::string name = "Unknown");
-
- std::string GetName() const override {
- return name;
- }
-
- static constexpr HandleType HANDLE_TYPE = HandleType::Session;
- HandleType GetHandleType() const override {
- return HANDLE_TYPE;
- }
-
- bool IsSignaled() const override;
-
- void Finalize() override {}
-
- std::shared_ptr<ClientSession> Client() {
- if (auto result{client.lock()}) {
- return result;
- }
- return {};
- }
-
- std::shared_ptr<ServerSession> Server() {
- if (auto result{server.lock()}) {
- return result;
- }
- return {};
- }
-
-private:
- std::string name;
- std::weak_ptr<ClientSession> client;
- std::weak_ptr<ServerSession> server;
-};
-
-} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index b83ee3e69..28c45e8a3 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -22,9 +22,9 @@
#include "core/core_timing_util.h"
#include "core/cpu_manager.h"
#include "core/hle/kernel/client_port.h"
-#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_address_arbiter.h"
+#include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_condition_variable.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_memory_block.h"
@@ -323,12 +323,12 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
auto client_port = it->second;
- std::shared_ptr<ClientSession> client_session;
+ KClientSession* client_session{};
CASCADE_RESULT(client_session, client_port->Connect());
// Return the client session
auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
- CASCADE_RESULT(*out_handle, handle_table.Create(client_session.get()));
+ CASCADE_RESULT(*out_handle, handle_table.Create(client_session));
return RESULT_SUCCESS;
}
@@ -340,15 +340,13 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle,
/// Makes a blocking IPC call to an OS service.
static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
+ LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
+
auto& kernel = system.Kernel();
- const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
- auto session = handle_table.Get<ClientSession>(handle);
- if (!session) {
- LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
- return ResultInvalidHandle;
- }
- LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
+ KScopedAutoObject session =
+ kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
+ R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
auto thread = kernel.CurrentScheduler()->GetCurrentThread();
{