diff options
Diffstat (limited to 'src/core/hle/kernel/k_server_port.cpp')
-rw-r--r-- | src/core/hle/kernel/k_server_port.cpp | 94 |
1 files changed, 67 insertions, 27 deletions
diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp index 2c51d66db..fcc04abaa 100644 --- a/src/core/hle/kernel/k_server_port.cpp +++ b/src/core/hle/kernel/k_server_port.cpp @@ -1,10 +1,12 @@ -// Copyright 2016 Citra Emulator Project +// Copyright 2021 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #include <tuple> #include "common/assert.h" #include "core/hle/kernel/k_client_port.h" +#include "core/hle/kernel/k_port.h" +#include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_server_port.h" #include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/k_thread.h" @@ -16,50 +18,88 @@ namespace Kernel { KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} KServerPort::~KServerPort() = default; -void KServerPort::Initialize(std::string&& name_) { +void KServerPort::Initialize(KPort* parent_, std::string&& name_) { // Set member variables. + parent = parent_; name = std::move(name_); } -ResultVal<KServerSession*> KServerPort::Accept() { - if (pending_sessions.empty()) { - return ResultNotFound; - } - - auto* session = pending_sessions.back(); - pending_sessions.pop_back(); - return MakeResult(session); +bool KServerPort::IsLight() const { + return this->GetParent()->IsLight(); } -void KServerPort::AppendPendingSession(KServerSession* pending_session) { - pending_sessions.push_back(std::move(pending_session)); - if (pending_sessions.size() == 1) { - NotifyAvailable(); +void KServerPort::CleanupSessions() { + // Ensure our preconditions are met. + if (this->IsLight()) { + UNIMPLEMENTED(); + } + + // Cleanup the session list. + while (true) { + // Get the last session in the list + KServerSession* session = nullptr; + { + KScopedSchedulerLock sl{kernel}; + if (!session_list.empty()) { + session = std::addressof(session_list.front()); + session_list.pop_front(); + } + } + + // Close the session. + if (session != nullptr) { + session->Close(); + } else { + break; + } } } -void KServerPort::Destroy() {} +void KServerPort::Destroy() { + // Note with our parent that we're closed. + parent->OnServerClosed(); + + // Perform necessary cleanup of our session lists. + this->CleanupSessions(); + + // Close our reference to our parent. + parent->Close(); +} bool KServerPort::IsSignaled() const { - return !pending_sessions.empty(); + if (this->IsLight()) { + UNIMPLEMENTED(); + return false; + } else { + return !session_list.empty(); + } } -KServerPort::PortPair KServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions, - std::string name) { - KServerPort* server_port = new KServerPort(kernel); - KClientPort* client_port = new KClientPort(kernel); +void KServerPort::EnqueueSession(KServerSession* session) { + ASSERT(!this->IsLight()); + + KScopedSchedulerLock sl{kernel}; - KAutoObject::Create(server_port); - KAutoObject::Create(client_port); + // Add the session to our queue. + session_list.push_back(*session); + if (session_list.size() == 1) { + this->NotifyAvailable(); + } +} - server_port->Initialize(name + "_Server"); - client_port->Initialize(max_sessions, name + "_Client"); +KServerSession* KServerPort::AcceptSession() { + ASSERT(!this->IsLight()); - client_port->server_port = server_port; + KScopedSchedulerLock sl{kernel}; - server_port->name = name + "_Server"; + // Return the first session in the list. + if (session_list.empty()) { + return nullptr; + } - return std::make_pair(server_port, client_port); + KServerSession* session = std::addressof(session_list.front()); + session_list.pop_front(); + return session; } } // namespace Kernel |