// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #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" namespace Kernel { KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} KServerPort::~KServerPort() = default; void KServerPort::Initialize(KernelCore& kernel, KPort* parent) { // Set member variables. m_parent = parent; } bool KServerPort::IsLight(KernelCore& kernel) const { return this->GetParent()->IsLight(); } void KServerPort::CleanupSessions(KernelCore& kernel) { // Ensure our preconditions are met. if (this->IsLight(kernel)) { ASSERT(m_session_list.empty()); } else { ASSERT(m_light_session_list.empty()); } // Cleanup the session list. while (true) { // Get the last session in the list. KServerSession* session = nullptr; { KScopedSchedulerLock sl{kernel}; if (!m_session_list.empty()) { session = std::addressof(m_session_list.front()); m_session_list.pop_front(); } } // Close the session. if (session != nullptr) { session->Close(kernel); } else { break; } } // Cleanup the light session list. while (true) { // Get the last session in the list. KLightServerSession* session = nullptr; { KScopedSchedulerLock sl{kernel}; if (!m_light_session_list.empty()) { session = std::addressof(m_light_session_list.front()); m_light_session_list.pop_front(); } } // Close the session. if (session != nullptr) { session->Close(kernel); } else { break; } } } void KServerPort::Destroy(KernelCore& kernel) { // Note with our parent that we're closed. m_parent->OnServerClosed(kernel); // Perform necessary cleanup of our session lists. this->CleanupSessions(kernel); // Close our reference to our parent. m_parent->Close(kernel); } bool KServerPort::IsSignaled(KernelCore& kernel) const { if (this->IsLight(kernel)) { return !m_light_session_list.empty(); } else { return !m_session_list.empty(); } } void KServerPort::EnqueueSession(KernelCore& kernel, KServerSession* session) { ASSERT(!this->IsLight(kernel)); KScopedSchedulerLock sl{kernel}; // Add the session to our queue. m_session_list.push_back(*session); if (m_session_list.size() == 1) { this->NotifyAvailable(kernel); } } void KServerPort::EnqueueSession(KernelCore& kernel, KLightServerSession* session) { ASSERT(this->IsLight(kernel)); KScopedSchedulerLock sl{kernel}; // Add the session to our queue. m_light_session_list.push_back(*session); if (m_light_session_list.size() == 1) { this->NotifyAvailable(kernel); } } KServerSession* KServerPort::AcceptSession(KernelCore& kernel) { ASSERT(!this->IsLight(kernel)); KScopedSchedulerLock sl{kernel}; // Return the first session in the list. if (m_session_list.empty()) { return nullptr; } KServerSession* session = std::addressof(m_session_list.front()); m_session_list.pop_front(); return session; } KLightServerSession* KServerPort::AcceptLightSession(KernelCore& kernel) { ASSERT(this->IsLight(kernel)); KScopedSchedulerLock sl{kernel}; // Return the first session in the list. if (m_light_session_list.empty()) { return nullptr; } KLightServerSession* session = std::addressof(m_light_session_list.front()); m_light_session_list.pop_front(); return session; } } // namespace Kernel