diff options
| author | lizzie <lizzie@eden-emu.dev> | 2026-06-23 06:31:25 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-06-23 06:31:25 +0200 |
| commit | 3aa0d462598beb2021308eee1d757d74fe33b312 (patch) | |
| tree | ed425c3845ba8fa61184d97b0588cb049b518bd7 /src/core | |
| parent | f8facda35fe7f17143f84bbfbdacc4cc48678946 (diff) | |
[video_core, hle] remove redundant parent references in system structs (#3908)
reworked a bit to remove references of parent objects and instead pass as arguments to methods to prevent useless reloads
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Co-authored-by: maufeat <sahyno1996@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3908
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
Diffstat (limited to 'src/core')
192 files changed, 2824 insertions, 2819 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index e730b808e0..33fece39f6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -108,7 +108,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) - : kernel{system}, fs_controller{system}, hid_core{}, cpu_manager{system}, + : kernel{system}, fs_controller{system}, hid_core{system.Kernel()}, cpu_manager{system}, reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {} u64 program_id; @@ -271,7 +271,7 @@ struct System::Impl { SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) { host1x_core.emplace(system); - gpu_core = VideoCore::CreateGPU(emu_window, system); + VideoCore::CreateGPU(gpu_core, emu_window, system); if (!gpu_core) return SystemResultStatus::ErrorVideoCore; @@ -347,7 +347,7 @@ struct System::Impl { // Register with applet manager // All threads are started, begin main process execution, now that we're in the clear - applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params); + applet_manager.CreateAndInsertByFrontendAppletParameters(std::make_unique<Service::Process>(*std::move(process)), params); if (Settings::values.gamecard_inserted) { if (Settings::values.gamecard_current_game) { @@ -391,10 +391,8 @@ struct System::Impl { is_powered_on = false; exit_locked = false; exit_requested = false; - - if (gpu_core != nullptr) { + if (gpu_core) gpu_core->NotifyShutdown(); - } stop_event.request_stop(); core_timing.SyncPause(false); @@ -478,6 +476,7 @@ struct System::Impl { std::optional<Memory::CheatEngine> cheat_engine; std::optional<Tools::Freezer> memory_freezer; std::optional<Tools::RenderdocAPI> renderdoc_api; + std::optional<Tegra::GPU> gpu_core; std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES> gpu_dirty_memory_managers; std::vector<std::vector<u8>> user_channel; @@ -492,7 +491,6 @@ struct System::Impl { std::unique_ptr<FileSys::ContentProviderUnion> content_provider; /// AppLoader used to load the current executing application std::unique_ptr<Loader::AppLoader> app_loader; - std::unique_ptr<Tegra::GPU> gpu_core; std::stop_source stop_event; mutable std::mutex suspend_guard; @@ -925,7 +923,7 @@ void System::PushGeneralChannelData(std::vector<u8>&& data) { const bool was_empty = impl->general_channel.empty(); impl->general_channel.push_back(std::move(data)); if (was_empty) { - impl->general_channel_event->Signal(); + impl->general_channel_event->Signal(impl->kernel); } } @@ -937,7 +935,7 @@ bool System::TryPopGeneralChannel(std::vector<u8>& out_data) { out_data = std::move(impl->general_channel.back()); impl->general_channel.pop_back(); if (impl->general_channel.empty()) { - impl->general_channel_event->Clear(); + impl->general_channel_event->Clear(impl->kernel); } return true; } diff --git a/src/core/core.h b/src/core/core.h index 012533c1fa..93f7b057f7 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -438,7 +438,6 @@ public: /// Applies any changes to settings to this core instance. void ApplySettings(); -private: struct Impl; std::unique_ptr<Impl> impl; }; diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 10fdcdf8a2..7194fa5022 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -25,9 +25,11 @@ CpuManager::~CpuManager() = default; void CpuManager::Initialize() { num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1; - gpu_barrier = std::make_unique<Common::Barrier>(num_cores + 1); + gpu_barrier.emplace(num_cores + 1); for (std::size_t core = 0; core < num_cores; core++) - core_data[core].host_thread = std::jthread([this, core](std::stop_token token) { RunThread(token, core); }); + core_data[core].host_thread = std::jthread([this, core](std::stop_token token) { + RunThread(token, core); + }); } void CpuManager::Shutdown() { @@ -39,69 +41,61 @@ void CpuManager::Shutdown() { } } -void CpuManager::GuestThreadFunction() { +void CpuManager::GuestThreadFunction(Kernel::KernelCore& kernel) { if (is_multicore) { - MultiCoreRunGuestThread(); + MultiCoreRunGuestThread(kernel); } else { - SingleCoreRunGuestThread(); + SingleCoreRunGuestThread(kernel); } } -void CpuManager::IdleThreadFunction() { +void CpuManager::IdleThreadFunction(Kernel::KernelCore& kernel) { if (is_multicore) { - MultiCoreRunIdleThread(); + MultiCoreRunIdleThread(kernel); } else { - SingleCoreRunIdleThread(); + SingleCoreRunIdleThread(kernel); } } -void CpuManager::ShutdownThreadFunction() { - ShutdownThread(); +void CpuManager::ShutdownThreadFunction(Kernel::KernelCore& kernel) { + ShutdownThread(kernel); } -void CpuManager::HandleInterrupt() { - auto& kernel = system.Kernel(); +void CpuManager::HandleInterrupt(Kernel::KernelCore& kernel) { auto core_index = kernel.CurrentPhysicalCoreIndex(); - - Kernel::KInterruptManager::HandleInterrupt(kernel, static_cast<s32>(core_index)); + Kernel::KInterruptManager::HandleInterrupt(kernel, s32(core_index)); } /////////////////////////////////////////////////////////////////////////////// /// MultiCore /// /////////////////////////////////////////////////////////////////////////////// -void CpuManager::MultiCoreRunGuestThread() { +void CpuManager::MultiCoreRunGuestThread(Kernel::KernelCore& kernel) { // Similar to UserModeThreadStarter in HOS - auto& kernel = system.Kernel(); auto* thread = Kernel::GetCurrentThreadPointer(kernel); - kernel.CurrentScheduler()->OnThreadStart(); + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); while (!physical_core->IsInterrupted()) { - physical_core->RunThread(thread); + physical_core->RunThread(kernel, thread); physical_core = &kernel.CurrentPhysicalCore(); } - - HandleInterrupt(); + HandleInterrupt(kernel); } } -void CpuManager::MultiCoreRunIdleThread() { +void CpuManager::MultiCoreRunIdleThread(Kernel::KernelCore& kernel) { // Not accurate to HOS. Remove this entire method when singlecore is removed. // See notes in KScheduler::ScheduleImpl for more information about why this // is inaccurate. - - auto& kernel = system.Kernel(); - kernel.CurrentScheduler()->OnThreadStart(); - + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { auto& physical_core = kernel.CurrentPhysicalCore(); if (!physical_core.IsInterrupted()) { physical_core.Idle(); } - - HandleInterrupt(); + HandleInterrupt(kernel); } } @@ -109,15 +103,14 @@ void CpuManager::MultiCoreRunIdleThread() { /// SingleCore /// /////////////////////////////////////////////////////////////////////////////// -void CpuManager::SingleCoreRunGuestThread() { - auto& kernel = system.Kernel(); +void CpuManager::SingleCoreRunGuestThread(Kernel::KernelCore& kernel) { auto* thread = Kernel::GetCurrentThreadPointer(kernel); - kernel.CurrentScheduler()->OnThreadStart(); + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); if (!physical_core->IsInterrupted()) { - physical_core->RunThread(thread); + physical_core->RunThread(kernel, thread); physical_core = &kernel.CurrentPhysicalCore(); } @@ -125,26 +118,22 @@ void CpuManager::SingleCoreRunGuestThread() { system.CoreTiming().Advance(); kernel.SetIsPhantomModeForSingleCore(false); - PreemptSingleCore(); - HandleInterrupt(); + PreemptSingleCore(kernel); + HandleInterrupt(kernel); } } -void CpuManager::SingleCoreRunIdleThread() { - auto& kernel = system.Kernel(); - kernel.CurrentScheduler()->OnThreadStart(); - +void CpuManager::SingleCoreRunIdleThread(Kernel::KernelCore& kernel) { + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { - PreemptSingleCore(false); + PreemptSingleCore(kernel, false); system.CoreTiming().AddTicks(1000U); idle_count++; - HandleInterrupt(); + HandleInterrupt(kernel); } } -void CpuManager::PreemptSingleCore(bool from_running_environment) { - auto& kernel = system.Kernel(); - +void CpuManager::PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running_environment) { if (idle_count >= 4 || from_running_environment) { if (!from_running_environment) { system.CoreTiming().Idle(); @@ -156,7 +145,7 @@ void CpuManager::PreemptSingleCore(bool from_running_environment) { } current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); system.CoreTiming().ResetTicks(); - kernel.Scheduler(current_core).PreemptSingleCore(); + kernel.Scheduler(current_core).PreemptSingleCore(kernel); // We've now been scheduled again, and we may have exchanged schedulers. // Reload the scheduler in case it's different. @@ -165,20 +154,16 @@ void CpuManager::PreemptSingleCore(bool from_running_environment) { } } -void CpuManager::GuestActivate() { +void CpuManager::GuestActivate(Kernel::KernelCore& kernel) { // Similar to the HorizonKernelMain callback in HOS - auto& kernel = system.Kernel(); auto* scheduler = kernel.CurrentScheduler(); - - scheduler->Activate(); + scheduler->Activate(kernel); UNREACHABLE(); } -void CpuManager::ShutdownThread() { - auto& kernel = system.Kernel(); +void CpuManager::ShutdownThread(Kernel::KernelCore& kernel) { auto* thread = kernel.GetCurrentEmuThread(); auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0; - Common::Fiber::YieldTo(thread->GetHostContext(), *core_data[core].host_context); UNREACHABLE(); } diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index a249dc5f76..5e97f51bfb 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,6 +17,10 @@ #include "common/thread.h" #include "core/hardware_properties.h" +namespace Kernel { +class KernelCore; +} + namespace Common { class Event; class Fiber; @@ -51,57 +58,55 @@ public: void Initialize(); void Shutdown(); - std::function<void()> GetGuestActivateFunc() { - return [this] { GuestActivate(); }; + std::function<void()> GetGuestActivateFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { GuestActivate(kernel); }; } - std::function<void()> GetGuestThreadFunc() { - return [this] { GuestThreadFunction(); }; + std::function<void()> GetGuestThreadFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { GuestThreadFunction(kernel); }; } - std::function<void()> GetIdleThreadStartFunc() { - return [this] { IdleThreadFunction(); }; + std::function<void()> GetIdleThreadStartFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { IdleThreadFunction(kernel); }; } - std::function<void()> GetShutdownThreadStartFunc() { - return [this] { ShutdownThreadFunction(); }; + std::function<void()> GetShutdownThreadStartFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { ShutdownThreadFunction(kernel); }; } - void PreemptSingleCore(bool from_running_environment = true); + void PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running_environment = true); std::size_t CurrentCore() const { return current_core.load(); } private: - void GuestThreadFunction(); - void IdleThreadFunction(); - void ShutdownThreadFunction(); + void GuestThreadFunction(Kernel::KernelCore& kernel); + void IdleThreadFunction(Kernel::KernelCore& kernel); + void ShutdownThreadFunction(Kernel::KernelCore& kernel); - void MultiCoreRunGuestThread(); - void MultiCoreRunIdleThread(); + void MultiCoreRunGuestThread(Kernel::KernelCore& kernel); + void MultiCoreRunIdleThread(Kernel::KernelCore& kernel); - void SingleCoreRunGuestThread(); - void SingleCoreRunIdleThread(); + void SingleCoreRunGuestThread(Kernel::KernelCore& kernel); + void SingleCoreRunIdleThread(Kernel::KernelCore& kernel); - void GuestActivate(); - void HandleInterrupt(); - void ShutdownThread(); + void GuestActivate(Kernel::KernelCore& kernel); + void HandleInterrupt(Kernel::KernelCore& kernel); + void ShutdownThread(Kernel::KernelCore& kernel); void RunThread(std::stop_token stop_token, std::size_t core); + static constexpr std::size_t max_cycle_runs = 5; + + std::optional<Common::Barrier> gpu_barrier{}; struct CoreData { std::shared_ptr<Common::Fiber> host_context; std::jthread host_thread; }; - - std::unique_ptr<Common::Barrier> gpu_barrier{}; std::array<CoreData, Core::Hardware::NUM_CPU_CORES> core_data{}; - - bool is_async_gpu{}; - bool is_multicore{}; + Core::System& system; std::atomic<std::size_t> current_core{}; std::size_t idle_count{}; std::size_t num_cores{}; - static constexpr std::size_t max_cycle_runs = 5; - - System& system; + bool is_async_gpu{}; + bool is_multicore{}; }; } // namespace Core diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index f90e78f959..d1c767721b 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp @@ -81,7 +81,10 @@ namespace Core { class DebuggerImpl : public DebuggerBackend { public: - explicit DebuggerImpl(Core::System& system_, u16 port) : system{system_} { + explicit DebuggerImpl(Core::System& system_, u16 port) + : system{system_} + , debug_process{system_.Kernel()} + { InitializeServer(port); } @@ -121,7 +124,7 @@ public: } void SetActiveThread(Kernel::KThread* thread) override { - state->active_thread = thread; + state->active_thread = {system.Kernel(), thread}; } Kernel::KThread* GetActiveThread() override { @@ -168,14 +171,7 @@ private: frontend = std::make_unique<GDBStub>(*this, system, debug_process.GetPointerUnsafe()); // Set the new state. This will tear down any existing state. - state = ConnectionState{ - .client_socket{std::move(peer)}, - .signal_pipe{io_context}, - .info{}, - .active_thread{}, - .client_data{}, - .pipe_data{}, - }; + state.emplace(std::move(peer), io_context, system.Kernel()); // Set up the client signals for new data. AsyncReceiveInto(state->signal_pipe, state->pipe_data, [&](auto d) { PipeData(d); }); @@ -204,7 +200,7 @@ private: PauseEmulation(); // Notify the client. - state->active_thread = state->info.thread; + state->active_thread = {system.Kernel(), state->info.thread}; UpdateActiveThread(); if (state->info.type == SignalType::Watchpoint) { @@ -258,7 +254,7 @@ private: auto* gdb = static_cast<GDBStub*>(frontend.get()); MarkResumed([this, threads = std::move(gdb->resume_threads)] { state->active_thread->SetStepState(Kernel::StepState::StepPending); - state->active_thread->Resume(Kernel::SuspendType::Debug); + state->active_thread->Resume(system.Kernel(), Kernel::SuspendType::Debug); ResumeThreads(threads, state->active_thread.GetPointerUnsafe()); }); break; @@ -281,7 +277,7 @@ private: // Put all threads to sleep on next scheduler round. for (auto& thread : ThreadList()) { - thread.RequestSuspend(Kernel::SuspendType::Debug); + thread.RequestSuspend(system.Kernel(), Kernel::SuspendType::Debug); } } @@ -296,7 +292,7 @@ private: } thread.SetStepState(Kernel::StepState::NotStepping); - thread.Resume(Kernel::SuspendType::Debug); + thread.Resume(system.Kernel(), Kernel::SuspendType::Debug); } } @@ -312,7 +308,7 @@ private: } thread->SetStepState(Kernel::StepState::NotStepping); - thread->Resume(Kernel::SuspendType::Debug); + thread->Resume(system.Kernel(), Kernel::SuspendType::Debug); } } @@ -332,7 +328,7 @@ private: return; } } - state->active_thread = std::addressof(threads.front()); + state->active_thread = {system.Kernel(), std::addressof(threads.front())}; } private: @@ -354,13 +350,20 @@ private: std::mutex connection_lock; struct ConnectionState { - boost::asio::ip::tcp::socket client_socket; #ifdef USE_BOOST_v1 - boost::process::v1::async_pipe signal_pipe; + using async_pipe = boost::process::v1::async_pipe; #else - boost::process::async_pipe signal_pipe; + using async_pipe = boost::process::async_pipe; #endif + ConnectionState(boost::asio::ip::tcp::socket&& client_socket_, async_pipe signal_pipe_, Kernel::KernelCore& kernel) + : client_socket{std::move(client_socket_)} + , signal_pipe{signal_pipe_} + , active_thread{kernel, nullptr} + {} + + boost::asio::ip::tcp::socket client_socket; + async_pipe signal_pipe; SignalInfo info; Kernel::KScopedAutoObject<Kernel::KThread> active_thread; std::array<u8, 4096> client_data; diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index 5d61c819f8..44ddf11c39 100644 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp @@ -323,13 +323,13 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) { success = true; break; case BreakpointType::WriteWatch: - success = debug_process->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); + success = debug_process->InsertWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Write); break; case BreakpointType::ReadWatch: - success = debug_process->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); + success = debug_process->InsertWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Read); break; case BreakpointType::AccessWatch: - success = debug_process->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); + success = debug_process->InsertWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::ReadOrWrite); break; case BreakpointType::Hardware: default: @@ -368,13 +368,13 @@ void GDBStub::HandleBreakpointRemove(std::string_view sv) { break; } case BreakpointType::WriteWatch: - success = debug_process->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); + success = debug_process->RemoveWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Write); break; case BreakpointType::ReadWatch: - success = debug_process->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); + success = debug_process->RemoveWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Read); break; case BreakpointType::AccessWatch: - success = debug_process->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); + success = debug_process->RemoveWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::ReadOrWrite); break; case BreakpointType::Hardware: default: diff --git a/src/core/hle/kernel/global_scheduler_context.cpp b/src/core/hle/kernel/global_scheduler_context.cpp index 855a8226ef..6d1cd030e0 100644 --- a/src/core/hle/kernel/global_scheduler_context.cpp +++ b/src/core/hle/kernel/global_scheduler_context.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -17,7 +17,8 @@ namespace Kernel { GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel) - : m_kernel{kernel}, m_scheduler_lock{kernel} {} + : m_scheduler_lock{kernel} +{} GlobalSchedulerContext::~GlobalSchedulerContext() = default; @@ -37,7 +38,7 @@ void GlobalSchedulerContext::RemoveThread(KThread* thread) noexcept { /// and then does some core rebalancing. Preemption priorities can be found /// in the array 'preemption_priorities'. /// @note This operation happens every 10ms. -void GlobalSchedulerContext::PreemptThreads() noexcept { +void GlobalSchedulerContext::PreemptThreads(KernelCore& kernel) noexcept { // The priority levels at which the global scheduler preempts threads every 10 ms. They are // ordered from Core 0 to Core 3. static constexpr std::array<u32, Core::Hardware::NUM_CPU_CORES> per_core{ @@ -46,9 +47,9 @@ void GlobalSchedulerContext::PreemptThreads() noexcept { 59, 63, }; - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); for (u32 core_id = 0; core_id < per_core.size(); core_id++) - KScheduler::RotateScheduledQueue(m_kernel, core_id, per_core[core_id]); + KScheduler::RotateScheduledQueue(kernel, core_id, per_core[core_id]); } /// @brief Returns true if the global scheduler lock is acquired @@ -69,11 +70,11 @@ void GlobalSchedulerContext::UnregisterDummyThreadForWakeup(KThread* thread) noe } } -void GlobalSchedulerContext::WakeupWaitingDummyThreads() noexcept { +void GlobalSchedulerContext::WakeupWaitingDummyThreads(KernelCore& kernel) noexcept { ASSERT(this->IsLocked()); if (m_woken_dummy_threads.size() > 0) { for (auto* thread : m_woken_dummy_threads) - thread->DummyThreadEndWait(); + thread->DummyThreadEndWait(kernel); m_woken_dummy_threads.clear(); } } diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h index 64aee86af8..dd53477d2d 100644 --- a/src/core/hle/kernel/global_scheduler_context.h +++ b/src/core/hle/kernel/global_scheduler_context.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -50,17 +50,16 @@ public: } void AddThread(KThread* thread) noexcept; void RemoveThread(KThread* thread) noexcept; - void PreemptThreads() noexcept; + void PreemptThreads(KernelCore& kernel) noexcept; bool IsLocked() const noexcept; void UnregisterDummyThreadForWakeup(KThread* thread) noexcept; void RegisterDummyThreadForWakeup(KThread* thread) noexcept; - void WakeupWaitingDummyThreads() noexcept; + void WakeupWaitingDummyThreads(KernelCore& kernel) noexcept; private: friend class KScopedSchedulerLock; friend class KScopedSchedulerLockAndSleep; - KernelCore& m_kernel; std::atomic_bool m_scheduler_update_needed{}; KSchedulerPriorityQueue m_priority_queue; LockType m_scheduler_lock; diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index a0e20bbbb4..5dd8afaf96 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -1,3 +1,6 @@ +// 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 @@ -281,7 +284,7 @@ void KPageBufferSlabHeap::Initialize(Core::System& system) { // Reserve memory from the system resource limit. ASSERT( - kernel.GetSystemResourceLimit()->Reserve(LimitableResource::PhysicalMemoryMax, slab_size)); + kernel.GetSystemResourceLimit()->Reserve(kernel, LimitableResource::PhysicalMemoryMax, slab_size)); // Allocate memory for the slab. constexpr auto AllocateOption = KMemoryManager::EncodeOption( diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 48889253dc..02634f8721 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -1,3 +1,6 @@ +// 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 @@ -16,8 +19,9 @@ namespace Kernel { -KAddressArbiter::KAddressArbiter(Core::System& system) - : m_system{system}, m_kernel{system.Kernel()} {} +KAddressArbiter::KAddressArbiter(Core::System& system_) + : system{system_} +{} KAddressArbiter::~KAddressArbiter() = default; namespace { @@ -112,7 +116,7 @@ public: explicit ThreadQueueImplForKAddressArbiter(KernelCore& kernel, KAddressArbiter::ThreadTree* t) : KThreadQueue(kernel), m_tree(t) {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // If the thread is waiting on an address arbiter, remove it from the tree. if (waiting_thread->IsWaitingForAddressArbiter()) { m_tree->erase(m_tree->iterator_to(*waiting_thread)); @@ -120,7 +124,7 @@ public: } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } private: @@ -133,14 +137,14 @@ Result KAddressArbiter::Signal(uint64_t addr, s32 count) { // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(system.Kernel()); auto it = m_tree.nfind_key({addr, -1}); while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->EndWait(ResultSuccess); + target_thread->EndWait(system.Kernel(), ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->ClearAddressArbiter(); @@ -156,11 +160,11 @@ Result KAddressArbiter::SignalAndIncrementIfEqual(uint64_t addr, s32 value, s32 // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(system.Kernel()); // Check the userspace value. s32 user_value{}; - R_UNLESS(UpdateIfEqual(m_kernel, std::addressof(user_value), addr, value, value + 1), + R_UNLESS(UpdateIfEqual(system.Kernel(), std::addressof(user_value), addr, value, value + 1), ResultInvalidCurrentMemory); R_UNLESS(user_value == value, ResultInvalidState); @@ -169,7 +173,7 @@ Result KAddressArbiter::SignalAndIncrementIfEqual(uint64_t addr, s32 value, s32 (it->GetAddressArbiterKey() == addr)) { // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->EndWait(ResultSuccess); + target_thread->EndWait(system.Kernel(), ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->ClearAddressArbiter(); @@ -185,7 +189,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(system.Kernel()); auto it = m_tree.nfind_key({addr, -1}); // Determine the updated value. @@ -220,9 +224,9 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 s32 user_value{}; bool succeeded{}; if (value != new_value) { - succeeded = UpdateIfEqual(m_kernel, std::addressof(user_value), addr, value, new_value); + succeeded = UpdateIfEqual(system.Kernel(), std::addressof(user_value), addr, value, new_value); } else { - succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr); + succeeded = ReadFromUser(system.Kernel(), std::addressof(user_value), addr); } R_UNLESS(succeeded, ResultInvalidCurrentMemory); @@ -232,7 +236,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 (it->GetAddressArbiterKey() == addr)) { // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->EndWait(ResultSuccess); + target_thread->EndWait(system.Kernel(), ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->ClearAddressArbiter(); @@ -246,12 +250,12 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(system.Kernel()); KHardwareTimer* timer{}; - ThreadQueueImplForKAddressArbiter wait_queue(m_kernel, std::addressof(m_tree)); + ThreadQueueImplForKAddressArbiter wait_queue(system.Kernel(), std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp{m_kernel, std::addressof(timer), cur_thread, timeout}; + KScopedSchedulerLockAndSleep slp{system.Kernel(), std::addressof(timer), cur_thread, timeout}; // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -263,9 +267,9 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, s32 user_value{}; bool succeeded{}; if (decrement) { - succeeded = DecrementIfLessThan(m_kernel, std::addressof(user_value), addr, value); + succeeded = DecrementIfLessThan(system.Kernel(), std::addressof(user_value), addr, value); } else { - succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr); + succeeded = ReadFromUser(system.Kernel(), std::addressof(user_value), addr); } if (!succeeded) { @@ -291,7 +295,7 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, // Wait for the thread to finish. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(system.Kernel(), std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } @@ -301,12 +305,12 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(system.Kernel()); KHardwareTimer* timer{}; - ThreadQueueImplForKAddressArbiter wait_queue(m_kernel, std::addressof(m_tree)); + ThreadQueueImplForKAddressArbiter wait_queue(system.Kernel(), std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp{m_kernel, std::addressof(timer), cur_thread, timeout}; + KScopedSchedulerLockAndSleep slp{system.Kernel(), std::addressof(timer), cur_thread, timeout}; // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -316,7 +320,7 @@ Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) { // Read the value from userspace. s32 user_value{}; - if (!ReadFromUser(m_kernel, std::addressof(user_value), addr)) { + if (!ReadFromUser(system.Kernel(), std::addressof(user_value), addr)) { slp.CancelSleep(); R_THROW(ResultInvalidCurrentMemory); } @@ -339,7 +343,7 @@ Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) { // Wait for the thread to finish. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(system.Kernel(), std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } diff --git a/src/core/hle/kernel/k_address_arbiter.h b/src/core/hle/kernel/k_address_arbiter.h index 3b70e1ab28..b3afe19476 100644 --- a/src/core/hle/kernel/k_address_arbiter.h +++ b/src/core/hle/kernel/k_address_arbiter.h @@ -1,3 +1,6 @@ +// 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 @@ -60,8 +63,7 @@ private: private: ThreadTree m_tree; - Core::System& m_system; - KernelCore& m_kernel; + Core::System& system; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_auto_object.cpp b/src/core/hle/kernel/k_auto_object.cpp index a7a46d29bb..14d1c4624d 100644 --- a/src/core/hle/kernel/k_auto_object.cpp +++ b/src/core/hle/kernel/k_auto_object.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -15,8 +15,8 @@ KAutoObject* KAutoObject::Create(KAutoObject* obj) { return obj; } -void KAutoObject::RegisterWithKernel() { - m_kernel.RegisterKernelObject(this); +void KAutoObject::RegisterWithKernel(KernelCore& kernel) { + kernel.RegisterKernelObject(this); } void KAutoObject::UnregisterWithKernel(KernelCore& kernel, KAutoObject* self) { diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index 5e8c0030ce..392b9c9f1d 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -87,21 +87,21 @@ private: KERNEL_AUTOOBJECT_TRAITS_IMPL(KAutoObject, KAutoObject, const); public: - explicit KAutoObject(KernelCore& kernel) : m_kernel(kernel) { + explicit KAutoObject(KernelCore& kernel) { m_class_token = GetStaticTypeObj().GetClassToken(); - RegisterWithKernel(); + RegisterWithKernel(kernel); } virtual ~KAutoObject() = default; static KAutoObject* Create(KAutoObject* ptr); // Destroy is responsible for destroying the auto object's resources when ref_count hits zero. - virtual void Destroy() { + virtual void Destroy(KernelCore& kernel) { UNIMPLEMENTED(); } // Finalize is responsible for cleaning up resource, but does not destroy the object. - virtual void Finalize() {} + virtual void Finalize(KernelCore& kernel) {} virtual KProcess* GetOwner() const { return nullptr; @@ -123,67 +123,50 @@ public: Derived DynamicCast() { static_assert(std::is_pointer_v<Derived>); using DerivedType = std::remove_pointer_t<Derived>; - - if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) { - return static_cast<Derived>(this); - } else { - return nullptr; - } + if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) + return Derived(this); + return nullptr; } template <typename Derived> const Derived DynamicCast() const { static_assert(std::is_pointer_v<Derived>); using DerivedType = std::remove_pointer_t<Derived>; - - if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) { - return static_cast<Derived>(this); - } else { - return nullptr; - } + if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) + return Derived(this); + return nullptr; } - bool Open() { + bool Open(KernelCore& kernel) { // Atomically increment the reference count, only if it's positive. u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire); do { - if (cur_ref_count == 0) { + if (cur_ref_count == 0) return false; - } ASSERT(cur_ref_count < cur_ref_count + 1); - } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count + 1, - std::memory_order_relaxed)); - + } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count + 1, std::memory_order_relaxed)); return true; } - void Close() { + void Close(KernelCore& kernel) { // Atomically decrement the reference count, not allowing it to become negative. u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire); do { - if (cur_ref_count == 0) { + if (cur_ref_count == 0) return; - } ASSERT(cur_ref_count > 0); - } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count - 1, - std::memory_order_acq_rel)); - + } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count - 1, std::memory_order_acq_rel)); // If ref count hits 1, destroy the object. if (cur_ref_count == 1) { - KernelCore& kernel = m_kernel; - this->Destroy(); + this->Destroy(kernel); KAutoObject::UnregisterWithKernel(kernel, this); } } private: - void RegisterWithKernel(); + void RegisterWithKernel(KernelCore& kernel); static void UnregisterWithKernel(KernelCore& kernel, KAutoObject* self); -protected: - KernelCore& m_kernel; - -private: std::atomic<u32> m_ref_count{}; ClassTokenType m_class_token{}; }; @@ -225,17 +208,22 @@ class KScopedAutoObject { public: YUZU_NON_COPYABLE(KScopedAutoObject); - constexpr KScopedAutoObject() = default; + constexpr KScopedAutoObject(KernelCore& kernel_) + : kernel{kernel_} + {} - constexpr KScopedAutoObject(T* o) : m_obj(o) { + constexpr KScopedAutoObject(KernelCore& kernel_, T* o) + : kernel{kernel_} + , m_obj(o) + { if (m_obj != nullptr) { - m_obj->Open(); + m_obj->Open(kernel); } } ~KScopedAutoObject() { if (m_obj != nullptr) { - m_obj->Close(); + m_obj->Close(kernel); } m_obj = nullptr; } @@ -253,7 +241,7 @@ public: if (rhs.m_obj != nullptr) { derived = rhs.m_obj->template DynamicCast<T*>(); if (derived == nullptr) { - rhs.m_obj->Close(); + rhs.m_obj->Close(rhs.kernel); } } @@ -274,8 +262,16 @@ public: return *m_obj; } + constexpr void SetObject(T* o) { + if (m_obj) + m_obj->Close(kernel); + m_obj = o; + if (m_obj) + m_obj->Open(kernel); + } + constexpr void Reset(T* o) { - KScopedAutoObject(o).Swap(*this); + KScopedAutoObject(kernel, o).Swap(*this); } constexpr T* GetPointerUnsafe() { @@ -304,6 +300,7 @@ private: friend class KScopedAutoObject; private: + KernelCore& kernel; T* m_obj{}; private: diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp index 68cea978a0..d13995988c 100644 --- a/src/core/hle/kernel/k_client_port.cpp +++ b/src/core/hle/kernel/k_client_port.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2021 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,7 +18,7 @@ namespace Kernel { KClientPort::KClientPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} KClientPort::~KClientPort() = default; -void KClientPort::Initialize(KPort* parent, s32 max_sessions) { +void KClientPort::Initialize(KernelCore& kernel, KPort* parent, s32 max_sessions) { // Set member variables. m_num_sessions = 0; m_peak_sessions = 0; @@ -23,48 +26,48 @@ void KClientPort::Initialize(KPort* parent, s32 max_sessions) { m_max_sessions = max_sessions; } -void KClientPort::OnSessionFinalized() { - KScopedSchedulerLock sl{m_kernel}; +void KClientPort::OnSessionFinalized(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; if (const auto prev = m_num_sessions--; prev == m_max_sessions) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } -void KClientPort::OnServerClosed() {} +void KClientPort::OnServerClosed(KernelCore& kernel) {} -bool KClientPort::IsLight() const { +bool KClientPort::IsLight(KernelCore& kernel) const { return this->GetParent()->IsLight(); } -bool KClientPort::IsServerClosed() const { - return this->GetParent()->IsServerClosed(); +bool KClientPort::IsServerClosed(KernelCore& kernel) const { + return this->GetParent()->IsServerClosed(kernel); } -void KClientPort::Destroy() { +void KClientPort::Destroy(KernelCore& kernel) { // Note with our parent that we're closed. - m_parent->OnClientClosed(); + m_parent->OnClientClosed(kernel); // Close our reference to our parent. - m_parent->Close(); + m_parent->Close(kernel); } -bool KClientPort::IsSignaled() const { +bool KClientPort::IsSignaled(KernelCore& kernel) const { return m_num_sessions.load() < m_max_sessions; } -Result KClientPort::CreateSession(KClientSession** out) { +Result KClientPort::CreateSession(KernelCore& kernel, KClientSession** out) { // Declare the session we're going to allocate. KSession* session{}; // Reserve a new session from the resource limit. - KScopedResourceReservation session_reservation(GetCurrentProcessPointer(m_kernel), + KScopedResourceReservation session_reservation(kernel, GetCurrentProcessPointer(kernel), LimitableResource::SessionCountMax); R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); // Allocate a session normally. // TODO: Dynamic resource limits - session = KSession::Create(m_kernel); + session = KSession::Create(kernel); // Check that we successfully created a session. R_UNLESS(session != nullptr, ResultOutOfResource); @@ -72,7 +75,7 @@ Result KClientPort::CreateSession(KClientSession** out) { // Update the session counts. { ON_RESULT_FAILURE { - session->Close(); + session->Close(kernel); }; // Atomically increment the number of sessions. @@ -100,38 +103,37 @@ Result KClientPort::CreateSession(KClientSession** out) { } // Initialize the session. - session->Initialize(this, m_parent->GetName()); + session->Initialize(kernel, this, m_parent->GetName()); // Commit the session reservation. session_reservation.Commit(); // Register the session. - KSession::Register(m_kernel, session); + KSession::Register(kernel, session); ON_RESULT_FAILURE { - session->GetClientSession().Close(); - session->GetServerSession().Close(); + session->GetClientSession().Close(kernel); + session->GetServerSession().Close(kernel); }; // Enqueue the session with our parent. - R_TRY(m_parent->EnqueueSession(std::addressof(session->GetServerSession()))); + R_TRY(m_parent->EnqueueSession(kernel, std::addressof(session->GetServerSession()))); // We succeeded, so set the output. *out = std::addressof(session->GetClientSession()); R_SUCCEED(); } -Result KClientPort::CreateLightSession(KLightClientSession** out) { +Result KClientPort::CreateLightSession(KernelCore& kernel, KLightClientSession** out) { // Declare the session we're going to allocate. KLightSession* session{}; // Reserve a new session from the resource limit. - KScopedResourceReservation session_reservation(GetCurrentProcessPointer(m_kernel), - Svc::LimitableResource::SessionCountMax); + KScopedResourceReservation session_reservation(kernel, GetCurrentProcessPointer(kernel), Svc::LimitableResource::SessionCountMax); R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); // Allocate a session normally. // TODO: Dynamic resource limits - session = KLightSession::Create(m_kernel); + session = KLightSession::Create(kernel); // Check that we successfully created a session. R_UNLESS(session != nullptr, ResultOutOfResource); @@ -139,7 +141,7 @@ Result KClientPort::CreateLightSession(KLightClientSession** out) { // Update the session counts. { ON_RESULT_FAILURE { - session->Close(); + session->Close(kernel); }; // Atomically increment the number of sessions. @@ -167,20 +169,20 @@ Result KClientPort::CreateLightSession(KLightClientSession** out) { } // Initialize the session. - session->Initialize(this, m_parent->GetName()); + session->Initialize(kernel, this, m_parent->GetName()); // Commit the session reservation. session_reservation.Commit(); // Register the session. - KLightSession::Register(m_kernel, session); + KLightSession::Register(kernel, session); ON_RESULT_FAILURE { - session->GetClientSession().Close(); - session->GetServerSession().Close(); + session->GetClientSession().Close(kernel); + session->GetServerSession().Close(kernel); }; // Enqueue the session with our parent. - R_TRY(m_parent->EnqueueSession(std::addressof(session->GetServerSession()))); + R_TRY(m_parent->EnqueueSession(kernel, std::addressof(session->GetServerSession()))); // We succeeded, so set the output. *out = std::addressof(session->GetClientSession()); diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index 28b3326081..3e48eeaa00 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,9 +26,9 @@ public: explicit KClientPort(KernelCore& kernel); ~KClientPort() override; - void Initialize(KPort* parent, s32 max_sessions); - void OnSessionFinalized(); - void OnServerClosed(); + void Initialize(KernelCore& kernel, KPort* parent, s32 max_sessions); + void OnSessionFinalized(KernelCore& kernel); + void OnServerClosed(KernelCore& kernel); const KPort* GetParent() const { return m_parent; @@ -44,15 +47,15 @@ public: return m_max_sessions; } - bool IsLight() const; - bool IsServerClosed() const; + bool IsLight(KernelCore& kernel) const; + bool IsServerClosed(KernelCore& kernel) const; // Overridden virtual functions. - void Destroy() override; - bool IsSignaled() const override; + void Destroy(KernelCore& kernel) override; + bool IsSignaled(KernelCore& kernel) const override; - Result CreateSession(KClientSession** out); - Result CreateLightSession(KLightClientSession** out); + Result CreateSession(KernelCore& kernel, KClientSession** out); + Result CreateLightSession(KernelCore& kernel, KLightClientSession** out); private: std::atomic<s32> m_num_sessions{}; diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp index 3e01e3b67f..95cb9896b9 100644 --- a/src/core/hle/kernel/k_client_session.cpp +++ b/src/core/hle/kernel/k_client_session.cpp @@ -1,3 +1,6 @@ +// 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 @@ -13,41 +16,41 @@ namespace Kernel { KClientSession::KClientSession(KernelCore& kernel) : KAutoObject{kernel} {} KClientSession::~KClientSession() = default; -void KClientSession::Destroy() { - m_parent->OnClientClosed(); - m_parent->Close(); +void KClientSession::Destroy(KernelCore& kernel) { + m_parent->OnClientClosed(kernel); + m_parent->Close(kernel); } void KClientSession::OnServerClosed() {} -Result KClientSession::SendSyncRequest(uintptr_t address, size_t size) { +Result KClientSession::SendSyncRequest(KernelCore& kernel, uintptr_t address, size_t size) { // Create a session request. - KSessionRequest* request = KSessionRequest::Create(m_kernel); + KSessionRequest* request = KSessionRequest::Create(kernel); R_UNLESS(request != nullptr, ResultOutOfResource); SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Initialize the request. - request->Initialize(nullptr, address, size); + request->Initialize(kernel, nullptr, address, size); // Send the request. - R_RETURN(m_parent->OnRequest(request)); + R_RETURN(m_parent->OnRequest(kernel, request)); } -Result KClientSession::SendAsyncRequest(KEvent* event, uintptr_t address, size_t size) { +Result KClientSession::SendAsyncRequest(KernelCore& kernel, KEvent* event, uintptr_t address, size_t size) { // Create a session request. - KSessionRequest* request = KSessionRequest::Create(m_kernel); + KSessionRequest* request = KSessionRequest::Create(kernel); R_UNLESS(request != nullptr, ResultOutOfResource); SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Initialize the request. - request->Initialize(event, address, size); + request->Initialize(kernel, event, address, size); // Send the request. - R_RETURN(m_parent->OnRequest(request)); + R_RETURN(m_parent->OnRequest(kernel, request)); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index a39213e17f..876c3fc789 100644 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h @@ -1,3 +1,6 @@ +// 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 @@ -26,14 +29,14 @@ public: m_parent = parent; } - void Destroy() override; + void Destroy(KernelCore& kernel) override; KSession* GetParent() const { return m_parent; } - Result SendSyncRequest(uintptr_t address, size_t size); - Result SendAsyncRequest(KEvent* event, uintptr_t address, size_t size); + Result SendSyncRequest(KernelCore& kernel, uintptr_t address, size_t size); + Result SendAsyncRequest(KernelCore& kernel, KEvent* event, uintptr_t address, size_t size); void OnServerClosed(); diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp index 7454be55c9..aa8edce832 100644 --- a/src/core/hle/kernel/k_code_memory.cpp +++ b/src/core/hle/kernel/k_code_memory.cpp @@ -1,3 +1,6 @@ +// 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 @@ -19,16 +22,15 @@ namespace Kernel { KCodeMemory::KCodeMemory(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock(kernel) {} -Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddress addr, - size_t size) { +Result KCodeMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory, KProcessAddress addr, size_t size) { // Set members. - m_owner = GetCurrentProcessPointer(m_kernel); + m_owner = GetCurrentProcessPointer(kernel); // Get the owner page table. auto& page_table = m_owner->GetPageTable(); // Construct the page group. - m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager()); + m_page_group.emplace(kernel, page_table.GetBlockInfoManager()); // Lock the memory. R_TRY(page_table.LockForCodeMemory(std::addressof(*m_page_group), addr, size)) @@ -39,7 +41,7 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddres } // Set remaining tracking members. - m_owner->Open(); + m_owner->Open(kernel); m_address = addr; m_is_initialized = true; m_is_owner_mapped = false; @@ -49,7 +51,7 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddres R_SUCCEED(); } -void KCodeMemory::Finalize() { +void KCodeMemory::Finalize(KernelCore& kernel) { // Unlock. if (!m_is_mapped && !m_is_owner_mapped) { const size_t size = m_page_group->GetNumPages() * PageSize; @@ -57,14 +59,14 @@ void KCodeMemory::Finalize() { } // Close the page group. - m_page_group->Close(); + m_page_group->Close(kernel); m_page_group->Finalize(); // Close our reference to our owner. - m_owner->Close(); + m_owner->Close(kernel); } -Result KCodeMemory::Map(KProcessAddress address, size_t size) { +Result KCodeMemory::Map(KernelCore& kernel, KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -75,7 +77,7 @@ Result KCodeMemory::Map(KProcessAddress address, size_t size) { R_UNLESS(!m_is_mapped, ResultInvalidState); // Map the memory. - R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup( + R_TRY(GetCurrentProcess(kernel).GetPageTable().MapPageGroup( address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite)); // Mark ourselves as mapped. @@ -84,7 +86,7 @@ Result KCodeMemory::Map(KProcessAddress address, size_t size) { R_SUCCEED(); } -Result KCodeMemory::Unmap(KProcessAddress address, size_t size) { +Result KCodeMemory::Unmap(KernelCore& kernel, KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -92,7 +94,7 @@ Result KCodeMemory::Unmap(KProcessAddress address, size_t size) { KScopedLightLock lk(m_lock); // Unmap the memory. - R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, + R_TRY(GetCurrentProcess(kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::CodeOut)); // Mark ourselves as unmapped. @@ -101,7 +103,7 @@ Result KCodeMemory::Unmap(KProcessAddress address, size_t size) { R_SUCCEED(); } -Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::MemoryPermission perm) { +Result KCodeMemory::MapToOwner(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission perm) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -135,7 +137,7 @@ Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::Memory R_SUCCEED(); } -Result KCodeMemory::UnmapFromOwner(KProcessAddress address, size_t size) { +Result KCodeMemory::UnmapFromOwner(KernelCore& kernel, KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index 26fe6b3dc6..4f3aab6b4f 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -1,3 +1,6 @@ +// 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 @@ -31,18 +34,18 @@ class KCodeMemory final public: explicit KCodeMemory(KernelCore& kernel); - Result Initialize(Core::DeviceMemory& device_memory, KProcessAddress address, size_t size); - void Finalize() override; + Result Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory, KProcessAddress address, size_t size); + void Finalize(KernelCore& kernel) override; - Result Map(KProcessAddress address, size_t size); - Result Unmap(KProcessAddress address, size_t size); - Result MapToOwner(KProcessAddress address, size_t size, Svc::MemoryPermission perm); - Result UnmapFromOwner(KProcessAddress address, size_t size); + Result Map(KernelCore& kernel, KProcessAddress address, size_t size); + Result Unmap(KernelCore& kernel, KProcessAddress address, size_t size); + Result MapToOwner(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission perm); + Result UnmapFromOwner(KernelCore& kernel, KProcessAddress address, size_t size); bool IsInitialized() const override { return m_is_initialized; } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} KProcess* GetOwner() const override { return m_owner; diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 1a7431df07..3cf8b28e17 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -66,14 +66,15 @@ bool UpdateLockAtomic(KernelCore& kernel, u32* out, KProcessAddress address, u32 class ThreadQueueImplForKConditionVariableWaitForAddress final : public KThreadQueue { public: explicit ThreadQueueImplForKConditionVariableWaitForAddress(KernelCore& kernel) - : KThreadQueue(kernel) {} + : KThreadQueue(kernel) + {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); + waiting_thread->GetLockOwner(kernel)->RemoveWaiter(kernel, waiting_thread); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -82,14 +83,15 @@ private: KConditionVariable::ThreadTree* m_tree; public: - explicit ThreadQueueImplForKConditionVariableWaitConditionVariable( - KernelCore& kernel, KConditionVariable::ThreadTree* t) - : KThreadQueue(kernel), m_tree(t) {} + explicit ThreadQueueImplForKConditionVariableWaitConditionVariable(KernelCore& kernel, KConditionVariable::ThreadTree* t) + : KThreadQueue(kernel) + , m_tree(t) + {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { - owner->RemoveWaiter(waiting_thread); + if (KThread* owner = waiting_thread->GetLockOwner(kernel); owner != nullptr) { + owner->RemoveWaiter(kernel, waiting_thread); } // If the thread is waiting on a condvar, remove it from the tree. @@ -99,14 +101,15 @@ public: } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; } // namespace KConditionVariable::KConditionVariable(Core::System& system) - : m_system{system}, m_kernel{system.Kernel()} {} + : m_system{system} +{} KConditionVariable::~KConditionVariable() = default; @@ -119,8 +122,7 @@ Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress a // Remove waiter thread. bool has_waiters{}; - KThread* const next_owner_thread = - owner_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); + KThread* const next_owner_thread = owner_thread->RemoveUserWaiterByKey(kernel, std::addressof(has_waiters), addr); // Determine the next tag. u32 next_value{}; @@ -144,15 +146,14 @@ Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress a // If necessary, signal the next owner thread. if (next_owner_thread != nullptr) { - next_owner_thread->EndWait(result); + next_owner_thread->EndWait(kernel, result); } R_RETURN(result); } } -Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, - u32 value) { +Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, u32 value) { KThread* cur_thread = GetCurrentThreadPointer(kernel); ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel); @@ -173,30 +174,30 @@ Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KPr // Get the lock owner thread. owner_thread = GetCurrentProcess(kernel) - .GetHandleTable() - .GetObjectWithoutPseudoHandle<KThread>(handle) - .ReleasePointerUnsafe(); + .GetHandleTable() + .GetObjectWithoutPseudoHandle<KThread>(kernel, handle) + .ReleasePointerUnsafe(); R_UNLESS(owner_thread != nullptr, ResultInvalidHandle); // Update the lock. cur_thread->SetUserAddressKey(addr, value); - owner_thread->AddWaiter(cur_thread); + owner_thread->AddWaiter(kernel, cur_thread); // Begin waiting. - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(kernel, std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); } // Close our reference to the owner thread, now that the wait is over. - owner_thread->Close(); + owner_thread->Close(kernel); // Get the wait result. R_RETURN(cur_thread->GetWaitResult()); } -void KConditionVariable::SignalImpl(KThread* thread) { +void KConditionVariable::SignalImpl(KernelCore& kernel, KThread* thread) { // Check pre-conditions. - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Update the tag. KProcessAddress address = thread->GetAddressKey(); @@ -211,35 +212,33 @@ void KConditionVariable::SignalImpl(KThread* thread) { // TODO(bunnei): We should call CanAccessAtomic(..) here. can_access = true; if (can_access) { - UpdateLockAtomic(m_kernel, std::addressof(prev_tag), address, own_tag, - Svc::HandleWaitMask); + UpdateLockAtomic(kernel, std::addressof(prev_tag), address, own_tag, Svc::HandleWaitMask); } } if (can_access) { if (prev_tag == Svc::InvalidHandle) { // If nobody held the lock previously, we're all good. - thread->EndWait(ResultSuccess); + thread->EndWait(kernel, ResultSuccess); } else { // Get the previous owner. - KThread* owner_thread = GetCurrentProcess(m_kernel) - .GetHandleTable() - .GetObjectWithoutPseudoHandle<KThread>( - static_cast<Handle>(prev_tag & ~Svc::HandleWaitMask)) - .ReleasePointerUnsafe(); + KThread* owner_thread = GetCurrentProcess(kernel) + .GetHandleTable() + .GetObjectWithoutPseudoHandle<KThread>(kernel, Handle(prev_tag & ~Svc::HandleWaitMask)) + .ReleasePointerUnsafe(); if (owner_thread) { // Add the thread as a waiter on the owner. - owner_thread->AddWaiter(thread); - owner_thread->Close(); + owner_thread->AddWaiter(kernel, thread); + owner_thread->Close(kernel); } else { // The lock was tagged with a thread that doesn't exist. - thread->EndWait(ResultInvalidState); + thread->EndWait(kernel, ResultInvalidState); } } } else { // If the address wasn't accessible, note so. - thread->EndWait(ResultInvalidCurrentMemory); + thread->EndWait(kernel, ResultInvalidCurrentMemory); } } @@ -247,17 +246,16 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(m_system.Kernel()); auto it = m_tree.nfind_key({cv_key, -1}); - while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && - (it->GetConditionVariableKey() == cv_key)) { + while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) { KThread* target_thread = std::addressof(*it); it = m_tree.erase(it); target_thread->ClearConditionVariable(); - this->SignalImpl(target_thread); + this->SignalImpl(m_system.Kernel(), target_thread); ++num_waiters; } @@ -265,20 +263,20 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // If we have no waiters, clear the has waiter flag. if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) { constexpr u32 HasNoWaiterFlag = 0; - WriteToUser(m_kernel, cv_key, HasNoWaiterFlag); + WriteToUser(m_system.Kernel(), cv_key, HasNoWaiterFlag); } } } Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(m_system.Kernel()); KHardwareTimer* timer{}; - ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_kernel, + ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_system.Kernel(), std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp(m_kernel, std::addressof(timer), cur_thread, timeout); + KScopedSchedulerLockAndSleep slp(m_system.Kernel(), std::addressof(timer), cur_thread, timeout); // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -291,7 +289,7 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti // Remove waiter thread. bool has_waiters{}; KThread* next_owner_thread = - cur_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); + cur_thread->RemoveUserWaiterByKey(m_system.Kernel(), std::addressof(has_waiters), addr); // Update for the next owner thread. u32 next_value{}; @@ -303,18 +301,18 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti } // Wake up the next owner. - next_owner_thread->EndWait(ResultSuccess); + next_owner_thread->EndWait(m_system.Kernel(), ResultSuccess); } // Write to the cv key. { constexpr u32 HasWaiterFlag = 1; - WriteToUser(m_kernel, key, HasWaiterFlag); + WriteToUser(m_system.Kernel(), key, HasWaiterFlag); std::atomic_thread_fence(std::memory_order_seq_cst); } // Write the value to userspace. - if (!WriteToUser(m_kernel, addr, next_value)) { + if (!WriteToUser(m_system.Kernel(), addr, next_value)) { slp.CancelSleep(); R_THROW(ResultInvalidCurrentMemory); } @@ -329,7 +327,7 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti // Begin waiting. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(m_system.Kernel(), std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); } diff --git a/src/core/hle/kernel/k_condition_variable.h b/src/core/hle/kernel/k_condition_variable.h index 2620c8e39e..ca80de8837 100644 --- a/src/core/hle/kernel/k_condition_variable.h +++ b/src/core/hle/kernel/k_condition_variable.h @@ -1,3 +1,6 @@ +// 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 @@ -26,19 +29,17 @@ public: // Arbitration. static Result SignalToAddress(KernelCore& kernel, KProcessAddress addr); - static Result WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, - u32 value); + static Result WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, u32 value); // Condition variable. void Signal(u64 cv_key, s32 count); Result Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout); private: - void SignalImpl(KThread* thread); + void SignalImpl(KernelCore& kernel, KThread* thread); private: Core::System& m_system; - KernelCore& m_kernel; ThreadTree m_tree{}; }; diff --git a/src/core/hle/kernel/k_debug.h b/src/core/hle/kernel/k_debug.h index 2290e3bcab..92ff70df74 100644 --- a/src/core/hle/kernel/k_debug.h +++ b/src/core/hle/kernel/k_debug.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,7 +17,7 @@ class KDebug final : public KAutoObjectWithSlabHeapAndContainer<KDebug, KAutoObj public: explicit KDebug(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_device_address_space.cpp b/src/core/hle/kernel/k_device_address_space.cpp index f0703f795b..9c88a279e3 100644 --- a/src/core/hle/kernel/k_device_address_space.cpp +++ b/src/core/hle/kernel/k_device_address_space.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,13 +16,13 @@ KDeviceAddressSpace::KDeviceAddressSpace(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer(kernel), m_lock(kernel), m_is_initialized(false) {} KDeviceAddressSpace::~KDeviceAddressSpace() = default; -void KDeviceAddressSpace::Initialize() { +void KDeviceAddressSpace::Initialize(KernelCore& kernel) { // This just forwards to the device page table manager. // KDevicePageTable::Initialize(); } // Member functions. -Result KDeviceAddressSpace::Initialize(u64 address, u64 size) { +Result KDeviceAddressSpace::Initialize(KernelCore& kernel, u64 address, u64 size) { // Initialize the device page table. // R_TRY(m_table.Initialize(address, size)); @@ -31,7 +34,7 @@ Result KDeviceAddressSpace::Initialize(u64 address, u64 size) { R_SUCCEED(); } -void KDeviceAddressSpace::Finalize() { +void KDeviceAddressSpace::Finalize(KernelCore& kernel) { // Finalize the table. // m_table.Finalize(); } diff --git a/src/core/hle/kernel/k_device_address_space.h b/src/core/hle/kernel/k_device_address_space.h index ff0ec8152b..a7fd62db1b 100644 --- a/src/core/hle/kernel/k_device_address_space.h +++ b/src/core/hle/kernel/k_device_address_space.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -20,13 +23,13 @@ public: explicit KDeviceAddressSpace(KernelCore& kernel); ~KDeviceAddressSpace(); - Result Initialize(u64 address, u64 size); - void Finalize() override; + Result Initialize(KernelCore& kernel, u64 address, u64 size); + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_is_initialized; } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} Result Attach(Svc::DeviceName device_name); Result Detach(Svc::DeviceName device_name); @@ -44,7 +47,7 @@ public: Result Unmap(KProcessPageTable* page_table, KProcessAddress process_address, size_t size, u64 device_address); - static void Initialize(); + static void Initialize(KernelCore& kernel); private: Result Map(KProcessPageTable* page_table, KProcessAddress process_address, size_t size, diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp index d92b491f8b..216d4ae575 100644 --- a/src/core/hle/kernel/k_event.cpp +++ b/src/core/hle/kernel/k_event.cpp @@ -1,3 +1,6 @@ +// 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 @@ -8,56 +11,58 @@ namespace Kernel { KEvent::KEvent(KernelCore& kernel) - : KAutoObjectWithSlabHeapAndContainer{kernel}, m_readable_event{kernel} {} + : KAutoObjectWithSlabHeapAndContainer{kernel} + , m_readable_event{kernel} +{} KEvent::~KEvent() = default; -void KEvent::Initialize(KProcess* owner) { +void KEvent::Initialize(KernelCore& kernel, KProcess* owner) { // Create our readable event. KAutoObject::Create(std::addressof(m_readable_event)); // Initialize our readable event. - m_readable_event.Initialize(this); + m_readable_event.Initialize(kernel, this); // Set our owner process. // HACK: this should never be nullptr, but service threads don't have a // proper parent process yet. if (owner != nullptr) { m_owner = owner; - m_owner->Open(); + m_owner->Open(kernel); } // Mark initialized. m_initialized = true; } -void KEvent::Finalize() { - KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObjectWithList>::Finalize(); +void KEvent::Finalize(KernelCore& kernel) { + KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObjectWithList>::Finalize(kernel); } -Result KEvent::Signal() { - KScopedSchedulerLock sl{m_kernel}; +Result KEvent::Signal(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; R_SUCCEED_IF(m_readable_event_destroyed); - return m_readable_event.Signal(); + return m_readable_event.Signal(kernel); } -Result KEvent::Clear() { - KScopedSchedulerLock sl{m_kernel}; +Result KEvent::Clear(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; R_SUCCEED_IF(m_readable_event_destroyed); - return m_readable_event.Clear(); + return m_readable_event.Clear(kernel); } -void KEvent::PostDestroy(uintptr_t arg) { +void KEvent::PostDestroy(KernelCore& kernel, uintptr_t arg) { // Release the event count resource the owner process holds. KProcess* owner = reinterpret_cast<KProcess*>(arg); if (owner != nullptr) { - owner->GetResourceLimit()->Release(LimitableResource::EventCountMax, 1); - owner->Close(); + owner->GetResourceLimit()->Release(kernel, LimitableResource::EventCountMax, 1); + owner->Close(kernel); } } diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index f522b0a84c..75b03efa69 100644 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h @@ -1,3 +1,6 @@ +// 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 @@ -19,9 +22,9 @@ public: explicit KEvent(KernelCore& kernel); ~KEvent() override; - void Initialize(KProcess* owner); + void Initialize(KernelCore& kernel, KProcess* owner); - void Finalize() override; + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_initialized; @@ -39,10 +42,10 @@ public: return m_readable_event; } - static void PostDestroy(uintptr_t arg); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); - Result Signal(); - Result Clear(); + Result Signal(KernelCore& kernel); + Result Clear(KernelCore& kernel); void OnReadableEventDestroyed() { m_readable_event_destroyed = true; diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index 04ca235344..91d805fa79 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -6,28 +6,27 @@ #include "core/hle/kernel/k_handle_table.h" #include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/kernel.h" namespace Kernel { -void KHandleTable::Finalize() { +void KHandleTable::Finalize(KernelCore& kernel) { // Get the table and clear our record of it. u16 saved_table_size = 0; { - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); std::swap(m_table_size, saved_table_size); } // Close and free all entries. - for (size_t i = 0; i < saved_table_size; i++) { - if (KAutoObject* obj = m_objects[i]; obj != nullptr) { - obj->Close(); - } - } + for (size_t i = 0; i < saved_table_size; i++) + if (KAutoObject* obj = m_objects[i]; obj != nullptr) + obj->Close(kernel); } -bool KHandleTable::Remove(Handle handle) { +bool KHandleTable::Remove(KernelCore& kernel, Handle handle) { // Don't allow removal of a pseudo-handle. if (Svc::IsPseudoHandle(handle)) [[unlikely]] { return false; @@ -42,7 +41,7 @@ bool KHandleTable::Remove(Handle handle) { // Find the object and free the entry. KAutoObject* obj = nullptr; { - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); if (this->IsValidHandle(handle)) [[likely]] { @@ -56,13 +55,13 @@ bool KHandleTable::Remove(Handle handle) { } // Close the object. - m_kernel.UnregisterInUseObject(obj); - obj->Close(); + kernel.UnregisterInUseObject(obj); + obj->Close(kernel); return true; } -Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { - KScopedDisableDispatch dd{m_kernel}; +Result KHandleTable::Add(KernelCore& kernel, Handle* out_handle, KAutoObject* obj) { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Never exceed our capacity. @@ -76,7 +75,7 @@ Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { m_entry_infos[index].linear_id = linear_id; m_objects[index] = obj; - obj->Open(); + obj->Open(kernel); *out_handle = EncodeHandle(static_cast<u16>(index), linear_id); } @@ -84,24 +83,22 @@ Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { R_SUCCEED(); } -KScopedAutoObject<KAutoObject> KHandleTable::GetObjectForIpc(Handle handle, - KThread* cur_thread) const { +KScopedAutoObject<KAutoObject> KHandleTable::GetObjectForIpc(KernelCore& kernel, Handle handle, KThread* cur_thread) const { // Handle pseudo-handles. ASSERT(cur_thread != nullptr); if (handle == Svc::PseudoHandle::CurrentProcess) { auto* const cur_process = cur_thread->GetOwnerProcess(); ASSERT(cur_process != nullptr); - return cur_process; + return {kernel, cur_process}; } if (handle == Svc::PseudoHandle::CurrentThread) { - return cur_thread; + return {kernel, cur_thread}; } - - return GetObjectForIpcWithoutPseudoHandle(handle); + return GetObjectForIpcWithoutPseudoHandle(kernel, handle); } -Result KHandleTable::Reserve(Handle* out_handle) { - KScopedDisableDispatch dd{m_kernel}; +Result KHandleTable::Reserve(KernelCore& kernel, Handle* out_handle) { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Never exceed our capacity. @@ -111,8 +108,8 @@ Result KHandleTable::Reserve(Handle* out_handle) { R_SUCCEED(); } -void KHandleTable::Unreserve(Handle handle) { - KScopedDisableDispatch dd{m_kernel}; +void KHandleTable::Unreserve(KernelCore& kernel, Handle handle) { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Unpack the handle. @@ -130,8 +127,8 @@ void KHandleTable::Unreserve(Handle handle) { } } -void KHandleTable::Register(Handle handle, KAutoObject* obj) { - KScopedDisableDispatch dd{m_kernel}; +void KHandleTable::Register(KernelCore& kernel, Handle handle, KAutoObject* obj) { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Unpack the handle. @@ -149,7 +146,7 @@ void KHandleTable::Register(Handle handle, KAutoObject* obj) { m_entry_infos[index].linear_id = static_cast<u16>(linear_id); m_objects[index] = obj; - obj->Open(); + obj->Open(kernel); } } diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h index 731a5284dc..0704fd56ef 100644 --- a/src/core/hle/kernel/k_handle_table.h +++ b/src/core/hle/kernel/k_handle_table.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -31,14 +31,14 @@ public: static constexpr size_t MaxTableSize = 1024; public: - explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {} + explicit KHandleTable(KernelCore& kernel) {} - Result Initialize(s32 size) { + Result Initialize(KernelCore& kernel, s32 size) { // Check that the table size is valid. R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory); // Lock. - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Initialize all fields. @@ -68,76 +68,72 @@ public: return m_max_count; } - void Finalize(); - bool Remove(Handle handle); + void Finalize(KernelCore& kernel); + bool Remove(KernelCore& kernel, Handle handle); template <typename T = KAutoObject> - KScopedAutoObject<T> GetObjectWithoutPseudoHandle(Handle handle) const { + KScopedAutoObject<T> GetObjectWithoutPseudoHandle(KernelCore& kernel, Handle handle) const { // Lock and look up in table. - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); if constexpr (std::is_same_v<T, KAutoObject>) { - return this->GetObjectImpl(handle); + return {kernel, this->GetObjectImpl(handle)}; } else { if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) [[likely]] { - return obj->DynamicCast<T*>(); + return {kernel, obj->DynamicCast<T*>()}; } else { - return nullptr; + return {kernel, nullptr}; } } } template <typename T = KAutoObject> - KScopedAutoObject<T> GetObject(Handle handle) const { + KScopedAutoObject<T> GetObject(KernelCore& kernel, Handle handle) const { // Handle pseudo-handles. if constexpr (std::derived_from<KProcess, T>) { if (handle == Svc::PseudoHandle::CurrentProcess) { - auto* const cur_process = GetCurrentProcessPointer(m_kernel); + auto* const cur_process = GetCurrentProcessPointer(kernel); ASSERT(cur_process != nullptr); - return cur_process; + return {kernel, cur_process}; } } else if constexpr (std::derived_from<KThread, T>) { if (handle == Svc::PseudoHandle::CurrentThread) { - auto* const cur_thread = GetCurrentThreadPointer(m_kernel); + auto* const cur_thread = GetCurrentThreadPointer(kernel); ASSERT(cur_thread != nullptr); - return cur_thread; + return {kernel, cur_thread}; } } - - return this->template GetObjectWithoutPseudoHandle<T>(handle); + return this->template GetObjectWithoutPseudoHandle<T>(kernel, handle); } - KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(Handle handle) const { + KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(KernelCore& kernel, Handle handle) const { // Lock and look up in table. - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); - - return this->GetObjectImpl(handle); + return {kernel, this->GetObjectImpl(handle)}; } - - KScopedAutoObject<KAutoObject> GetObjectForIpc(Handle handle, KThread* cur_thread) const; - - KScopedAutoObject<KAutoObject> GetObjectByIndex(Handle* out_handle, size_t index) const { - KScopedDisableDispatch dd{m_kernel}; + KScopedAutoObject<KAutoObject> GetObjectForIpc(KernelCore& kernel, Handle handle, KThread* cur_thread) const; + KScopedAutoObject<KAutoObject> GetObjectByIndex(KernelCore& kernel, Handle* out_handle, size_t index) const { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); - return this->GetObjectByIndexImpl(out_handle, index); + return {kernel, this->GetObjectByIndexImpl(out_handle, index)}; } - Result Reserve(Handle* out_handle); - void Unreserve(Handle handle); + Result Reserve(KernelCore& kernel, Handle* out_handle); + void Unreserve(KernelCore& kernel, Handle handle); - Result Add(Handle* out_handle, KAutoObject* obj); - void Register(Handle handle, KAutoObject* obj); + Result Add(KernelCore& kernel, Handle* out_handle, KAutoObject* obj); + void Register(KernelCore& kernel, Handle handle, KAutoObject* obj); template <typename T> - bool GetMultipleObjects(T** out, const Handle* handles, size_t num_handles) const { + bool GetMultipleObjects(KernelCore& kernel, T** out, const Handle* handles, size_t num_handles) const { // Try to convert and open all the handles. size_t num_opened; { // Lock the table. - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); for (num_opened = 0; num_opened < num_handles; num_opened++) { // Get the current handle. @@ -150,14 +146,14 @@ public: } // Cast the current object to the desired type. - T* cur_t = cur_object->DynamicCast<T*>(); - if (cur_t == nullptr) [[unlikely]] { + T* cur_thread = cur_object->DynamicCast<T*>(); + if (cur_thread == nullptr) [[unlikely]] { break; } // Open a reference to the current object. - cur_t->Open(); - out[num_opened] = cur_t; + cur_thread->Open(kernel); + out[num_opened] = cur_thread; } } @@ -168,7 +164,7 @@ public: // If we didn't convert entry object, close the ones we opened. for (size_t i = 0; i < num_opened; i++) { - out[i]->Close(); + out[i]->Close(kernel); } return false; @@ -177,13 +173,9 @@ public: private: s32 AllocateEntry() { ASSERT(m_count < m_table_size); - const auto index = m_free_head_index; - m_free_head_index = m_entry_infos[index].GetNextFreeIndex(); - m_max_count = (std::max)(m_max_count, ++m_count); - return index; } @@ -302,7 +294,6 @@ private: }; private: - KernelCore& m_kernel; std::array<EntryInfo, MaxTableSize> m_entry_infos{}; std::array<KAutoObject*, MaxTableSize> m_objects{}; mutable KSpinLock m_lock; diff --git a/src/core/hle/kernel/k_hardware_timer_base.h b/src/core/hle/kernel/k_hardware_timer_base.h index 6318b35bdd..75a4a54763 100644 --- a/src/core/hle/kernel/k_hardware_timer_base.h +++ b/src/core/hle/kernel/k_hardware_timer_base.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -45,7 +48,7 @@ protected: this->RemoveTaskFromTree(task); // Handle the task. - task->OnTimer(); + task->OnTimer(m_kernel); } } diff --git a/src/core/hle/kernel/k_interrupt_manager.cpp b/src/core/hle/kernel/k_interrupt_manager.cpp index 22d79569a5..9bd182fd9b 100644 --- a/src/core/hle/kernel/k_interrupt_manager.cpp +++ b/src/core/hle/kernel/k_interrupt_manager.cpp @@ -1,3 +1,6 @@ +// 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 @@ -18,19 +21,19 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) { if (auto* process = GetCurrentProcessPointer(kernel); process) { // If the user disable count is set, we may need to pin the current thread. - if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) { + if (current_thread.GetUserDisableCount(kernel) && !process->GetPinnedThread(core_id)) { KScopedSchedulerLock sl{kernel}; // Pin the current thread. - process->PinCurrentThread(); + process->PinCurrentThread(kernel); // Set the interrupt flag for the thread. - GetCurrentThread(kernel).SetInterruptFlag(); + GetCurrentThread(kernel).SetInterruptFlag(kernel); } } // Request interrupt scheduling. - kernel.CurrentScheduler()->RequestScheduleOnInterrupt(); + kernel.CurrentScheduler()->RequestScheduleOnInterrupt(kernel); } void SendInterProcessorInterrupt(KernelCore& kernel, u64 core_mask) { diff --git a/src/core/hle/kernel/k_light_client_session.cpp b/src/core/hle/kernel/k_light_client_session.cpp index 8ce3e1ae49..23f77deffd 100644 --- a/src/core/hle/kernel/k_light_client_session.cpp +++ b/src/core/hle/kernel/k_light_client_session.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,21 +14,21 @@ KLightClientSession::KLightClientSession(KernelCore& kernel) : KAutoObject(kerne KLightClientSession::~KLightClientSession() = default; -void KLightClientSession::Destroy() { - m_parent->OnClientClosed(); +void KLightClientSession::Destroy(KernelCore& kernel) { + m_parent->OnClientClosed(kernel); } -void KLightClientSession::OnServerClosed() {} +void KLightClientSession::OnServerClosed(KernelCore& kernel) {} -Result KLightClientSession::SendSyncRequest(u32* data) { +Result KLightClientSession::SendSyncRequest(KernelCore& kernel, u32* data) { // Get the request thread. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); // Set the light data. cur_thread->SetLightSessionData(data); // Send the request. - R_RETURN(m_parent->OnRequest(cur_thread)); + R_RETURN(m_parent->OnRequest(kernel, cur_thread)); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_client_session.h b/src/core/hle/kernel/k_light_client_session.h index 881a15cbda..c0f48c295e 100644 --- a/src/core/hle/kernel/k_light_client_session.h +++ b/src/core/hle/kernel/k_light_client_session.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,15 +25,15 @@ public: m_parent = parent; } - virtual void Destroy() override; + virtual void Destroy(KernelCore& kernel) override; const KLightSession* GetParent() const { return m_parent; } - Result SendSyncRequest(u32* data); + Result SendSyncRequest(KernelCore& kernel, u32* data); - void OnServerClosed(); + void OnServerClosed(KernelCore& kernel); private: KLightSession* m_parent; diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp index 6d5a815aab..2c873162fb 100644 --- a/src/core/hle/kernel/k_light_condition_variable.cpp +++ b/src/core/hle/kernel/k_light_condition_variable.cpp @@ -1,3 +1,6 @@ +// 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 @@ -13,11 +16,13 @@ namespace { class ThreadQueueImplForKLightConditionVariable final : public KThreadQueue { public: - ThreadQueueImplForKLightConditionVariable(KernelCore& kernel, KThread::WaiterList* wl, - bool term) - : KThreadQueue(kernel), m_wait_list(wl), m_allow_terminating_thread(term) {} + ThreadQueueImplForKLightConditionVariable(KernelCore& kernel, KThread::WaiterList* wl, bool term) + : KThreadQueue(kernel) + , m_wait_list(wl) + , m_allow_terminating_thread(term) + {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Only process waits if we're allowed to. if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) { return; @@ -27,7 +32,7 @@ public: m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } private: @@ -61,7 +66,7 @@ void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_ter // Begin waiting. wait_queue.SetHardwareTimer(timer); - owner->BeginWait(std::addressof(wait_queue)); + owner->BeginWait(m_kernel, std::addressof(wait_queue)); } // Re-acquire the lock. @@ -73,7 +78,7 @@ void KLightConditionVariable::Broadcast() { // Signal all threads. for (auto it = m_wait_list.begin(); it != m_wait_list.end(); it = m_wait_list.erase(it)) { - it->EndWait(ResultSuccess); + it->EndWait(m_kernel, ResultSuccess); } } diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index e87ee8b652..614e056d13 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -1,3 +1,6 @@ +// 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 @@ -15,29 +18,25 @@ class ThreadQueueImplForKLightLock final : public KThreadQueue { public: explicit ThreadQueueImplForKLightLock(KernelCore& kernel) : KThreadQueue(kernel) {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { - owner->RemoveWaiter(waiting_thread); + if (KThread* owner = waiting_thread->GetLockOwner(kernel); owner != nullptr) { + owner->RemoveWaiter(kernel, waiting_thread); } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; } // namespace void KLightLock::Lock() { - const uintptr_t cur_thread = reinterpret_cast<uintptr_t>(GetCurrentThreadPointer(m_kernel)); - + const uintptr_t cur_thread = uintptr_t(GetCurrentThreadPointer(m_kernel)); while (true) { uintptr_t old_tag = m_tag.load(std::memory_order_relaxed); - - while (!m_tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : (old_tag | 1), - std::memory_order_acquire)) { - } - + while (!m_tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : (old_tag | 1), std::memory_order_acquire)) + ; if (old_tag == 0 || this->LockSlowPath(old_tag | 1, cur_thread)) { break; } @@ -69,13 +68,13 @@ bool KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { // Add the current thread as a waiter on the owner. KThread* owner_thread = reinterpret_cast<KThread*>(_owner & ~1ULL); cur_thread->SetKernelAddressKey(reinterpret_cast<uintptr_t>(std::addressof(m_tag))); - owner_thread->AddWaiter(cur_thread); + owner_thread->AddWaiter(m_kernel, cur_thread); // Begin waiting to hold the lock. - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(m_kernel, std::addressof(wait_queue)); if (owner_thread->IsSuspended()) { - owner_thread->ContinueIfHasKernelWaiters(); + owner_thread->ContinueIfHasKernelWaiters(m_kernel); } } @@ -91,26 +90,25 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { // Get the next owner. bool has_waiters; - KThread* next_owner = owner_thread->RemoveKernelWaiterByKey( - std::addressof(has_waiters), reinterpret_cast<uintptr_t>(std::addressof(m_tag))); + KThread* next_owner = owner_thread->RemoveKernelWaiterByKey(m_kernel, + std::addressof(has_waiters), uintptr_t(std::addressof(m_tag))); // Pass the lock to the next owner. uintptr_t next_tag = 0; if (next_owner != nullptr) { - next_tag = - reinterpret_cast<uintptr_t>(next_owner) | static_cast<uintptr_t>(has_waiters); + next_tag = uintptr_t(next_owner) | uintptr_t(has_waiters); - next_owner->EndWait(ResultSuccess); + next_owner->EndWait(m_kernel, ResultSuccess); if (next_owner->IsSuspended()) { - next_owner->ContinueIfHasKernelWaiters(); + next_owner->ContinueIfHasKernelWaiters(m_kernel); } } // We may have unsuspended in the process of acquiring the lock, so we'll re-suspend now if // so. if (owner_thread->IsSuspended()) { - owner_thread->TrySuspend(); + owner_thread->TrySuspend(m_kernel); } // Write the new tag value. @@ -119,8 +117,7 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { } bool KLightLock::IsLockedByCurrentThread() const { - return (m_tag.load() | 1ULL) == - (reinterpret_cast<uintptr_t>(GetCurrentThreadPointer(m_kernel)) | 1ULL); + return (m_tag.load() | 1ULL) == (uintptr_t(GetCurrentThreadPointer(m_kernel)) | 1ULL); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_server_session.cpp b/src/core/hle/kernel/k_light_server_session.cpp index a4d2b11231..6344f418ed 100644 --- a/src/core/hle/kernel/k_light_server_session.cpp +++ b/src/core/hle/kernel/k_light_server_session.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -24,21 +24,20 @@ public: ThreadQueueImplForKLightServerSessionRequest(KernelCore& kernel, KThread::WaiterList* wl) : KThreadQueue(kernel), m_wait_list(wl) {} - virtual void EndWait(KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { // Remove the thread from our wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base end wait handler. - KThreadQueue::EndWait(waiting_thread, wait_result); + KThreadQueue::EndWait(kernel, waiting_thread, wait_result); } - virtual void CancelWait(KThread* waiting_thread, Result wait_result, - bool cancel_timer_task) override { + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread from our wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -48,9 +47,11 @@ private: public: ThreadQueueImplForKLightServerSessionReceive(KernelCore& kernel, KThread** st) - : KThreadQueue(kernel), m_server_thread(st) {} + : KThreadQueue(kernel) + , m_server_thread(st) + {} - virtual void EndWait(KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { // Clear the server thread. *m_server_thread = nullptr; @@ -58,11 +59,10 @@ public: waiting_thread->ClearCancellable(); // Invoke the base end wait handler. - KThreadQueue::EndWait(waiting_thread, wait_result); + KThreadQueue::EndWait(kernel, waiting_thread, wait_result); } - virtual void CancelWait(KThread* waiting_thread, Result wait_result, - bool cancel_timer_task) override { + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Clear the server thread. *m_server_thread = nullptr; @@ -70,7 +70,7 @@ public: waiting_thread->ClearCancellable(); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -79,24 +79,21 @@ public: KLightServerSession::KLightServerSession(KernelCore& kernel) : KAutoObject(kernel) {} KLightServerSession::~KLightServerSession() = default; -void KLightServerSession::Destroy() { - this->CleanupRequests(); - - m_parent->OnServerClosed(); +void KLightServerSession::Destroy(KernelCore& kernel) { + this->CleanupRequests(kernel); + m_parent->OnServerClosed(kernel); } -void KLightServerSession::OnClientClosed() { - this->CleanupRequests(); +void KLightServerSession::OnClientClosed(KernelCore& kernel) { + this->CleanupRequests(kernel); } -Result KLightServerSession::OnRequest(KThread* request_thread) { - ThreadQueueImplForKLightServerSessionRequest wait_queue(m_kernel, - std::addressof(m_request_list)); - +Result KLightServerSession::OnRequest(KernelCore& kernel, KThread* request_thread) { + ThreadQueueImplForKLightServerSessionRequest wait_queue(kernel, std::addressof(m_request_list)); // Send the request. { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Check that the server isn't closed. R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed); @@ -109,11 +106,11 @@ Result KLightServerSession::OnRequest(KThread* request_thread) { // Begin waiting on the request. request_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - request_thread->BeginWait(std::addressof(wait_queue)); + request_thread->BeginWait(kernel, std::addressof(wait_queue)); // If we have a server thread, end its wait. if (m_server_thread != nullptr) { - m_server_thread->EndWait(ResultSuccess); + m_server_thread->EndWait(kernel, ResultSuccess); } } @@ -123,13 +120,13 @@ Result KLightServerSession::OnRequest(KThread* request_thread) { R_RETURN(request_thread->GetWaitResult()); } -Result KLightServerSession::ReplyAndReceive(u32* data) { +Result KLightServerSession::ReplyAndReceive(KernelCore& kernel, u32* data) { // Set the server context. - GetCurrentThread(m_kernel).SetLightSessionData(data); + GetCurrentThread(kernel).SetLightSessionData(data); // Reply, if we need to. if (data[0] & KLightSession::ReplyFlag) { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Check that we're open. R_UNLESS(!m_parent->IsClientClosed(), ResultSessionClosed); @@ -139,17 +136,16 @@ Result KLightServerSession::ReplyAndReceive(u32* data) { R_UNLESS(m_current_request != nullptr, ResultInvalidState); // Check that the server thread id is correct. - R_UNLESS(m_server_thread_id == GetCurrentThread(m_kernel).GetId(), ResultInvalidState); + R_UNLESS(m_server_thread_id == GetCurrentThread(kernel).GetId(), ResultInvalidState); // If we can reply, do so. if (!m_current_request->IsTerminationRequested()) { - std::memcpy(m_current_request->GetLightSessionData(), - GetCurrentThread(m_kernel).GetLightSessionData(), KLightSession::DataSize); - m_current_request->EndWait(ResultSuccess); + std::memcpy(m_current_request->GetLightSessionData(), GetCurrentThread(kernel).GetLightSessionData(), KLightSession::DataSize); + m_current_request->EndWait(kernel, ResultSuccess); } // Close our current request. - m_current_request->Close(); + m_current_request->Close(kernel); // Clear our current request. m_current_request = nullptr; @@ -157,14 +153,13 @@ Result KLightServerSession::ReplyAndReceive(u32* data) { } // Create the wait queue for our receive. - ThreadQueueImplForKLightServerSessionReceive wait_queue(m_kernel, - std::addressof(m_server_thread)); + ThreadQueueImplForKLightServerSessionReceive wait_queue(kernel, std::addressof(m_server_thread)); // Receive. while (true) { // Try to receive a request. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Check that we aren't already receiving. R_UNLESS(m_server_thread == nullptr, ResultInvalidState); @@ -175,20 +170,19 @@ Result KLightServerSession::ReplyAndReceive(u32* data) { R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed); // Check that we're not terminating. - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), - ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // If we have a request available, use it. if (auto head = m_request_list.begin(); head != m_request_list.end()) { // Set our current request. m_current_request = std::addressof(*head); - m_current_request->Open(); + m_current_request->Open(kernel); // Set our server thread id. - m_server_thread_id = GetCurrentThread(m_kernel).GetId(); + m_server_thread_id = GetCurrentThread(kernel).GetId(); // Copy the client request data. - std::memcpy(GetCurrentThread(m_kernel).GetLightSessionData(), + std::memcpy(GetCurrentThread(kernel).GetLightSessionData(), m_current_request->GetLightSessionData(), KLightSession::DataSize); // We successfully received. @@ -198,51 +192,51 @@ Result KLightServerSession::ReplyAndReceive(u32* data) { // We need to wait for a request to come in. // Check if we were cancelled. - if (GetCurrentThread(m_kernel).IsWaitCancelled()) { - GetCurrentThread(m_kernel).ClearWaitCancelled(); + if (GetCurrentThread(kernel).IsWaitCancelled()) { + GetCurrentThread(kernel).ClearWaitCancelled(); R_THROW(ResultCancelled); } // Mark ourselves as cancellable. - GetCurrentThread(m_kernel).SetCancellable(); + GetCurrentThread(kernel).SetCancellable(); // Wait for a request to come in. - m_server_thread = GetCurrentThreadPointer(m_kernel); - GetCurrentThread(m_kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); + m_server_thread = GetCurrentThreadPointer(kernel); + GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); + GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); } // We waited to receive a request; if our wait failed, return the failing result. - R_TRY(GetCurrentThread(m_kernel).GetWaitResult()); + R_TRY(GetCurrentThread(kernel).GetWaitResult()); } } -void KLightServerSession::CleanupRequests() { +void KLightServerSession::CleanupRequests(KernelCore& kernel) { // Cleanup all pending requests. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Handle the current request. if (m_current_request != nullptr) { // Reply to the current request. if (!m_current_request->IsTerminationRequested()) { - m_current_request->EndWait(ResultSessionClosed); + m_current_request->EndWait(kernel, ResultSessionClosed); } // Clear our current request. - m_current_request->Close(); + m_current_request->Close(kernel); m_current_request = nullptr; m_server_thread_id = InvalidThreadId; } // Reply to all other requests. for (auto& thread : m_request_list) { - thread.EndWait(ResultSessionClosed); + thread.EndWait(kernel, ResultSessionClosed); } // Wait up our server thread, if we have one. if (m_server_thread != nullptr) { - m_server_thread->EndWait(ResultSessionClosed); + m_server_thread->EndWait(kernel, ResultSessionClosed); } } } diff --git a/src/core/hle/kernel/k_light_server_session.h b/src/core/hle/kernel/k_light_server_session.h index 67db3f76ca..5849a41c7b 100644 --- a/src/core/hle/kernel/k_light_server_session.h +++ b/src/core/hle/kernel/k_light_server_session.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -34,19 +34,19 @@ public: m_parent = parent; } - virtual void Destroy() override; + virtual void Destroy(KernelCore& kernel) override; constexpr const KLightSession* GetParent() const { return m_parent; } - Result OnRequest(KThread* request_thread); - Result ReplyAndReceive(u32* data); + Result OnRequest(KernelCore& kernel, KThread* request_thread); + Result ReplyAndReceive(KernelCore& kernel, u32* data); - void OnClientClosed(); + void OnClientClosed(KernelCore& kernel); private: - void CleanupRequests(); + void CleanupRequests(KernelCore& kernel); }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_session.cpp b/src/core/hle/kernel/k_light_session.cpp index d8b1e69582..add72d404b 100644 --- a/src/core/hle/kernel/k_light_session.cpp +++ b/src/core/hle/kernel/k_light_session.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,15 +13,18 @@ namespace Kernel { KLightSession::KLightSession(KernelCore& kernel) - : KAutoObjectWithSlabHeapAndContainer(kernel), m_server(kernel), m_client(kernel) {} + : KAutoObjectWithSlabHeapAndContainer(kernel) + , m_server(kernel) + , m_client(kernel) +{} KLightSession::~KLightSession() = default; -void KLightSession::Initialize(KClientPort* client_port, uintptr_t name) { +void KLightSession::Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_t 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. - this->Open(); + this->Open(kernel); // Create our sub sessions. KAutoObject::Create(std::addressof(m_server)); @@ -33,49 +39,47 @@ void KLightSession::Initialize(KClientPort* client_port, uintptr_t name) { m_name = name; // Set our owner process. - m_process = GetCurrentProcessPointer(m_kernel); - m_process->Open(); + m_process = GetCurrentProcessPointer(kernel); + m_process->Open(kernel); // Set our port. m_port = client_port; if (m_port != nullptr) { - m_port->Open(); + m_port->Open(kernel); } // Mark initialized. m_initialized = true; } -void KLightSession::Finalize() { +void KLightSession::Finalize(KernelCore& kernel) { if (m_port != nullptr) { - m_port->OnSessionFinalized(); - m_port->Close(); + m_port->OnSessionFinalized(kernel); + m_port->Close(kernel); } } -void KLightSession::OnServerClosed() { +void KLightSession::OnServerClosed(KernelCore& kernel) { if (m_state == State::Normal) { m_state = State::ServerClosed; - m_client.OnServerClosed(); + m_client.OnServerClosed(kernel); } - - this->Close(); + this->Close(kernel); } -void KLightSession::OnClientClosed() { +void KLightSession::OnClientClosed(KernelCore& kernel) { if (m_state == State::Normal) { m_state = State::ClientClosed; - m_server.OnClientClosed(); + m_server.OnClientClosed(kernel); } - - this->Close(); + this->Close(kernel); } -void KLightSession::PostDestroy(uintptr_t arg) { +void KLightSession::PostDestroy(KernelCore& kernel, uintptr_t arg) { // Release the session count resource the owner process holds. KProcess* owner = reinterpret_cast<KProcess*>(arg); - owner->ReleaseResource(Svc::LimitableResource::SessionCountMax, 1); - owner->Close(); + owner->ReleaseResource(kernel, Svc::LimitableResource::SessionCountMax, 1); + owner->Close(kernel); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_session.h b/src/core/hle/kernel/k_light_session.h index f78d8e6899..5bbb942b35 100644 --- a/src/core/hle/kernel/k_light_session.h +++ b/src/core/hle/kernel/k_light_session.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -43,20 +46,20 @@ public: explicit KLightSession(KernelCore& kernel); ~KLightSession(); - void Initialize(KClientPort* client_port, uintptr_t name); - void Finalize() override; + void Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_t name); + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_initialized; } uintptr_t GetPostDestroyArgument() const override { - return reinterpret_cast<uintptr_t>(m_process); + return uintptr_t(m_process); } - static void PostDestroy(uintptr_t arg); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); - void OnServerClosed(); - void OnClientClosed(); + void OnServerClosed(KernelCore& kernel); + void OnClientClosed(KernelCore& kernel); bool IsServerClosed() const { return m_state != State::Normal; @@ -65,8 +68,8 @@ public: return m_state != State::Normal; } - Result OnRequest(KThread* request_thread) { - R_RETURN(m_server.OnRequest(request_thread)); + Result OnRequest(KernelCore& kernel, KThread* request_thread) { + R_RETURN(m_server.OnRequest(kernel, request_thread)); } KLightClientSession& GetClientSession() { diff --git a/src/core/hle/kernel/k_object_name.cpp b/src/core/hle/kernel/k_object_name.cpp index df3a1c4c56..da0b04b450 100644 --- a/src/core/hle/kernel/k_object_name.cpp +++ b/src/core/hle/kernel/k_object_name.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -8,14 +11,14 @@ namespace Kernel { KObjectNameGlobalData::KObjectNameGlobalData(KernelCore& kernel) : m_object_list_lock{kernel} {} KObjectNameGlobalData::~KObjectNameGlobalData() = default; -void KObjectName::Initialize(KAutoObject* obj, const char* name) { +void KObjectName::Initialize(KernelCore& kernel, KAutoObject* obj, const char* name) { // Set member variables. m_object = obj; std::strncpy(m_name.data(), name, sizeof(m_name) - 1); m_name[sizeof(m_name) - 1] = '\x00'; // Open a reference to the object we hold. - m_object->Open(); + m_object->Open(kernel); } bool KObjectName::MatchesName(const char* name) const { @@ -28,7 +31,7 @@ Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char R_UNLESS(new_name != nullptr, ResultOutOfResource); // Initialize the new name. - new_name->Initialize(obj, name); + new_name->Initialize(kernel, obj, name); // Check if there's an existing name. { @@ -47,7 +50,7 @@ Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char } // The object already exists, which is an error condition. Perform cleanup. - obj->Close(); + obj->Close(kernel); KObjectName::Free(kernel, new_name); R_THROW(ResultInvalidState); } @@ -63,7 +66,7 @@ Result KObjectName::Delete(KernelCore& kernel, KAutoObject* obj, const char* com for (auto& name : gd.GetObjectList()) { if (name.MatchesName(compare_name) && obj == name.GetObject()) { // We found a match, clean up its resources. - obj->Close(); + obj->Close(kernel); gd.GetObjectList().erase(gd.GetObjectList().iterator_to(name)); KObjectName::Free(kernel, std::addressof(name)); R_SUCCEED(); @@ -89,14 +92,12 @@ KScopedAutoObject<KAutoObject> KObjectName::FindImpl(KernelCore& kernel, const c KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()}; // Try to find a matching object in the global list. - for (const auto& name : gd.GetObjectList()) { - if (name.MatchesName(compare_name)) { - return name.GetObject(); - } - } + for (const auto& name : gd.GetObjectList()) + if (name.MatchesName(compare_name)) + return {kernel, name.GetObject()}; // There's no matching entry in the list. - return nullptr; + return {kernel, nullptr}; } } // namespace Kernel diff --git a/src/core/hle/kernel/k_object_name.h b/src/core/hle/kernel/k_object_name.h index a8876fe370..2ae9edcf51 100644 --- a/src/core/hle/kernel/k_object_name.h +++ b/src/core/hle/kernel/k_object_name.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -41,7 +44,7 @@ public: R_UNLESS(derived != nullptr, ResultNotFound); // Check that the object is closed. - R_UNLESS(derived->IsServerClosed(), ResultInvalidState); + R_UNLESS(derived->IsServerClosed(kernel), ResultInvalidState); R_RETURN(Delete(kernel, obj.GetPointerUnsafe(), name)); } @@ -49,13 +52,13 @@ public: template <typename Derived> requires(std::derived_from<Derived, KAutoObject>) static KScopedAutoObject<Derived> Find(KernelCore& kernel, const char* name) { - return Find(kernel, name); + return {kernel, static_cast<Derived*>(Find(kernel, name).GetPointerUnsafe())}; } private: static KScopedAutoObject<KAutoObject> FindImpl(KernelCore& kernel, const char* name); - void Initialize(KAutoObject* obj, const char* name); + void Initialize(KernelCore& kernel, KAutoObject* obj, const char* name); bool MatchesName(const char* name) const; KAutoObject* GetObject() const { diff --git a/src/core/hle/kernel/k_page_group.cpp b/src/core/hle/kernel/k_page_group.cpp index d8c644a336..ed7f219718 100644 --- a/src/core/hle/kernel/k_page_group.cpp +++ b/src/core/hle/kernel/k_page_group.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -21,8 +24,8 @@ void KPageGroup::Finalize() { m_last_block = nullptr; } -void KPageGroup::CloseAndReset() { - auto& mm = m_kernel.MemoryManager(); +void KPageGroup::CloseAndReset(KernelCore& kernel) { + auto& mm = kernel.MemoryManager(); KBlockInfo* cur = m_first_block; while (cur != nullptr) { @@ -76,28 +79,22 @@ Result KPageGroup::AddBlock(KPhysicalAddress addr, size_t num_pages) { R_SUCCEED(); } -void KPageGroup::Open() const { - auto& mm = m_kernel.MemoryManager(); - - for (const auto& it : *this) { +void KPageGroup::Open(KernelCore& kernel) const { + auto& mm = kernel.MemoryManager(); + for (const auto& it : *this) mm.Open(it.GetAddress(), it.GetNumPages()); - } } -void KPageGroup::OpenFirst() const { - auto& mm = m_kernel.MemoryManager(); - - for (const auto& it : *this) { +void KPageGroup::OpenFirst(KernelCore& kernel) const { + auto& mm = kernel.MemoryManager(); + for (const auto& it : *this) mm.OpenFirst(it.GetAddress(), it.GetNumPages()); - } } -void KPageGroup::Close() const { - auto& mm = m_kernel.MemoryManager(); - - for (const auto& it : *this) { +void KPageGroup::Close(KernelCore& kernel) const { + auto& mm = kernel.MemoryManager(); + for (const auto& it : *this) mm.Close(it.GetAddress(), it.GetNumPages()); - } } bool KPageGroup::IsEquivalentTo(const KPageGroup& rhs) const { diff --git a/src/core/hle/kernel/k_page_group.h b/src/core/hle/kernel/k_page_group.h index de9d63a8d2..60a6faa2fd 100644 --- a/src/core/hle/kernel/k_page_group.h +++ b/src/core/hle/kernel/k_page_group.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -139,12 +142,12 @@ public: }; explicit KPageGroup(KernelCore& kernel, KBlockInfoManager* m) - : m_kernel{kernel}, m_manager{m} {} + : m_manager{m} {} ~KPageGroup() { this->Finalize(); } - void CloseAndReset(); + void CloseAndReset(KernelCore& kernel); void Finalize(); Iterator begin() const { @@ -158,9 +161,9 @@ public: } Result AddBlock(KPhysicalAddress addr, size_t num_pages); - void Open() const; - void OpenFirst() const; - void Close() const; + void Open(KernelCore& kernel) const; + void OpenFirst(KernelCore& kernel) const; + void Close(KernelCore& kernel) const; size_t GetNumPages() const; @@ -175,7 +178,6 @@ public: } private: - KernelCore& m_kernel; KBlockInfo* m_first_block{}; KBlockInfo* m_last_block{}; KBlockInfoManager* m_manager{}; @@ -183,21 +185,24 @@ private: class KScopedPageGroup { public: - explicit KScopedPageGroup(const KPageGroup* gp, bool not_first = true) : m_pg(gp) { + explicit KScopedPageGroup(KernelCore& kernel, const KPageGroup* gp, bool not_first = true) + : m_kernel{kernel} + , m_pg{gp} + { if (m_pg) { if (not_first) { - m_pg->Open(); + m_pg->Open(kernel); } else { - m_pg->OpenFirst(); + m_pg->OpenFirst(kernel); } } } - explicit KScopedPageGroup(const KPageGroup& gp, bool not_first = true) - : KScopedPageGroup(std::addressof(gp), not_first) {} + explicit KScopedPageGroup(KernelCore& kernel, const KPageGroup& gp, bool not_first = true) + : KScopedPageGroup(kernel, std::addressof(gp), not_first) {} + ~KScopedPageGroup() { - if (m_pg) { - m_pg->Close(); - } + if (m_pg) + m_pg->Close(m_kernel); } void CancelClose() { @@ -205,6 +210,7 @@ public: } private: + KernelCore& m_kernel; const KPageGroup* m_pg{}; }; diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 3696f9f251..a727355a9f 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -127,22 +127,22 @@ constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission p } // namespace -void KPageTableBase::MemoryRange::Open() { +void KPageTableBase::MemoryRange::Open(KernelCore& kernel) { // If the range contains heap pages, open them. if (this->IsHeap()) { - m_kernel.MemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize); + kernel.MemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize); } } -void KPageTableBase::MemoryRange::Close() { +void KPageTableBase::MemoryRange::Close(KernelCore& kernel) { // If the range contains heap pages, close them. if (this->IsHeap()) { - m_kernel.MemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize); + kernel.MemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize); } } KPageTableBase::KPageTableBase(KernelCore& kernel) - : m_kernel(kernel), m_system(kernel.System()), m_general_lock(kernel), + : m_system(kernel.System()), m_general_lock(kernel), m_map_physical_memory_lock(kernel), m_device_map_lock(kernel) {} KPageTableBase::~KPageTableBase() = default; @@ -177,9 +177,9 @@ Result KPageTableBase::InitializeForKernel(bool is_64_bit, KVirtualAddress start m_mapped_ipc_server_memory = 0; m_memory_block_slab_manager = - m_kernel.GetSystemSystemResource().GetMemoryBlockSlabManagerPointer(); - m_block_info_manager = m_kernel.GetSystemSystemResource().GetBlockInfoManagerPointer(); - m_resource_limit = m_kernel.GetSystemResourceLimit(); + m_system.Kernel().GetSystemSystemResource().GetMemoryBlockSlabManagerPointer(); + m_block_info_manager = m_system.Kernel().GetSystemSystemResource().GetBlockInfoManagerPointer(); + m_resource_limit = m_system.Kernel().GetSystemResourceLimit(); m_allocate_option = KMemoryManager::EncodeOption(KMemoryManager::Pool::System, KMemoryManager::Direction::FromFront); @@ -469,11 +469,11 @@ void KPageTableBase::Finalize() { } // Get physical pages. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); this->MakePageGroup(pg, addr, size / PageSize); // Free the pages. - pg.CloseAndReset(); + pg.CloseAndReset(m_system.Kernel()); }; // Finalize memory blocks. @@ -490,16 +490,16 @@ void KPageTableBase::Finalize() { // Release any insecure mapped memory. if (m_mapped_insecure_memory) { if (auto* const insecure_resource_limit = - KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); + KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel()); insecure_resource_limit != nullptr) { - insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + insecure_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, m_mapped_insecure_memory); } } // Release any ipc server memory. if (m_mapped_ipc_server_memory) { - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, m_mapped_ipc_server_memory); } } @@ -833,7 +833,7 @@ Result KPageTableBase::LockMemoryAndOpen(KPageGroup* out_pg, KPhysicalAddress* o // If we have an output group, open. if (out_pg) { - out_pg->Open(); + out_pg->Open(m_system.Kernel()); } R_SUCCEED(); @@ -1041,7 +1041,7 @@ Result KPageTableBase::MapMemory(KProcessAddress dst_address, KProcessAddress sr const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Create the page group representing the source. R_TRY(this->MakePageGroup(pg, src_address, num_pages)); @@ -1129,7 +1129,7 @@ Result KPageTableBase::UnmapMemory(KProcessAddress dst_address, KProcessAddress const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Create the page group representing the destination. R_TRY(this->MakePageGroup(pg, dst_address, num_pages)); @@ -1217,7 +1217,7 @@ Result KPageTableBase::MapCodeMemory(KProcessAddress dst_address, KProcessAddres const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Create the page group representing the source. R_TRY(this->MakePageGroup(pg, src_address, num_pages)); @@ -1312,7 +1312,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr bool reprotected_pages = false; SCOPE_EXIT { if (reprotected_pages && any_code_pages) { - InvalidateInstructionCache(m_kernel, this, dst_address, size); + InvalidateInstructionCache(m_system.Kernel(), this, dst_address, size); } }; @@ -1322,7 +1322,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Create the page group representing the destination. R_TRY(this->MakePageGroup(pg, dst_address, num_pages)); @@ -1383,19 +1383,19 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) { // Get the insecure memory resource limit and pool. - auto* const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); + auto* const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel()); const auto insecure_pool = static_cast<KMemoryManager::Pool>(KSystemControl::GetInsecureMemoryPool()); // Reserve the insecure memory. // NOTE: ResultOutOfMemory is returned here instead of the usual LimitReached. - KScopedResourceReservation memory_reservation(insecure_resource_limit, + KScopedResourceReservation memory_reservation(m_system.Kernel(), insecure_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, size); R_UNLESS(memory_reservation.Succeeded(), ResultOutOfMemory); // Allocate pages for the insecure memory. - KPageGroup pg(m_kernel, m_block_info_manager); - R_TRY(m_kernel.MemoryManager().AllocateAndOpen( + KPageGroup pg(m_system.Kernel(), m_block_info_manager); + R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen( std::addressof(pg), size / PageSize, KMemoryManager::EncodeOption(insecure_pool, KMemoryManager::Direction::FromFront))); @@ -1403,7 +1403,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) { // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed // automatically. SCOPE_EXIT { - pg.Close(); + pg.Close(m_system.Kernel()); }; // Clear all the newly allocated pages. @@ -1491,9 +1491,9 @@ Result KPageTableBase::UnmapInsecureMemory(KProcessAddress address, size_t size) // Release the insecure memory from the insecure limit. if (auto* const insecure_resource_limit = - KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); + KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel()); insecure_resource_limit != nullptr) { - insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, size); + insecure_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, size); } R_SUCCEED(); @@ -1603,15 +1603,15 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce ASSERT(this->IsLockedByCurrentThread()); // Create a page group to hold the pages we allocate. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Allocate the pages. R_TRY( - m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option)); + m_system.Kernel().MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option)); // Ensure that the page group is closed when we're done working with it. SCOPE_EXIT { - pg.Close(); + pg.Close(m_system.Kernel()); }; // Clear all pages. @@ -1992,7 +1992,7 @@ Result KPageTableBase::SetProcessMemoryPermission(KProcessAddress addr, size_t s KMemoryAttribute::All, KMemoryAttribute::None)); // Make a new page group for the region. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Determine new perm/state. const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm); @@ -2048,9 +2048,9 @@ Result KPageTableBase::SetProcessMemoryPermission(KProcessAddress addr, size_t s // Ensure cache coherency, if we're setting pages as executable. if (is_x) { for (const auto& block : pg) { - StoreDataCache(GetHeapVirtualPointer(m_kernel, block.GetAddress()), block.GetSize()); + StoreDataCache(GetHeapVirtualPointer(m_system.Kernel(), block.GetAddress()), block.GetSize()); } - InvalidateInstructionCache(m_kernel, this, addr, size); + InvalidateInstructionCache(m_system.Kernel(), this, addr, size); } R_SUCCEED(); @@ -2158,7 +2158,7 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) { false, unmap_properties, OperationType::Unmap, false)); // Release the memory from the resource limit. - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, num_pages * PageSize); // Apply the memory block update. @@ -2188,20 +2188,20 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) { } // Reserve memory for the heap extension. - KScopedResourceReservation memory_reservation( + KScopedResourceReservation memory_reservation(m_system.Kernel(), m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, allocation_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate pages for the heap extension. - KPageGroup pg(m_kernel, m_block_info_manager); - R_TRY(m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), allocation_size / PageSize, + KPageGroup pg(m_system.Kernel(), m_block_info_manager); + R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen(std::addressof(pg), allocation_size / PageSize, m_allocate_option)); // Close the opened pages when we're done with them. // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed // automatically. SCOPE_EXIT { - pg.Close(); + pg.Close(m_system.Kernel()); }; // Clear all the newly allocated pages. @@ -2406,7 +2406,7 @@ Result KPageTableBase::MapIoImpl(KProcessAddress* out, PageLinkedList* page_list ASSERT(this->CanContain(region_start, region_size, state)); // Locate the memory region. - const KMemoryRegion* region = KMemoryLayout::Find(m_kernel.MemoryLayout(), phys_addr); + const KMemoryRegion* region = KMemoryLayout::Find(m_system.Kernel().MemoryLayout(), phys_addr); R_UNLESS(region != nullptr, ResultInvalidAddress); ASSERT(region->Contains(GetInteger(phys_addr))); @@ -2640,7 +2640,7 @@ Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemor const size_t region_num_pages = region_size / PageSize; // Locate the memory region. - const KMemoryRegion* region = KMemoryLayout::Find(m_kernel.MemoryLayout(), phys_addr); + const KMemoryRegion* region = KMemoryLayout::Find(m_system.Kernel().MemoryLayout(), phys_addr); R_UNLESS(region != nullptr, ResultInvalidAddress); ASSERT(region->Contains(GetInteger(phys_addr))); @@ -2707,7 +2707,7 @@ Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemor Result KPageTableBase::MapRegion(KMemoryRegionType region_type, KMemoryPermission perm) { // Get the memory region. const KMemoryRegion* region = - m_kernel.MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(region_type); + m_system.Kernel().MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(region_type); R_UNLESS(region != nullptr, ResultOutOfRange); // Check that the region is valid. @@ -3004,7 +3004,7 @@ Result KPageTableBase::MakeAndOpenPageGroup(KPageGroup* out, KProcessAddress add R_TRY(this->MakePageGroup(*out, address, num_pages)); // Open a new reference to the pages in the group. - out->Open(); + out->Open(m_system.Kernel()); R_SUCCEED(); } @@ -3051,7 +3051,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_ // Invalidate the block. if (cur_size > 0) { // NOTE: Nintendo does not check the result of invalidation. - InvalidateDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); + InvalidateDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); } // Advance. @@ -3075,7 +3075,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_ // Invalidate the last block. if (cur_size > 0) { // NOTE: Nintendo does not check the result of invalidation. - InvalidateDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); + InvalidateDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); } R_SUCCEED(); @@ -3083,7 +3083,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_ Result KPageTableBase::InvalidateCurrentProcessDataCache(KProcessAddress address, size_t size) { // Check pre-condition: this is being called on the current process. - ASSERT(this == std::addressof(GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable())); + ASSERT(this == std::addressof(GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable())); // Check that the region is in range. R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); @@ -3144,7 +3144,7 @@ Result KPageTableBase::ReadDebugMemory(KProcessAddress dst_address, KProcessAddr // Copy as much aligned data as we can. if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); - const void* copy_src = GetLinearMappedVirtualPointer(m_kernel, cur_addr); + const void* copy_src = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); FlushDataCache(copy_src, copy_size); R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, copy_size), ResultInvalidPointer); @@ -3155,7 +3155,7 @@ Result KPageTableBase::ReadDebugMemory(KProcessAddress dst_address, KProcessAddr // Copy remaining data. if (cur_size > 0) { - const void* copy_src = GetLinearMappedVirtualPointer(m_kernel, cur_addr); + const void* copy_src = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); FlushDataCache(copy_src, cur_size); R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, cur_size), ResultInvalidPointer); } @@ -3240,11 +3240,11 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd // Copy as much aligned data as we can. if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); - void* copy_dst = GetLinearMappedVirtualPointer(m_kernel, cur_addr); + void* copy_dst = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, copy_size), ResultInvalidCurrentMemory); - StoreDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), copy_size); + StoreDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), copy_size); src_address += copy_size; cur_addr += copy_size; @@ -3253,11 +3253,11 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd // Copy remaining data. if (cur_size > 0) { - void* copy_dst = GetLinearMappedVirtualPointer(m_kernel, cur_addr); + void* copy_dst = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, cur_size), ResultInvalidCurrentMemory); - StoreDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); + StoreDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); } R_SUCCEED(); @@ -3295,7 +3295,7 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd R_TRY(PerformCopy()); // Invalidate the instruction cache, as this svc allows modifying executable pages. - InvalidateInstructionCache(m_kernel, this, dst_address, size); + InvalidateInstructionCache(m_system.Kernel(), this, dst_address, size); R_SUCCEED(); } @@ -3311,7 +3311,7 @@ Result KPageTableBase::ReadIoMemoryImpl(KProcessAddress dst_addr, KPhysicalAddre const size_t map_size = map_end - map_start; // Get the memory reference to write into. - auto& dst_memory = GetCurrentMemory(m_kernel); + auto& dst_memory = GetCurrentMemory(m_system.Kernel()); // We're going to perform an update, so create a helper. KScopedPageTableUpdater updater(this); @@ -3347,7 +3347,7 @@ Result KPageTableBase::WriteIoMemoryImpl(KPhysicalAddress phys_addr, KProcessAdd const size_t map_size = map_end - map_start; // Get the memory reference to read from. - auto& src_memory = GetCurrentMemory(m_kernel); + auto& src_memory = GetCurrentMemory(m_system.Kernel()); // We're going to perform an update, so create a helper. KScopedPageTableUpdater updater(this); @@ -3379,7 +3379,7 @@ Result KPageTableBase::ReadDebugIoMemory(KProcessAddress dst_address, KProcessAd // We need to lock both this table, and the current process's table, so set up some aliases. KPageTableBase& src_page_table = *this; - KPageTableBase& dst_page_table = GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable(); + KPageTableBase& dst_page_table = GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable(); // Acquire the table locks. KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); @@ -3421,7 +3421,7 @@ Result KPageTableBase::WriteDebugIoMemory(KProcessAddress dst_address, KProcessA // We need to lock both this table, and the current process's table, so set up some aliases. KPageTableBase& src_page_table = *this; - KPageTableBase& dst_page_table = GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable(); + KPageTableBase& dst_page_table = GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable(); // Acquire the table locks. KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); @@ -3606,7 +3606,7 @@ Result KPageTableBase::OpenMemoryRangeForMapDeviceAddressSpace(KPageTableBase::M KMemoryAttribute::IpcLocked | KMemoryAttribute::Locked, KMemoryAttribute::None)); // We got the range, so open it. - out->Open(); + out->Open(m_system.Kernel()); R_SUCCEED(); } @@ -3624,7 +3624,7 @@ Result KPageTableBase::OpenMemoryRangeForUnmapDeviceAddressSpace(MemoryRange* ou KMemoryAttribute::DeviceShared | KMemoryAttribute::Locked, KMemoryAttribute::DeviceShared)); // We got the range, so open it. - out->Open(); + out->Open(m_system.Kernel()); R_SUCCEED(); } @@ -3697,7 +3697,7 @@ Result KPageTableBase::OpenMemoryRangeForProcessCacheOperation(MemoryRange* out, KMemoryAttribute::None)); // We got the range, so open it. - out->Open(); + out->Open(m_system.Kernel()); R_SUCCEED(); } @@ -3710,7 +3710,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser( R_UNLESS(this->Contains(src_addr, size), ResultInvalidCurrentMemory); // Get the destination memory reference. - auto& dst_memory = GetCurrentMemory(m_kernel); + auto& dst_memory = GetCurrentMemory(m_system.Kernel()); // Copy the memory. { @@ -3745,7 +3745,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser( if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); R_UNLESS(dst_memory.WriteBlock(dst_addr, - GetLinearMappedVirtualPointer(m_kernel, cur_addr), + GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), copy_size), ResultInvalidCurrentMemory); @@ -3757,7 +3757,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser( // Copy remaining data. if (cur_size > 0) { R_UNLESS(dst_memory.WriteBlock( - dst_addr, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size), + dst_addr, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size), ResultInvalidCurrentMemory); } @@ -3836,7 +3836,7 @@ Result KPageTableBase::CopyMemoryFromLinearToKernel( R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(buffer, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); + std::memcpy(buffer, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); R_SUCCEED(); }; @@ -3884,7 +3884,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear( R_UNLESS(this->Contains(dst_addr, size), ResultInvalidCurrentMemory); // Get the source memory reference. - auto& src_memory = GetCurrentMemory(m_kernel); + auto& src_memory = GetCurrentMemory(m_system.Kernel()); // Copy the memory. { @@ -3919,7 +3919,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear( if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); R_UNLESS(src_memory.ReadBlock(src_addr, - GetLinearMappedVirtualPointer(m_kernel, cur_addr), + GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), copy_size), ResultInvalidCurrentMemory); src_addr += copy_size; @@ -3930,7 +3930,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear( // Copy remaining data. if (cur_size > 0) { R_UNLESS(src_memory.ReadBlock( - src_addr, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size), + src_addr, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size), ResultInvalidCurrentMemory); } @@ -4011,7 +4011,7 @@ Result KPageTableBase::CopyMemoryFromKernelToLinear(KProcessAddress dst_addr, si R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(GetLinearMappedVirtualPointer(m_kernel, cur_addr), buffer, cur_size); + std::memcpy(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), buffer, cur_size); R_SUCCEED(); }; @@ -4162,8 +4162,8 @@ Result KPageTableBase::CopyMemoryFromHeapToHeap( R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(GetHeapVirtualPointer(m_kernel, cur_dst_addr), - GetHeapVirtualPointer(m_kernel, cur_src_addr), cur_copy_size); + std::memcpy(GetHeapVirtualPointer(m_system.Kernel(), cur_dst_addr), + GetHeapVirtualPointer(m_system.Kernel(), cur_src_addr), cur_copy_size); // Update. cur_src_block_addr = src_next_entry.phys_addr; @@ -4296,8 +4296,8 @@ Result KPageTableBase::CopyMemoryFromHeapToHeapWithoutCheckDestination( R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(GetHeapVirtualPointer(m_kernel, cur_dst_addr), - GetHeapVirtualPointer(m_kernel, cur_src_addr), cur_copy_size); + std::memcpy(GetHeapVirtualPointer(m_system.Kernel(), cur_dst_addr), + GetHeapVirtualPointer(m_system.Kernel(), cur_src_addr), cur_copy_size); // Update. cur_src_block_addr = src_next_entry.phys_addr; @@ -4493,7 +4493,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Reserve space for any partial pages we allocate. const size_t unmapped_size = aligned_src_size - mapping_src_size; - KScopedResourceReservation memory_reservation( + KScopedResourceReservation memory_reservation(m_system.Kernel(), m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, unmapped_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); @@ -4506,10 +4506,10 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // free on scope exit. SCOPE_EXIT { if (start_partial_page != 0) { - m_kernel.MemoryManager().Close(start_partial_page, 1); + m_system.Kernel().MemoryManager().Close(start_partial_page, 1); } if (end_partial_page != 0) { - m_kernel.MemoryManager().Close(end_partial_page, 1); + m_system.Kernel().MemoryManager().Close(end_partial_page, 1); } }; @@ -4526,7 +4526,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Allocate the start page as needed. if (aligned_src_start < mapping_src_start) { start_partial_page = - m_kernel.MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); + m_system.Kernel().MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); R_UNLESS(start_partial_page != 0, ResultOutOfMemory); } @@ -4534,7 +4534,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, if (mapping_src_end < aligned_src_end && (aligned_src_start < mapping_src_end || aligned_src_start == mapping_src_start)) { end_partial_page = - m_kernel.MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); + m_system.Kernel().MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); R_UNLESS(end_partial_page != 0, ResultOutOfMemory); } @@ -4560,7 +4560,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Map the start page, if we have one. if (start_partial_page != 0) { // Ensure the page holds correct data. - u8* const start_partial_virt = GetHeapVirtualPointer(m_kernel, start_partial_page); + u8* const start_partial_virt = GetHeapVirtualPointer(m_system.Kernel(), start_partial_page); if (send) { const size_t partial_offset = src_start - aligned_src_start; size_t copy_size, clear_size; @@ -4574,7 +4574,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, std::memset(start_partial_virt, fill_val, partial_offset); std::memcpy(start_partial_virt + partial_offset, - GetHeapVirtualPointer(m_kernel, cur_block_addr) + partial_offset, + GetHeapVirtualPointer(m_system.Kernel(), cur_block_addr) + partial_offset, copy_size); if (clear_size > 0) { std::memset(start_partial_virt + partial_offset + copy_size, fill_val, clear_size); @@ -4663,10 +4663,10 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Map the end page, if we have one. if (end_partial_page != 0) { // Ensure the page holds correct data. - u8* const end_partial_virt = GetHeapVirtualPointer(m_kernel, end_partial_page); + u8* const end_partial_virt = GetHeapVirtualPointer(m_system.Kernel(), end_partial_page); if (send) { const size_t copy_size = src_end - mapping_src_end; - std::memcpy(end_partial_virt, GetHeapVirtualPointer(m_kernel, cur_block_addr), + std::memcpy(end_partial_virt, GetHeapVirtualPointer(m_system.Kernel(), cur_block_addr), copy_size); std::memset(end_partial_virt + copy_size, fill_val, PageSize - copy_size); } else { @@ -4799,7 +4799,7 @@ Result KPageTableBase::CleanupForIpcServer(KProcessAddress address, size_t size, const KProcessAddress mapping_start = Common::AlignUp(GetInteger(address), PageSize); const KProcessAddress mapping_end = Common::AlignDown(GetInteger(address) + size, PageSize); const size_t mapping_size = (mapping_start < mapping_end) ? mapping_end - mapping_start : 0; - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, aligned_size - mapping_size); R_SUCCEED(); @@ -5168,20 +5168,20 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { // Allocate and map the memory. { // Reserve the memory from the process resource limit. - KScopedResourceReservation memory_reservation( + KScopedResourceReservation memory_reservation(m_system.Kernel(), m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, size - mapped_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate pages for the new memory. - KPageGroup pg(m_kernel, m_block_info_manager); - R_TRY(m_kernel.MemoryManager().AllocateForProcess( + KPageGroup pg(m_system.Kernel(), m_block_info_manager); + R_TRY(m_system.Kernel().MemoryManager().AllocateForProcess( std::addressof(pg), (size - mapped_size) / PageSize, m_allocate_option, - GetCurrentProcess(m_kernel).GetId(), m_heap_fill_value)); + GetCurrentProcess(m_system.Kernel()).GetId(), m_heap_fill_value)); // If we fail in the next bit (or retry), we need to cleanup the pages. auto pg_guard = SCOPE_GUARD { - pg.OpenFirst(); - pg.Close(); + pg.OpenFirst(m_system.Kernel()); + pg.Close(m_system.Kernel()); }; // Map the memory. @@ -5304,12 +5304,12 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { } // Release any remaining unmapped memory. - m_kernel.MemoryManager().OpenFirst(pg_phys_addr, pg_pages); - m_kernel.MemoryManager().Close(pg_phys_addr, pg_pages); + m_system.Kernel().MemoryManager().OpenFirst(pg_phys_addr, pg_pages); + m_system.Kernel().MemoryManager().Close(pg_phys_addr, pg_pages); for (++pg_it; pg_it != pg.end(); ++pg_it) { - m_kernel.MemoryManager().OpenFirst(pg_it->GetAddress(), + m_system.Kernel().MemoryManager().OpenFirst(pg_it->GetAddress(), pg_it->GetNumPages()); - m_kernel.MemoryManager().Close(pg_it->GetAddress(), pg_it->GetNumPages()); + m_system.Kernel().MemoryManager().Close(pg_it->GetAddress(), pg_it->GetNumPages()); } }; @@ -5337,11 +5337,11 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { // While we have pages to map, map them. { // Create a page group for the current mapping range. - KPageGroup cur_pg(m_kernel, m_block_info_manager); + KPageGroup cur_pg(m_system.Kernel(), m_block_info_manager); { ON_RESULT_FAILURE_2 { - cur_pg.OpenFirst(); - cur_pg.Close(); + cur_pg.OpenFirst(m_system.Kernel()); + cur_pg.Close(m_system.Kernel()); }; size_t remain_pages = map_pages; @@ -5541,7 +5541,7 @@ Result KPageTableBase::UnmapPhysicalMemory(KProcessAddress address, size_t size) // Release the memory resource. m_mapped_physical_memory_size -= mapped_size; - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, mapped_size); + m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, mapped_size); // Update memory blocks. m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize, @@ -5706,9 +5706,9 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a const bool separate_heap = operation == OperationType::UnmapPhysical; // Ensure that any pages we track are closed on exit. - KPageGroup pages_to_close(m_kernel, this->GetBlockInfoManager()); + KPageGroup pages_to_close(m_system.Kernel(), this->GetBlockInfoManager()); SCOPE_EXIT { - pages_to_close.CloseAndReset(); + pages_to_close.CloseAndReset(m_system.Kernel()); }; // Make a page group representing the region to unmap. @@ -5727,7 +5727,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a // Open references to pages, if we should. if (this->IsHeapPhysicalAddress(phys_addr)) { - m_kernel.MemoryManager().Open(phys_addr, num_pages); + m_system.Kernel().MemoryManager().Open(phys_addr, num_pages); } R_SUCCEED(); @@ -5767,7 +5767,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a const bool separate_heap = operation == OperationType::MapFirstGroupPhysical; // We want to maintain a new reference to every page in the group. - KScopedPageGroup spg(page_group, operation == OperationType::MapGroup); + KScopedPageGroup spg(m_system.Kernel(), page_group, operation == OperationType::MapGroup); for (const auto& node : page_group) { const size_t size{node.GetNumPages() * PageSize}; diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index 726fad989f..160e722985 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h @@ -61,14 +61,12 @@ public: class MemoryRange { private: - KernelCore& m_kernel; - KPhysicalAddress m_address; - size_t m_size; - bool m_heap; + KPhysicalAddress m_address = 0; + size_t m_size = 0; + bool m_heap = false; public: - explicit MemoryRange(KernelCore& kernel) - : m_kernel(kernel), m_address(0), m_size(0), m_heap(false) {} + explicit MemoryRange() : m_address(0), m_size(0), m_heap(false) {} void Set(KPhysicalAddress address, size_t size, bool heap) { m_address = address; @@ -86,8 +84,8 @@ public: return m_heap; } - void Open(); - void Close(); + void Open(KernelCore& kernel); + void Close(KernelCore& kernel); }; protected: @@ -189,7 +187,6 @@ private: }; private: - KernelCore& m_kernel; Core::System& m_system; KProcessAddress m_address_space_start{}; KProcessAddress m_address_space_end{}; @@ -329,35 +326,35 @@ protected: bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr) { ASSERT(this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsLinearMappedPhysicalAddress( + return m_system.Kernel().MemoryLayout().IsLinearMappedPhysicalAddress( m_cached_physical_linear_region, phys_addr); } bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr, size_t size) { ASSERT(this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsLinearMappedPhysicalAddress( + return m_system.Kernel().MemoryLayout().IsLinearMappedPhysicalAddress( m_cached_physical_linear_region, phys_addr, size); } bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr) { ASSERT(this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, + return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr); } bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr, size_t size) { ASSERT(this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, + return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr, size); } bool IsHeapPhysicalAddressForFinalize(KPhysicalAddress phys_addr) { ASSERT(!this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, + return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr); } @@ -744,15 +741,15 @@ public: // Member heap u8* GetHeapVirtualPointer(KPhysicalAddress addr) { - return GetHeapVirtualPointer(m_kernel, addr); + return GetHeapVirtualPointer(m_system.Kernel(), addr); } KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress addr) { - return GetHeapPhysicalAddress(m_kernel, addr); + return GetHeapPhysicalAddress(m_system.Kernel(), addr); } KVirtualAddress GetHeapVirtualAddress(KPhysicalAddress addr) { - return GetHeapVirtualAddress(m_kernel, addr); + return GetHeapVirtualAddress(m_system.Kernel(), addr); } // TODO: GetPageTableVirtualAddress diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp index e5f5d8028c..f64d983e0c 100644 --- a/src/core/hle/kernel/k_port.cpp +++ b/src/core/hle/kernel/k_port.cpp @@ -1,8 +1,12 @@ +// 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 "core/hle/kernel/k_port.h" #include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/svc_results.h" namespace Kernel { @@ -12,15 +16,15 @@ KPort::KPort(KernelCore& kernel) KPort::~KPort() = default; -void KPort::Initialize(s32 max_sessions, bool is_light, uintptr_t name) { +void KPort::Initialize(KernelCore& kernel, s32 max_sessions, bool is_light, uintptr_t name) { // Open a new reference count to the initialized port. - this->Open(); + this->Open(kernel); // Create and initialize our server/client pair. KAutoObject::Create(std::addressof(m_server)); KAutoObject::Create(std::addressof(m_client)); - m_server.Initialize(this); - m_client.Initialize(this, max_sessions); + m_server.Initialize(kernel, this); + m_client.Initialize(kernel, this, max_sessions); // Set our member variables. m_is_light = is_light; @@ -28,42 +32,38 @@ void KPort::Initialize(s32 max_sessions, bool is_light, uintptr_t name) { m_state = State::Normal; } -void KPort::OnClientClosed() { - KScopedSchedulerLock sl{m_kernel}; +void KPort::OnClientClosed(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; if (m_state == State::Normal) { m_state = State::ClientClosed; } } -void KPort::OnServerClosed() { - KScopedSchedulerLock sl{m_kernel}; +void KPort::OnServerClosed(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; if (m_state == State::Normal) { m_state = State::ServerClosed; } } -bool KPort::IsServerClosed() const { - KScopedSchedulerLock sl{m_kernel}; +bool KPort::IsServerClosed(KernelCore& kernel) const { + KScopedSchedulerLock sl{kernel}; return m_state == State::ServerClosed; } -Result KPort::EnqueueSession(KServerSession* session) { - KScopedSchedulerLock sl{m_kernel}; - +Result KPort::EnqueueSession(KernelCore& kernel, KServerSession* session) { + KScopedSchedulerLock sl{kernel}; R_UNLESS(m_state == State::Normal, ResultPortClosed); - - m_server.EnqueueSession(session); + m_server.EnqueueSession(kernel, session); R_SUCCEED(); } -Result KPort::EnqueueSession(KLightServerSession* session) { - KScopedSchedulerLock sl{m_kernel}; - +Result KPort::EnqueueSession(KernelCore& kernel, KLightServerSession* session) { + KScopedSchedulerLock sl{kernel}; R_UNLESS(m_state == State::Normal, ResultPortClosed); - - m_server.EnqueueSession(session); + m_server.EnqueueSession(kernel, session); R_SUCCEED(); } diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h index 26f5f14eff..698f794538 100644 --- a/src/core/hle/kernel/k_port.h +++ b/src/core/hle/kernel/k_port.h @@ -1,3 +1,6 @@ +// 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 @@ -23,11 +26,11 @@ public: explicit KPort(KernelCore& kernel); ~KPort() override; - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} - void Initialize(s32 max_sessions, bool is_light, uintptr_t name); - void OnClientClosed(); - void OnServerClosed(); + void Initialize(KernelCore& kernel, s32 max_sessions, bool is_light, uintptr_t name); + void OnClientClosed(KernelCore& kernel); + void OnServerClosed(KernelCore& kernel); uintptr_t GetName() const { return m_name; @@ -36,10 +39,10 @@ public: return m_is_light; } - bool IsServerClosed() const; + bool IsServerClosed(KernelCore& kernel) const; - Result EnqueueSession(KServerSession* session); - Result EnqueueSession(KLightServerSession* session); + Result EnqueueSession(KernelCore& kernel, KServerSession* session); + Result EnqueueSession(KernelCore& kernel, KLightServerSession* session); KClientPort& GetClientPort() { return m_client; diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index f737a18736..7308b0ff87 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -28,8 +28,7 @@ namespace Kernel { namespace { -Result TerminateChildren(KernelCore& kernel, KProcess* process, - const KThread* thread_to_not_terminate) { +Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* thread_to_not_terminate) { // Request that all children threads terminate. { KScopedLightLock proc_lk(process->GetListLock()); @@ -41,14 +40,14 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, // This is valid because the only caller which uses non-nullptr as argument uses // GetCurrentThreadPointer(), but it's still notable because it seems incorrect at // first glance. - process->UnpinCurrentThread(); + process->UnpinCurrentThread(kernel); } auto& thread_list = process->GetThreadList(); for (auto it = thread_list.begin(); it != thread_list.end(); ++it) { if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) { if (thread->GetState() != ThreadState::Terminated) { - thread->RequestTerminate(); + thread->RequestTerminate(kernel); } } } @@ -65,7 +64,7 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, for (auto it = thread_list.begin(); it != thread_list.end(); ++it) { if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) { if (thread->GetState() != ThreadState::Terminated) { - if (thread->Open()) { + if (thread->Open(kernel)) { cur_child = thread; break; } @@ -81,11 +80,10 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, // Terminate and close the thread. SCOPE_EXIT { - cur_child->Close(); + cur_child->Close(kernel); }; - if (const Result terminate_result = cur_child->Terminate(); - ResultTerminationRequested == terminate_result) { + if (const Result terminate_result = cur_child->Terminate(kernel); ResultTerminationRequested == terminate_result) { R_THROW(terminate_result); } } @@ -101,21 +99,21 @@ public: explicit ThreadQueueImplForKProcessEnterUserException(KernelCore& kernel, KThread** t) : KThreadQueue(kernel), m_exception_thread(t) {} - virtual void EndWait(KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { // Set the exception thread. *m_exception_thread = waiting_thread; // Invoke the base end wait handler. - KThreadQueue::EndWait(waiting_thread, wait_result); + KThreadQueue::EndWait(kernel, waiting_thread, wait_result); } - virtual void CancelWait(KThread* waiting_thread, Result wait_result, + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter on its mutex owner. - waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); + waiting_thread->GetLockOwner(kernel)->RemoveWaiter(kernel, waiting_thread); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -128,12 +126,12 @@ void GenerateRandom(std::span<u64> out_random) { } // namespace -void KProcess::Finalize() { +void KProcess::Finalize(KernelCore& kernel) { // Delete the process local region. - this->DeleteThreadLocalRegion(m_plr_address); + this->DeleteThreadLocalRegion(kernel, m_plr_address); // Get the used memory size. - const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize(); + const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize(kernel); // Finalize the page table. m_page_table.Finalize(); @@ -142,10 +140,10 @@ void KProcess::Finalize() { if (m_system_resource) { if (m_system_resource->IsSecureResource()) { // Finalize optimized memory. If memory wasn't optimized, this is a no-op. - m_kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool); + kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool); } - m_system_resource->Close(); + m_system_resource->Close(kernel); m_system_resource = nullptr; } @@ -157,12 +155,12 @@ void KProcess::Finalize() { KSharedMemory* shmem = info->GetSharedMemory(); while (!info->Close()) { - shmem->Close(); + shmem->Close(kernel); } - shmem->Close(); + shmem->Close(kernel); it = m_shared_memory_list.erase(it); - KSharedMemoryInfo::Free(m_kernel, info); + KSharedMemoryInfo::Free(kernel, info); } } @@ -173,9 +171,8 @@ void KProcess::Finalize() { // Release memory to the resource limit. if (m_resource_limit != nullptr) { ASSERT(used_memory_size >= m_memory_release_hint); - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, used_memory_size, - used_memory_size - m_memory_release_hint); - m_resource_limit->Close(); + m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint); + m_resource_limit->Close(kernel); } // Clear expensive resources, as the destructor is not called for guest objects. @@ -185,15 +182,14 @@ void KProcess::Finalize() { m_exclusive_monitor.reset(); // Perform inherited finalization. - KSynchronizationObject::Finalize(); + KSynchronizationObject::Finalize(kernel); } -Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, - bool is_real) { +Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, bool is_real) { // TODO: remove this special case if (is_real) { // Create and clear the process local region. - R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address))); + R_TRY(this->CreateThreadLocalRegion(kernel, std::addressof(m_plr_address))); this->GetMemory().ZeroBlock(m_plr_address, Svc::ThreadLocalRegionSize); } @@ -259,7 +255,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResource // Open a reference to our resource limit. m_resource_limit = res_limit; - m_resource_limit->Open(); + m_resource_limit->Open(kernel); // We're initialized! m_is_initialized = true; @@ -267,7 +263,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResource R_SUCCEED(); } -Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg, +Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, const KPageGroup& pg, std::span<const u32> caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, bool immortal) { ASSERT(res_limit != nullptr); @@ -283,34 +279,33 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) { // Create a secure system resource. - KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel); + KSecureSystemResource* secure_resource = KSecureSystemResource::Create(kernel); R_UNLESS(secure_resource != nullptr, ResultOutOfResource); ON_RESULT_FAILURE { - secure_resource->Close(); + secure_resource->Close(kernel); }; // Initialize the secure resource. - R_TRY(secure_resource->Initialize(system_resource_num_pages * PageSize, res_limit, - m_memory_pool)); + R_TRY(secure_resource->Initialize(kernel, system_resource_num_pages * PageSize, res_limit, m_memory_pool)); // Set our system resource. m_system_resource = secure_resource; } else { // Use the system-wide system resource. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication); - m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource() - : m_kernel.GetSystemSystemResource()); + m_system_resource = std::addressof(is_app ? kernel.GetAppSystemResource() + : kernel.GetSystemSystemResource()); m_is_default_application_system_resource = is_app; // Open reference to the system resource. - m_system_resource->Open(); + m_system_resource->Open(kernel); } // Ensure we clean up our secure resource, if we fail. ON_RESULT_FAILURE { - m_system_resource->Close(); + m_system_resource->Close(kernel); m_system_resource = nullptr; }; @@ -330,7 +325,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa // Ensure our memory is initialized. m_memory.SetCurrentPageTable(*this); - m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); + m_memory.SetGPUDirtyManagers(kernel.System().GetGPUDirtyMemoryManager()); // Ensure we can insert the code region. R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, @@ -350,18 +345,18 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa } // Initialize the process id. - m_process_id = m_kernel.CreateNewUserProcessID(); + m_process_id = kernel.CreateNewUserProcessID(); ASSERT(InitialProcessIdMin <= m_process_id); ASSERT(m_process_id <= InitialProcessIdMax); // Initialize the rest of the process. - R_TRY(this->Initialize(params, res_limit, true)); + R_TRY(this->Initialize(kernel, params, res_limit, true)); // We succeeded! R_SUCCEED(); } -Result KProcess::Initialize(const Svc::CreateProcessParameter& params, +Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, std::span<const u32> user_caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, KProcessAddress aslr_space_start) { ASSERT(res_limit != nullptr); @@ -378,22 +373,22 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const size_t system_resource_size = system_resource_num_pages * PageSize; // Reserve memory for our code resource. - KScopedResourceReservation memory_reservation( + KScopedResourceReservation memory_reservation(kernel, res_limit, Svc::LimitableResource::PhysicalMemoryMax, code_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Setup our system resource. if (system_resource_num_pages != 0) { // Create a secure system resource. - KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel); + KSecureSystemResource* secure_resource = KSecureSystemResource::Create(kernel); R_UNLESS(secure_resource != nullptr, ResultOutOfResource); ON_RESULT_FAILURE { - secure_resource->Close(); + secure_resource->Close(kernel); }; // Initialize the secure resource. - R_TRY(secure_resource->Initialize(system_resource_size, res_limit, m_memory_pool)); + R_TRY(secure_resource->Initialize(kernel, system_resource_size, res_limit, m_memory_pool)); // Set our system resource. m_system_resource = secure_resource; @@ -401,18 +396,18 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, } else { // Use the system-wide system resource. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication); - m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource() - : m_kernel.GetSystemSystemResource()); + m_system_resource = std::addressof(is_app ? kernel.GetAppSystemResource() + : kernel.GetSystemSystemResource()); m_is_default_application_system_resource = is_app; // Open reference to the system resource. - m_system_resource->Open(); + m_system_resource->Open(kernel); } // Ensure we clean up our secure resource, if we fail. ON_RESULT_FAILURE { - m_system_resource->Close(); + m_system_resource->Close(kernel); m_system_resource = nullptr; }; @@ -432,7 +427,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, // Ensure our memory is initialized. m_memory.SetCurrentPageTable(*this); - m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); + m_memory.SetGPUDirtyManagers(kernel.System().GetGPUDirtyMemoryManager()); // Ensure we can insert the code region. R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code), @@ -451,101 +446,99 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, } // Initialize the process id. - m_process_id = m_kernel.CreateNewUserProcessID(); + m_process_id = kernel.CreateNewUserProcessID(); ASSERT(ProcessIdMin <= m_process_id); ASSERT(m_process_id <= ProcessIdMax); // If we should optimize memory allocations, do so. if (m_system_resource->IsSecureResource() && True(params.flags & Svc::CreateProcessFlag::OptimizeMemoryAllocation)) { - R_TRY(m_kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool)); + R_TRY(kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool)); } // Initialize the rest of the process. - R_TRY(this->Initialize(params, res_limit, true)); + R_TRY(this->Initialize(kernel, params, res_limit, true)); // We succeeded, so commit our memory reservation. memory_reservation.Commit(); R_SUCCEED(); } -void KProcess::DoWorkerTaskImpl() { +void KProcess::DoWorkerTaskImpl(KernelCore& kernel) { // Terminate child threads. - TerminateChildren(m_kernel, this, nullptr); + TerminateChildren(kernel, this, nullptr); // Finalize the handle table, if we're not immortal. if (!m_is_immortal && m_is_handle_table_initialized) { - this->FinalizeHandleTable(); + this->FinalizeHandleTable(kernel); } // Finish termination. - this->FinishTermination(); + this->FinishTermination(kernel); } -Result KProcess::StartTermination() { +Result KProcess::StartTermination(KernelCore& kernel) { // Finalize the handle table when we're done, if the process isn't immortal. SCOPE_EXIT { if (!m_is_immortal) { - this->FinalizeHandleTable(); + this->FinalizeHandleTable(kernel); } }; // Terminate child threads other than the current one. - R_RETURN(TerminateChildren(m_kernel, this, GetCurrentThreadPointer(m_kernel))); + R_RETURN(TerminateChildren(kernel, this, GetCurrentThreadPointer(kernel))); } -void KProcess::FinishTermination() { +void KProcess::FinishTermination(KernelCore& kernel) { // Only allow termination to occur if the process isn't immortal. if (!m_is_immortal) { // Release resource limit hint. if (m_resource_limit != nullptr) { - m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize(); - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, 0, - m_memory_release_hint); + m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize(kernel); + m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, 0, m_memory_release_hint); } // Change state. { - KScopedSchedulerLock sl(m_kernel); - this->ChangeState(State::Terminated); + KScopedSchedulerLock sl(kernel); + this->ChangeState(kernel, State::Terminated); } // Close. - this->Close(); + this->Close(kernel); } } -void KProcess::Exit() { +void KProcess::Exit(KernelCore& kernel) { // Determine whether we need to start terminating bool needs_terminate = false; { KScopedLightLock lk(m_state_lock); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); ASSERT(m_state != State::Created); ASSERT(m_state != State::CreatedAttached); ASSERT(m_state != State::Crashed); ASSERT(m_state != State::Terminated); - if (m_state == State::Running || m_state == State::RunningAttached || - m_state == State::DebugBreak) { - this->ChangeState(State::Terminating); + if (m_state == State::Running || m_state == State::RunningAttached || m_state == State::DebugBreak) { + this->ChangeState(kernel, State::Terminating); needs_terminate = true; } } // If we need to start termination, do so. if (needs_terminate) { - this->StartTermination(); + this->StartTermination(kernel); // Register the process as a work task. - m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, this); + kernel.WorkerTaskManager().AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); } // Exit the current thread. - GetCurrentThread(m_kernel).Exit(); + GetCurrentThread(kernel).Exit(kernel); } -Result KProcess::Terminate() { +Result KProcess::Terminate(KernelCore& kernel) { // Determine whether we need to start terminating. bool needs_terminate = false; { @@ -555,11 +548,11 @@ Result KProcess::Terminate() { R_UNLESS(m_state != State::Created, ResultInvalidState); R_UNLESS(m_state != State::CreatedAttached, ResultInvalidState); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (m_state == State::Running || m_state == State::RunningAttached || m_state == State::Crashed || m_state == State::DebugBreak) { - this->ChangeState(State::Terminating); + this->ChangeState(kernel, State::Terminating); needs_terminate = true; } } @@ -567,20 +560,19 @@ Result KProcess::Terminate() { // If we need to terminate, do so. if (needs_terminate) { // Start termination. - if (R_SUCCEEDED(this->StartTermination())) { + if (R_SUCCEEDED(this->StartTermination(kernel))) { // Finish termination. - this->FinishTermination(); + this->FinishTermination(kernel); } else { // Register the process as a work task. - m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, - this); + kernel.WorkerTaskManager().AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); } } R_SUCCEED(); } -Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) { +Result KProcess::AddSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -596,7 +588,7 @@ Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, // If we didn't find an info, create one. if (info == nullptr) { // Allocate a new info. - info = KSharedMemoryInfo::Allocate(m_kernel); + info = KSharedMemoryInfo::Allocate(kernel); R_UNLESS(info != nullptr, ResultOutOfResource); // Initialize the info and add it to our list. @@ -605,13 +597,13 @@ Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, } // Open a reference to the shared memory and its info. - shmem->Open(); + shmem->Open(kernel); info->Open(); R_SUCCEED(); } -void KProcess::RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) { +void KProcess::RemoveSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -629,19 +621,19 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, // Close a reference to the info and its memory. if (info->Close()) { m_shared_memory_list.erase(it); - KSharedMemoryInfo::Free(m_kernel, info); + KSharedMemoryInfo::Free(kernel, info); } - shmem->Close(); + shmem->Close(kernel); } -Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { +Result KProcess::CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* out) { KThreadLocalPage* tlp = nullptr; KProcessAddress tlr = 0; // See if we can get a region from a partially used TLP. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (auto it = m_partially_used_tlp_tree.begin(); it != m_partially_used_tlp_tree.end()) { tlr = it->Reserve(); @@ -659,14 +651,14 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { } // Allocate a new page. - tlp = KThreadLocalPage::Allocate(m_kernel); + tlp = KThreadLocalPage::Allocate(kernel); R_UNLESS(tlp != nullptr, ResultOutOfMemory); ON_RESULT_FAILURE { - KThreadLocalPage::Free(m_kernel, tlp); + KThreadLocalPage::Free(kernel, tlp); }; // Initialize the new page. - R_TRY(tlp->Initialize(m_kernel, this)); + R_TRY(tlp->Initialize(kernel, this)); // Reserve a TLR. tlr = tlp->Reserve(); @@ -674,7 +666,7 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { // Insert into our tree. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (tlp->IsAllUsed()) { m_fully_used_tlp_tree.insert(*tlp); } else { @@ -687,12 +679,12 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { R_SUCCEED(); } -Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) { +Result KProcess::DeleteThreadLocalRegion(KernelCore& kernel, KProcessAddress addr) { KThreadLocalPage* page_to_free = nullptr; // Release the region. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Try to find the page in the partially used list. auto it = m_partially_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize)); @@ -729,57 +721,56 @@ Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) { if (page_to_free != nullptr) { page_to_free->Finalize(); - KThreadLocalPage::Free(m_kernel, page_to_free); + KThreadLocalPage::Free(kernel, page_to_free); } R_SUCCEED(); } -bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value) { +bool KProcess::ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - return rl->Reserve(which, value); + return rl->Reserve(kernel, which, value); } else { return true; } } -bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout) { +bool KProcess::ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 timeout) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - return rl->Reserve(which, value, timeout); + return rl->Reserve(kernel, which, value, timeout); } else { return true; } } -void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value) { +void KProcess::ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - rl->Release(which, value); + rl->Release(kernel, which, value); } } -void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint) { +void KProcess::ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 hint) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - rl->Release(which, value, hint); + rl->Release(kernel, which, value, hint); } } -void KProcess::IncrementRunningThreadCount() { +void KProcess::IncrementRunningThreadCount(KernelCore& kernel) { ASSERT(m_num_running_threads.load() >= 0); ++m_num_running_threads; } -void KProcess::DecrementRunningThreadCount() { +void KProcess::DecrementRunningThreadCount(KernelCore& kernel) { ASSERT(m_num_running_threads.load() > 0); - if (const auto prev = m_num_running_threads--; prev == 1) { - this->Terminate(); + this->Terminate(kernel); } } -bool KProcess::EnterUserException() { +bool KProcess::EnterUserException(KernelCore& kernel) { // Get the current thread. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); ASSERT(this == cur_thread->GetOwnerProcess()); // Check that we haven't already claimed the exception thread. @@ -788,13 +779,13 @@ bool KProcess::EnterUserException() { } // Create the wait queue we'll be using. - ThreadQueueImplForKProcessEnterUserException wait_queue(m_kernel, + ThreadQueueImplForKProcessEnterUserException wait_queue(kernel, std::addressof(m_exception_thread)); // Claim the exception thread. { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Check that we're not terminating. if (cur_thread->IsTerminationRequested()) { @@ -804,45 +795,44 @@ bool KProcess::EnterUserException() { // If we don't have an exception thread, we can just claim it directly. if (m_exception_thread == nullptr) { m_exception_thread = cur_thread; - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); return true; } // Otherwise, we need to wait until we don't have an exception thread. // Add the current thread as a waiter on the current exception thread. - cur_thread->SetKernelAddressKey( - reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)) | 1); - m_exception_thread->AddWaiter(cur_thread); + cur_thread->SetKernelAddressKey(uintptr_t(std::addressof(m_exception_thread)) | 1); + m_exception_thread->AddWaiter(kernel, cur_thread); // Wait to claim the exception thread. - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(kernel, std::addressof(wait_queue)); } // If our wait didn't end due to thread termination, we succeeded. return ResultTerminationRequested != cur_thread->GetWaitResult(); } -bool KProcess::LeaveUserException() { - return this->ReleaseUserException(GetCurrentThreadPointer(m_kernel)); +bool KProcess::LeaveUserException(KernelCore& kernel) { + return this->ReleaseUserException(kernel, GetCurrentThreadPointer(kernel)); } -bool KProcess::ReleaseUserException(KThread* thread) { - KScopedSchedulerLock sl(m_kernel); +bool KProcess::ReleaseUserException(KernelCore& kernel, KThread* thread) { + KScopedSchedulerLock sl(kernel); if (m_exception_thread == thread) { m_exception_thread = nullptr; // Remove waiter thread. bool has_waiters; - if (KThread* next = thread->RemoveKernelWaiterByKey( + if (KThread* next = thread->RemoveKernelWaiterByKey(kernel, std::addressof(has_waiters), reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)) | 1); next != nullptr) { - next->EndWait(ResultSuccess); + next->EndWait(kernel, ResultSuccess); } - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); return true; } else { @@ -850,19 +840,19 @@ bool KProcess::ReleaseUserException(KThread* thread) { } } -void KProcess::RegisterThread(KThread* thread) { +void KProcess::RegisterThread(KernelCore& kernel, KThread* thread) { KScopedLightLock lk(m_list_lock); m_thread_list.push_back(*thread); } -void KProcess::UnregisterThread(KThread* thread) { +void KProcess::UnregisterThread(KernelCore& kernel, KThread* thread) { KScopedLightLock lk(m_list_lock); m_thread_list.erase(m_thread_list.iterator_to(*thread)); } -size_t KProcess::GetUsedUserPhysicalMemorySize() const { +size_t KProcess::GetUsedUserPhysicalMemorySize(KernelCore& kernel) const { const size_t norm_size = m_page_table.GetNormalMemorySize(); const size_t other_size = m_code_size + m_main_thread_stack_size; const size_t sec_size = this->GetRequiredSecureMemorySizeNonDefault(); @@ -870,7 +860,7 @@ size_t KProcess::GetUsedUserPhysicalMemorySize() const { return norm_size + other_size + sec_size; } -size_t KProcess::GetTotalUserPhysicalMemorySize() const { +size_t KProcess::GetTotalUserPhysicalMemorySize(KernelCore& kernel) const { // Get the amount of free and used size. const size_t free_size = m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax); @@ -889,18 +879,18 @@ size_t KProcess::GetTotalUserPhysicalMemorySize() const { if (used_size + free_size > max_size) { return max_size; } else { - return free_size + this->GetUsedUserPhysicalMemorySize(); + return free_size + this->GetUsedUserPhysicalMemorySize(kernel); } } -size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize() const { +size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize(KernelCore& kernel) const { const size_t norm_size = m_page_table.GetNormalMemorySize(); const size_t other_size = m_code_size + m_main_thread_stack_size; return norm_size + other_size; } -size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const { +size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize(KernelCore& kernel) const { // Get the amount of free and used size. const size_t free_size = m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax); @@ -919,11 +909,11 @@ size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const { if (used_size + free_size > max_size) { return max_size - this->GetRequiredSecureMemorySizeNonDefault(); } else { - return free_size + this->GetUsedNonSystemUserPhysicalMemorySize(); + return free_size + this->GetUsedNonSystemUserPhysicalMemorySize(kernel); } } -Result KProcess::Run(s32 priority, size_t stack_size) { +Result KProcess::Run(KernelCore& kernel, s32 priority, size_t stack_size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -932,7 +922,7 @@ Result KProcess::Run(s32 priority, size_t stack_size) { R_UNLESS(state == State::Created || state == State::CreatedAttached, ResultInvalidState); // Place a tentative reservation of a thread for this process. - KScopedResourceReservation thread_reservation(this, Svc::LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(kernel, this, Svc::LimitableResource::ThreadCountMax); R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached); // Ensure that we haven't already allocated stack. @@ -944,7 +934,7 @@ Result KProcess::Run(s32 priority, size_t stack_size) { R_UNLESS(stack_size + m_code_size >= m_code_size, ResultOutOfMemory); // Place a tentative reservation of memory for our new stack. - KScopedResourceReservation mem_reservation(this, Svc::LimitableResource::PhysicalMemoryMax, + KScopedResourceReservation mem_reservation(kernel, this, Svc::LimitableResource::PhysicalMemoryMax, stack_size); R_UNLESS(mem_reservation.Succeeded(), ResultLimitReached); @@ -974,29 +964,29 @@ Result KProcess::Run(s32 priority, size_t stack_size) { (m_main_thread_stack_size + m_code_size))); // Initialize our handle table. - R_TRY(this->InitializeHandleTable(m_capabilities.GetHandleTableSize())); + R_TRY(this->InitializeHandleTable(kernel, m_capabilities.GetHandleTableSize())); ON_RESULT_FAILURE_2 { - this->FinalizeHandleTable(); + this->FinalizeHandleTable(kernel); }; // Create a new thread for the process. - KThread* main_thread = KThread::Create(m_kernel); + KThread* main_thread = KThread::Create(kernel); R_UNLESS(main_thread != nullptr, ResultOutOfResource); SCOPE_EXIT { - main_thread->Close(); + main_thread->Close(kernel); }; // Initialize the thread. - R_TRY(KThread::InitializeUserThread(m_kernel.System(), main_thread, this->GetEntryPoint(), 0, + R_TRY(KThread::InitializeUserThread(kernel.System(), main_thread, this->GetEntryPoint(), 0, stack_top, priority, m_ideal_core_id, this)); // Register the thread, and commit our reservation. - KThread::Register(m_kernel, main_thread); + KThread::Register(kernel, main_thread); thread_reservation.Commit(); // Add the thread to our handle table. Handle thread_handle; - R_TRY(m_handle_table.Add(std::addressof(thread_handle), main_thread)); + R_TRY(m_handle_table.Add(kernel, std::addressof(thread_handle), main_thread)); // Set the thread arguments. Two distinct entry conventions: // * Kernel/NSO entry (no homebrew ABI): x0 = 0, x1 = thread_handle @@ -1024,21 +1014,21 @@ Result KProcess::Run(s32 priority, size_t stack_size) { this->GetMemory().Write32(GetInteger(main_thread->GetTlsAddress()) + 0x110, thread_handle); // Update our state. - this->ChangeState((state == State::Created) ? State::Running : State::RunningAttached); + this->ChangeState(kernel, (state == State::Created) ? State::Running : State::RunningAttached); ON_RESULT_FAILURE_2 { - this->ChangeState(state); + this->ChangeState(kernel, state); }; // Suspend for debug, if we should. - if (m_kernel.System().DebuggerEnabled()) { - main_thread->RequestSuspend(SuspendType::Debug); + if (kernel.System().DebuggerEnabled()) { + main_thread->RequestSuspend(kernel, SuspendType::Debug); } // Run our thread. - R_TRY(main_thread->Run()); + R_TRY(main_thread->Run(kernel)); // Open a reference to represent that we're running. - this->Open(); + this->Open(kernel); // We succeeded! Commit our memory reservation. mem_reservation.Commit(); @@ -1046,10 +1036,10 @@ Result KProcess::Run(s32 priority, size_t stack_size) { R_SUCCEED(); } -Result KProcess::Reset() { +Result KProcess::Reset(KernelCore& kernel) { // Lock the process and the scheduler. KScopedLightLock lk(m_state_lock); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Validate that we're in a state that we can reset. R_UNLESS(m_state != State::Terminated, ResultInvalidState); @@ -1060,11 +1050,11 @@ Result KProcess::Reset() { R_SUCCEED(); } -Result KProcess::SetActivity(Svc::ProcessActivity activity) { +Result KProcess::SetActivity(KernelCore& kernel, Svc::ProcessActivity activity) { // Lock ourselves and the scheduler. KScopedLightLock lk(m_state_lock); KScopedLightLock list_lk(m_list_lock); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Validate our state. R_UNLESS(m_state != State::Terminating, ResultInvalidState); @@ -1078,7 +1068,7 @@ Result KProcess::SetActivity(Svc::ProcessActivity activity) { // Suspend all threads. auto end = this->GetThreadList().end(); for (auto it = this->GetThreadList().begin(); it != end; ++it) { - it->RequestSuspend(SuspendType::Process); + it->RequestSuspend(kernel, SuspendType::Process); } // Set ourselves as suspended. @@ -1092,7 +1082,7 @@ Result KProcess::SetActivity(Svc::ProcessActivity activity) { // Resume all threads. auto end = this->GetThreadList().end(); for (auto it = this->GetThreadList().begin(); it != end; ++it) { - it->Resume(SuspendType::Process); + it->Resume(kernel, SuspendType::Process); } // Set ourselves as resumed. @@ -1102,54 +1092,54 @@ Result KProcess::SetActivity(Svc::ProcessActivity activity) { R_SUCCEED(); } -void KProcess::PinCurrentThread() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +void KProcess::PinCurrentThread(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the current thread. - const s32 core_id = GetCurrentCoreId(m_kernel); - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + const s32 core_id = GetCurrentCoreId(kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); // If the thread isn't terminated, pin it. if (!cur_thread->IsTerminationRequested()) { // Pin it. this->PinThread(core_id, cur_thread); - cur_thread->Pin(core_id); + cur_thread->Pin(kernel, core_id); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } } -void KProcess::UnpinCurrentThread() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +void KProcess::UnpinCurrentThread(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the current thread. - const s32 core_id = GetCurrentCoreId(m_kernel); - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + const s32 core_id = GetCurrentCoreId(kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); // Unpin it. - cur_thread->Unpin(); + cur_thread->Unpin(kernel); this->UnpinThread(core_id, cur_thread); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } -void KProcess::UnpinThread(KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +void KProcess::UnpinThread(KernelCore& kernel, KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the thread's core id. const auto core_id = thread->GetActiveCore(); // Unpin it. this->UnpinThread(core_id, thread); - thread->Unpin(); + thread->Unpin(kernel); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } -Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, +Result KProcess::GetThreadList(KernelCore& kernel, s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count) { auto& memory = this->GetMemory(); @@ -1179,7 +1169,7 @@ Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ R_SUCCEED(); } -void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {} +void KProcess::Switch(KernelCore& kernel, KProcess* cur_process, KProcess* next_process) {} KProcess::KProcess(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer(kernel) @@ -1195,16 +1185,16 @@ KProcess::KProcess(KernelCore& kernel) KProcess::~KProcess() = default; -Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset) { +Result KProcess::LoadFromMetadata(KernelCore& kernel, const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset) { // Create a resource limit for the process. const auto pool = static_cast<KMemoryManager::Pool>(metadata.GetPoolPartition()); - const auto physical_memory_size = m_kernel.MemoryManager().GetSize(pool); + const auto physical_memory_size = kernel.MemoryManager().GetSize(pool); auto* res_limit = - Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size); + Kernel::CreateResourceLimitForProcess(kernel.System(), physical_memory_size); // Ensure we maintain a clean state on exit. SCOPE_EXIT { - res_limit->Close(); + res_limit->Close(kernel); }; // Declare flags and code address. @@ -1263,22 +1253,20 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: std::memcpy(params.name.data(), name.data(), sizeof(params.name)); // Initialize for application process. - R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, pool, - aslr_space_start)); + R_TRY(this->Initialize(kernel, params, metadata.GetKernelCapabilities(), res_limit, pool, aslr_space_start)); // Assign remaining properties. m_ideal_core_id = metadata.GetMainThreadCore(); // Set up emulation context. - this->InitializeInterfaces(); + this->InitializeInterfaces(kernel); // We succeeded. R_SUCCEED(); } -void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { - const auto ReprotectSegment = [&](const CodeSet::Segment& segment, - Svc::MemoryPermission permission) { +void KProcess::LoadModule(KernelCore& kernel, CodeSet code_set, KProcessAddress base_addr) { + const auto ReprotectSegment = [&](const CodeSet::Segment& segment, Svc::MemoryPermission permission) { m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); }; @@ -1292,7 +1280,7 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { const auto& patch = code_set.PatchSegment(); const auto& post_patch = code_set.PostPatchSegment(); if (this->IsApplication() && Settings::IsNceEnabled() && patch.size != 0) { - auto& buffer = m_kernel.System().DeviceMemory().buffer; + auto& buffer = kernel.System().DeviceMemory().buffer; const auto& code = code_set.CodeSegment(); buffer.Protect(GetInteger(base_addr + code.addr), code.size, Common::MemoryPermission::Read | Common::MemoryPermission::Execute); @@ -1311,32 +1299,32 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { #endif } -void KProcess::InitializeInterfaces() { +void KProcess::InitializeInterfaces(KernelCore& kernel) { m_exclusive_monitor = Core::MakeExclusiveMonitor(this->GetMemory(), Core::Hardware::NUM_CPU_CORES); #ifdef HAS_NCE if (this->IsApplication() && Settings::IsNceEnabled()) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) - m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(m_kernel.System(), true, i); + m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(kernel.System(), true, i); } else #endif if (this->Is64Bit()) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique<Core::ArmDynarmic64>( - m_kernel.System(), m_kernel.IsMulticore(), this, + kernel.System(), kernel.IsMulticore(), this, static_cast<Core::DynarmicExclusiveMonitor&>(*m_exclusive_monitor), i); } } else { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique<Core::ArmDynarmic32>( - m_kernel.System(), m_kernel.IsMulticore(), this, + kernel.System(), kernel.IsMulticore(), this, static_cast<Core::DynarmicExclusiveMonitor&>(*m_exclusive_monitor), i); } } } -bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { +bool KProcess::InsertWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { return wp.type == DebugWatchpointType::None; })}; @@ -1358,7 +1346,7 @@ bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointT return true; } -bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { +bool KProcess::RemoveWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { return wp.start_address == addr && wp.end_address == addr + size && wp.type == type; })}; diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 2413e5bfd9..c861a9ea51 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -141,8 +141,8 @@ private: bool m_is_handle_table_initialized : 1 = false; private: - Result StartTermination(); - void FinishTermination(); + Result StartTermination(KernelCore& kernel); + void FinishTermination(KernelCore& kernel); void PinThread(s32 core_id, KThread* thread) { ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); @@ -162,16 +162,16 @@ public: explicit KProcess(KernelCore& kernel); ~KProcess() override; - Result Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, + Result Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, bool is_real); - Result Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg, + Result Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, const KPageGroup& pg, std::span<const u32> caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, bool immortal); - Result Initialize(const Svc::CreateProcessParameter& params, std::span<const u32> user_caps, + Result Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, std::span<const u32> user_caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, KProcessAddress aslr_space_start); - void Exit(); + void Exit(KernelCore& kernel); const char* GetName() const { return m_name.data(); @@ -267,7 +267,7 @@ public: m_pointer_buffer_size = size; } - Result Terminate(); + Result Terminate(KernelCore& kernel); bool IsTerminated() const { return m_state == State::Terminated; @@ -300,9 +300,9 @@ public: return m_thread_list; } - bool EnterUserException(); - bool LeaveUserException(); - bool ReleaseUserException(KThread* thread); + bool EnterUserException(KernelCore& kernel); + bool LeaveUserException(KernelCore& kernel); + bool ReleaseUserException(KernelCore& kernel, KThread* thread); KThread* GetPinnedThread(s32 core_id) const { ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); @@ -317,10 +317,10 @@ public: return m_resource_limit; } - bool ReserveResource(Svc::LimitableResource which, s64 value); - bool ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout); - void ReleaseResource(Svc::LimitableResource which, s64 value); - void ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint); + bool ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value); + bool ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 timeout); + void ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value); + void ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 hint); KLightLock& GetStateLock() { return m_state_lock; @@ -343,16 +343,16 @@ public: return m_handle_table; } - size_t GetUsedUserPhysicalMemorySize() const; - size_t GetTotalUserPhysicalMemorySize() const; - size_t GetUsedNonSystemUserPhysicalMemorySize() const; - size_t GetTotalNonSystemUserPhysicalMemorySize() const; + size_t GetUsedUserPhysicalMemorySize(KernelCore& kernel) const; + size_t GetTotalUserPhysicalMemorySize(KernelCore& kernel) const; + size_t GetUsedNonSystemUserPhysicalMemorySize(KernelCore& kernel) const; + size_t GetTotalNonSystemUserPhysicalMemorySize(KernelCore& kernel) const; - Result AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size); - void RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size); + Result AddSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size); + void RemoveSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size); - Result CreateThreadLocalRegion(KProcessAddress* out); - Result DeleteThreadLocalRegion(KProcessAddress addr); + Result CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* out); + Result DeleteThreadLocalRegion(KernelCore& kernel, KProcessAddress addr); KProcessAddress GetProcessLocalRegionAddress() const { return m_plr_address; @@ -376,8 +376,8 @@ public: ++m_schedule_count; } - void IncrementRunningThreadCount(); - void DecrementRunningThreadCount(); + void IncrementRunningThreadCount(KernelCore& kernel); + void DecrementRunningThreadCount(KernelCore& kernel); size_t GetRequiredSecureMemorySizeNonDefault() const { if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) { @@ -422,11 +422,9 @@ public: } void ClearRunningThread(KThread* thread) { - for (size_t i = 0; i < m_running_threads.size(); ++i) { - if (m_running_threads[i] == thread) { + for (size_t i = 0; i < m_running_threads.size(); ++i) + if (m_running_threads[i] == thread) m_running_threads[i] = nullptr; - } - } } const KSystemResource& GetSystemResource() const { @@ -453,30 +451,27 @@ public: return m_running_thread_switch_counts[core]; } - void RegisterThread(KThread* thread); - void UnregisterThread(KThread* thread); - - Result Run(s32 priority, size_t stack_size); + void RegisterThread(KernelCore& kernel, KThread* thread); + void UnregisterThread(KernelCore& kernel, KThread* thread); + Result Run(KernelCore& kernel, s32 priority, size_t stack_size); + Result Reset(KernelCore& kernel); - Result Reset(); - - void SetDebugBreak() { + void SetDebugBreak(KernelCore& kernel) { if (m_state == State::RunningAttached) { - this->ChangeState(State::DebugBreak); + this->ChangeState(kernel, State::DebugBreak); } } - void SetAttached() { + void SetAttached(KernelCore& kernel) { if (m_state == State::DebugBreak) { - this->ChangeState(State::RunningAttached); + this->ChangeState(kernel, State::RunningAttached); } } - Result SetActivity(Svc::ProcessActivity activity); - - void PinCurrentThread(); - void UnpinCurrentThread(); - void UnpinThread(KThread* thread); + Result SetActivity(KernelCore& kernel, Svc::ProcessActivity activity); + void PinCurrentThread(KernelCore& kernel); + void UnpinCurrentThread(KernelCore& kernel); + void UnpinThread(KernelCore& kernel, KThread* thread); void SignalConditionVariable(uintptr_t cv_key, int32_t count) { return m_cond_var.Signal(cv_key, count); @@ -486,19 +481,17 @@ public: R_RETURN(m_cond_var.Wait(address, cv_key, tag, ns)); } - Result SignalAddressArbiter(uintptr_t address, Svc::SignalType signal_type, s32 value, - s32 count) { + Result SignalAddressArbiter(uintptr_t address, Svc::SignalType signal_type, s32 value, s32 count) { R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count)); } - Result WaitAddressArbiter(uintptr_t address, Svc::ArbitrationType arb_type, s32 value, - s64 timeout) { + Result WaitAddressArbiter(uintptr_t address, Svc::ArbitrationType arb_type, s32 value, s64 timeout) { R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout)); } - Result GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count); + Result GetThreadList(KernelCore& kernel, s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count); - static void Switch(KProcess* cur_process, KProcess* next_process); + static void Switch(KernelCore& kernel, KProcess* cur_process, KProcess* next_process); #ifdef HAS_NCE ankerl::unordered_dense::map<u64, u64>& GetPostHandlers() noexcept { @@ -512,21 +505,21 @@ public: public: // Attempts to insert a watchpoint into a free slot. Returns false if none are available. - bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); + bool InsertWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type); // Attempts to remove the watchpoint specified by the given parameters. - bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); + bool RemoveWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type); const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const { return m_watchpoints; } public: - Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset); + Result LoadFromMetadata(KernelCore& kernel, const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset); - void LoadModule(CodeSet code_set, KProcessAddress base_addr); + void LoadModule(KernelCore& kernel, CodeSet code_set, KProcessAddress base_addr); - void InitializeInterfaces(); + void InitializeInterfaces(KernelCore& kernel); Core::Memory::Memory& GetMemory() { return m_memory; @@ -542,9 +535,9 @@ public: return m_is_initialized; } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} - void Finalize() override; + void Finalize(KernelCore& kernel) override; u64 GetIdImpl() const { return this->GetProcessId(); @@ -553,34 +546,34 @@ public: return this->GetIdImpl(); } - virtual bool IsSignaled() const override { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + virtual bool IsSignaled(KernelCore& kernel) const override { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); return m_is_signaled; } - void DoWorkerTaskImpl(); + void DoWorkerTaskImpl(KernelCore& kernel); private: - void ChangeState(State new_state) { + void ChangeState(KernelCore& kernel, State new_state) { if (m_state != new_state) { m_state = new_state; m_is_signaled = true; - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } - Result InitializeHandleTable(s32 size) { + Result InitializeHandleTable(KernelCore& kernel, s32 size) { // Try to initialize the handle table. - R_TRY(m_handle_table.Initialize(size)); + R_TRY(m_handle_table.Initialize(kernel, size)); // We succeeded, so note that we did. m_is_handle_table_initialized = true; R_SUCCEED(); } - void FinalizeHandleTable() { + void FinalizeHandleTable(KernelCore& kernel) { // Finalize the table. - m_handle_table.Finalize(); + m_handle_table.Finalize(kernel); // Note that the table is finalized. m_is_handle_table_initialized = false; diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp index c30662666b..a00941bc1e 100644 --- a/src/core/hle/kernel/k_readable_event.cpp +++ b/src/core/hle/kernel/k_readable_event.cpp @@ -1,3 +1,6 @@ +// 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 @@ -15,50 +18,45 @@ KReadableEvent::KReadableEvent(KernelCore& kernel) : KSynchronizationObject{kern KReadableEvent::~KReadableEvent() = default; -void KReadableEvent::Initialize(KEvent* parent) { +void KReadableEvent::Initialize(KernelCore& kernel, KEvent* parent) { m_is_signaled = false; m_parent = parent; - if (m_parent != nullptr) { - m_parent->Open(); + m_parent->Open(kernel); } } -bool KReadableEvent::IsSignaled() const { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); - +bool KReadableEvent::IsSignaled(KernelCore& kernel) const { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); return m_is_signaled; } -void KReadableEvent::Destroy() { +void KReadableEvent::Destroy(KernelCore& kernel) { if (m_parent) { { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; m_parent->OnReadableEventDestroyed(); } - m_parent->Close(); + m_parent->Close(kernel); } } -Result KReadableEvent::Signal() { - KScopedSchedulerLock lk{m_kernel}; - +Result KReadableEvent::Signal(KernelCore& kernel) { + KScopedSchedulerLock lk{kernel}; if (!m_is_signaled) { m_is_signaled = true; - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } - R_SUCCEED(); } -Result KReadableEvent::Clear() { - this->Reset(); - +Result KReadableEvent::Clear(KernelCore& kernel) { + this->Reset(kernel); R_SUCCEED(); } -Result KReadableEvent::Reset() { - KScopedSchedulerLock lk{m_kernel}; +Result KReadableEvent::Reset(KernelCore& kernel) { + KScopedSchedulerLock lk{kernel}; R_UNLESS(m_is_signaled, ResultInvalidState); diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h index d2ec363233..63a6e8de60 100644 --- a/src/core/hle/kernel/k_readable_event.h +++ b/src/core/hle/kernel/k_readable_event.h @@ -1,3 +1,6 @@ +// 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 @@ -20,19 +23,17 @@ public: explicit KReadableEvent(KernelCore& kernel); ~KReadableEvent() override; - void Initialize(KEvent* parent); + void Initialize(KernelCore& kernel, KEvent* parent); KEvent* GetParent() const { return m_parent; } - Result Signal(); - Result Clear(); - - bool IsSignaled() const override; - void Destroy() override; - - Result Reset(); + Result Signal(KernelCore& kernel); + Result Clear(KernelCore& kernel); + bool IsSignaled(KernelCore& kernel) const override; + void Destroy(KernelCore& kernel) override; + Result Reset(KernelCore& kernel); private: bool m_is_signaled{}; diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index e886f97ebd..1a2c92a665 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -16,12 +16,15 @@ namespace Kernel { constexpr s64 DefaultTimeout = 10000000000; // 10 seconds KResourceLimit::KResourceLimit(KernelCore& kernel) - : KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {} + : KAutoObjectWithSlabHeapAndContainer{kernel} + , m_lock{kernel} + , m_cond_var{kernel} +{} KResourceLimit::~KResourceLimit() = default; void KResourceLimit::Initialize() {} -void KResourceLimit::Finalize() {} +void KResourceLimit::Finalize(KernelCore& kernel) {} s64 KResourceLimit::GetLimitValue(LimitableResource which) const { const auto index = static_cast<std::size_t>(which); @@ -87,11 +90,11 @@ Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { R_SUCCEED(); } -bool KResourceLimit::Reserve(LimitableResource which, s64 value) { - return Reserve(which, value, m_kernel.HardwareTimer().GetTick() + DefaultTimeout); +bool KResourceLimit::Reserve(KernelCore& kernel, LimitableResource which, s64 value) { + return Reserve(kernel, which, value, kernel.HardwareTimer().GetTick() + DefaultTimeout); } -bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { +bool KResourceLimit::Reserve(KernelCore& kernel, LimitableResource which, s64 value, s64 timeout) { ASSERT(value >= 0); const auto index = static_cast<std::size_t>(which); KScopedLightLock lk(m_lock); @@ -119,7 +122,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { } if (m_current_hints[index] + value <= m_limit_values[index] && - (timeout < 0 || m_kernel.HardwareTimer().GetTick() < timeout)) { + (timeout < 0 || kernel.HardwareTimer().GetTick() < timeout)) { m_waiter_count++; m_cond_var.Wait(std::addressof(m_lock), timeout, false); m_waiter_count--; @@ -131,11 +134,11 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { return false; } -void KResourceLimit::Release(LimitableResource which, s64 value) { - Release(which, value, value); +void KResourceLimit::Release(KernelCore& kernel, LimitableResource which, s64 value) { + Release(kernel, which, value, value); } -void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) { +void KResourceLimit::Release(KernelCore& kernel, LimitableResource which, s64 value, s64 hint) { ASSERT(value >= 0); ASSERT(hint >= 0); diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index b733ec8f81..eb45d23bab 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -32,7 +35,7 @@ public: ~KResourceLimit() override; void Initialize(); - void Finalize() override; + void Finalize(KernelCore& kernel) override; s64 GetLimitValue(LimitableResource which) const; s64 GetCurrentValue(LimitableResource which) const; @@ -41,12 +44,12 @@ public: Result SetLimitValue(LimitableResource which, s64 value); - bool Reserve(LimitableResource which, s64 value); - bool Reserve(LimitableResource which, s64 value, s64 timeout); - void Release(LimitableResource which, s64 value); - void Release(LimitableResource which, s64 value, s64 hint); + bool Reserve(KernelCore& kernel, LimitableResource which, s64 value); + bool Reserve(KernelCore& kernel, LimitableResource which, s64 value, s64 timeout); + void Release(KernelCore& kernel, LimitableResource which, s64 value); + void Release(KernelCore& kernel, LimitableResource which, s64 value, s64 hint); - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} private: using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>; diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 4b76e18950..8e629f6456 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -30,34 +30,32 @@ static void IncrementScheduledCount(Kernel::KThread* thread) { } } -KScheduler::KScheduler(KernelCore& kernel) : m_kernel{kernel} { - m_switch_fiber = std::make_shared<Common::Fiber>([this] { +KScheduler::KScheduler(KernelCore& kernel) { + m_switch_fiber = std::make_shared<Common::Fiber>([this, &kernel] { while (true) { - ScheduleImplFiber(); + ScheduleImplFiber(kernel); } }); - m_state.needs_scheduling = true; } KScheduler::~KScheduler() = default; -void KScheduler::SetInterruptTaskRunnable() { +void KScheduler::SetInterruptTaskRunnable(KernelCore& kernel) { m_state.interrupt_task_runnable = true; m_state.needs_scheduling = true; } -void KScheduler::RequestScheduleOnInterrupt() { +void KScheduler::RequestScheduleOnInterrupt(KernelCore& kernel) { m_state.needs_scheduling = true; - - if (CanSchedule(m_kernel)) { - ScheduleOnInterrupt(); + if (CanSchedule(kernel)) { + ScheduleOnInterrupt(kernel); } } void KScheduler::DisableScheduling(KernelCore& kernel) { ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() >= 0); - GetCurrentThread(kernel).DisableDispatch(); + GetCurrentThread(kernel).DisableDispatch(kernel); } void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduling) { @@ -71,12 +69,12 @@ void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduli return; } - scheduler->RescheduleOtherCores(cores_needing_scheduling); + scheduler->RescheduleOtherCores(kernel, cores_needing_scheduling); if (GetCurrentThread(kernel).GetDisableDispatchCount() > 1) { - GetCurrentThread(kernel).EnableDispatch(); + GetCurrentThread(kernel).EnableDispatch(kernel); } else { - scheduler->RescheduleCurrentCore(); + scheduler->RescheduleCurrentCore(kernel); } } @@ -85,10 +83,10 @@ void KScheduler::RescheduleCurrentHLEThread(KernelCore& kernel) { ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); // Ensure dummy threads that are waiting block. - GetCurrentThread(kernel).DummyThreadBeginWait(); + GetCurrentThread(kernel).DummyThreadBeginWait(kernel); ASSERT(GetCurrentThread(kernel).GetState() != ThreadState::Waiting); - GetCurrentThread(kernel).EnableDispatch(); + GetCurrentThread(kernel).EnableDispatch(kernel); } u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) { @@ -99,55 +97,55 @@ u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) { } } -void KScheduler::Schedule() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); - ASSERT(m_core_id == GetCurrentCoreId(m_kernel)); +void KScheduler::Schedule(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); + ASSERT(m_core_id == GetCurrentCoreId(kernel)); - ScheduleImpl(); + ScheduleImpl(kernel); } -void KScheduler::ScheduleOnInterrupt() { - GetCurrentThread(m_kernel).DisableDispatch(); - Schedule(); - GetCurrentThread(m_kernel).EnableDispatch(); +void KScheduler::ScheduleOnInterrupt(KernelCore& kernel) { + GetCurrentThread(kernel).DisableDispatch(kernel); + Schedule(kernel); + GetCurrentThread(kernel).EnableDispatch(kernel); } -void KScheduler::PreemptSingleCore() { - GetCurrentThread(m_kernel).DisableDispatch(); +void KScheduler::PreemptSingleCore(KernelCore& kernel) { + GetCurrentThread(kernel).DisableDispatch(kernel); - auto* thread = GetCurrentThreadPointer(m_kernel); - auto& previous_scheduler = m_kernel.Scheduler(thread->GetCurrentCore()); - previous_scheduler.Unload(thread); + auto* thread = GetCurrentThreadPointer(kernel); + auto& previous_scheduler = kernel.Scheduler(thread->GetCurrentCore()); + previous_scheduler.Unload(kernel, thread); Common::Fiber::YieldTo(thread->GetHostContext(), *m_switch_fiber); - GetCurrentThread(m_kernel).EnableDispatch(); + GetCurrentThread(kernel).EnableDispatch(kernel); } -void KScheduler::RescheduleCurrentCore() { - ASSERT(!m_kernel.IsPhantomModeForSingleCore()); - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); +void KScheduler::RescheduleCurrentCore(KernelCore& kernel) { + ASSERT(!kernel.IsPhantomModeForSingleCore()); + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); - GetCurrentThread(m_kernel).EnableDispatch(); + GetCurrentThread(kernel).EnableDispatch(kernel); if (m_state.needs_scheduling.load()) { // Disable interrupts, and then check again if rescheduling is needed. // KScopedInterruptDisable intr_disable; - m_kernel.CurrentScheduler()->RescheduleCurrentCoreImpl(); + kernel.CurrentScheduler()->RescheduleCurrentCoreImpl(kernel); } } -void KScheduler::RescheduleCurrentCoreImpl() { +void KScheduler::RescheduleCurrentCoreImpl(KernelCore& kernel) { // Check that scheduling is needed. if (m_state.needs_scheduling.load()) [[likely]] { - GetCurrentThread(m_kernel).DisableDispatch(); - Schedule(); - GetCurrentThread(m_kernel).EnableDispatch(); + GetCurrentThread(kernel).DisableDispatch(kernel); + Schedule(kernel); + GetCurrentThread(kernel).EnableDispatch(kernel); } } -void KScheduler::Initialize(KThread* main_thread, KThread* idle_thread, s32 core_id) { +void KScheduler::Initialize(KernelCore& kernel, KThread* main_thread, KThread* idle_thread, s32 core_id) { // Set core ID/idle thread/interrupt task manager. m_core_id = core_id; m_idle_thread = idle_thread; @@ -156,39 +154,39 @@ void KScheduler::Initialize(KThread* main_thread, KThread* idle_thread, s32 core // Insert the main thread into the priority queue. // { - // KScopedSchedulerLock lk{m_kernel}; - // GetPriorityQueue(m_kernel).PushBack(GetCurrentThreadPointer(m_kernel)); - // SetSchedulerUpdateNeeded(m_kernel); + // KScopedSchedulerLock lk{kernel}; + // GetPriorityQueue(kernel).PushBack(GetCurrentThreadPointer(kernel)); + // SetSchedulerUpdateNeeded(kernel); // } // Bind interrupt handler. // kernel.GetInterruptManager().BindHandler( - // GetSchedulerInterruptHandler(m_kernel), KInterruptName::Scheduler, m_core_id, + // GetSchedulerInterruptHandler(kernel), KInterruptName::Scheduler, m_core_id, // KInterruptController::PriorityLevel::Scheduler, false, false); // Set the current thread. m_current_thread = main_thread; } -void KScheduler::Activate() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); +void KScheduler::Activate(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); // m_state.should_count_idle = KTargetSystem::IsDebugMode(); m_is_active = true; - RescheduleCurrentCore(); + RescheduleCurrentCore(kernel); } -void KScheduler::OnThreadStart() { - GetCurrentThread(m_kernel).EnableDispatch(); +void KScheduler::OnThreadStart(KernelCore& kernel) { + GetCurrentThread(kernel).EnableDispatch(kernel); } -u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { +u64 KScheduler::UpdateHighestPriorityThread(KernelCore& kernel, KThread* highest_thread) { if (KThread* prev_highest_thread = m_state.highest_priority_thread; prev_highest_thread != highest_thread) [[likely]] { if (prev_highest_thread != nullptr) [[likely]] { IncrementScheduledCount(prev_highest_thread); prev_highest_thread->SetLastScheduledTick( - m_kernel.System().CoreTiming().GetClockTicks()); + kernel.System().CoreTiming().GetClockTicks()); } if (m_state.should_count_idle) { if (highest_thread != nullptr) [[likely]] { @@ -245,8 +243,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { } top_threads[core_id] = top_thread; - cores_needing_scheduling |= - kernel.Scheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); + cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); } // Idle cores are bad. We're going to try to migrate threads to each idle core in turn. @@ -274,8 +271,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { suggested->SetActiveCore(core_id); priority_queue.ChangeCore(suggested_core, suggested); top_threads[core_id] = suggested; - cores_needing_scheduling |= - kernel.Scheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); + cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); break; } @@ -298,17 +294,13 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { // The candidate core can run some other thread! We'll migrate its current // top thread to us. top_threads[candidate_core] = next_on_candidate_core; - cores_needing_scheduling |= - kernel.Scheduler(candidate_core) - .UpdateHighestPriorityThread(top_threads[candidate_core]); + cores_needing_scheduling |= kernel.Scheduler(candidate_core).UpdateHighestPriorityThread(kernel, top_threads[candidate_core]); // Perform the migration. suggested->SetActiveCore(core_id); priority_queue.ChangeCore(candidate_core, suggested); top_threads[core_id] = suggested; - cores_needing_scheduling |= - kernel.Scheduler(core_id).UpdateHighestPriorityThread( - top_threads[core_id]); + cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); break; } } @@ -319,21 +311,21 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { } // HACK: any waiting dummy threads can wake up now. - kernel.GlobalSchedulerContext().WakeupWaitingDummyThreads(); + kernel.GlobalSchedulerContext().WakeupWaitingDummyThreads(kernel); // HACK: if we are a dummy thread, and we need to go sleep, indicate // that for when the lock is released. KThread* const cur_thread = GetCurrentThreadPointer(kernel); if (cur_thread->IsDummyThread() && cur_thread->GetState() != ThreadState::Runnable) { - cur_thread->RequestDummyThreadWait(); + cur_thread->RequestDummyThreadWait(kernel); } return cores_needing_scheduling; } -void KScheduler::SwitchThread(KThread* next_thread) { - KProcess* const cur_process = GetCurrentProcessPointer(m_kernel); - KThread* const cur_thread = GetCurrentThreadPointer(m_kernel); +void KScheduler::SwitchThread(KernelCore& kernel, KThread* next_thread) { + KProcess* const cur_process = GetCurrentProcessPointer(kernel); + KThread* const cur_thread = GetCurrentThreadPointer(kernel); // We never want to schedule a null thread, so use the idle thread if we don't have a next. if (next_thread == nullptr) { @@ -355,7 +347,7 @@ void KScheduler::SwitchThread(KThread* next_thread) { // Update the CPU time tracking variables. const s64 prev_tick = m_last_context_switch_time; - const s64 cur_tick = m_kernel.System().CoreTiming().GetClockTicks(); + const s64 cur_tick = kernel.System().CoreTiming().GetClockTicks(); const s64 tick_diff = cur_tick - prev_tick; cur_thread->AddCpuTime(m_core_id, tick_diff); if (cur_process != nullptr) { @@ -379,23 +371,23 @@ void KScheduler::SwitchThread(KThread* next_thread) { // } // Set the new thread. - SetCurrentThread(m_kernel, next_thread); + SetCurrentThread(kernel, next_thread); m_current_thread = next_thread; // Set the new Thread Local region. // cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress())); // Update the thread's cpu time differential in TLS, if relevant. - next_thread->UpdateTlsThreadCpuTime(cur_tick); + next_thread->UpdateTlsThreadCpuTime(kernel, cur_tick); } -void KScheduler::ScheduleImpl() { +void KScheduler::ScheduleImpl(KernelCore& kernel) { // First, clear the needs scheduling bool. m_state.needs_scheduling.store(false, std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_seq_cst); // Load the appropriate thread pointers for scheduling. - KThread* const cur_thread{GetCurrentThreadPointer(m_kernel)}; + KThread* const cur_thread{GetCurrentThreadPointer(kernel)}; KThread* highest_priority_thread{m_state.highest_priority_thread}; // Check whether there are runnable interrupt tasks. @@ -423,7 +415,7 @@ void KScheduler::ScheduleImpl() { // Returning from ScheduleImpl occurs after this thread has been scheduled again. } -void KScheduler::ScheduleImplFiber() { +void KScheduler::ScheduleImplFiber(KernelCore& kernel) { KThread* const cur_thread{m_switch_cur_thread}; KThread* highest_priority_thread{m_switch_highest_priority_thread}; @@ -437,7 +429,7 @@ void KScheduler::ScheduleImplFiber() { m_switch_from_schedule = false; // Save the original thread context. - Unload(cur_thread); + Unload(kernel, cur_thread); // The current thread's context has been entirely taken care of. // Now we want to loop until we successfully switch the thread context. @@ -468,7 +460,7 @@ void KScheduler::ScheduleImplFiber() { // It's time to switch the thread. // Switch to the highest priority thread. - SwitchThread(highest_priority_thread); + SwitchThread(kernel, highest_priority_thread); // Check if we need scheduling. If we do, then we can't complete the switch and should // retry. @@ -493,14 +485,14 @@ void KScheduler::ScheduleImplFiber() { } // Reload the guest thread context. - Reload(highest_priority_thread); + Reload(kernel, highest_priority_thread); // Reload the host thread. Common::Fiber::YieldTo(m_switch_fiber, *highest_priority_thread->m_host_context); } -void KScheduler::Unload(KThread* thread) { - m_kernel.PhysicalCore(m_core_id).SaveContext(thread); +void KScheduler::Unload(KernelCore& kernel, KThread* thread) { + kernel.PhysicalCore(m_core_id).SaveContext(thread); // Check if the thread is terminated by checking the DPC flags. if ((thread->GetStackParameters().dpc_flags & static_cast<u32>(DpcFlag::Terminated)) == 0) { @@ -509,8 +501,8 @@ void KScheduler::Unload(KThread* thread) { } } -void KScheduler::Reload(KThread* thread) { - m_kernel.PhysicalCore(m_core_id).LoadContext(thread); +void KScheduler::Reload(KernelCore& kernel, KThread* thread) { + kernel.PhysicalCore(m_core_id).LoadContext(thread); } void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) { @@ -877,9 +869,9 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) { } } -void KScheduler::RescheduleOtherCores(u64 cores_needing_scheduling) { +void KScheduler::RescheduleOtherCores(KernelCore& kernel, u64 cores_needing_scheduling) { if (const u64 core_mask = cores_needing_scheduling & ~(1ULL << m_core_id); core_mask != 0) { - RescheduleCores(m_kernel, core_mask); + RescheduleCores(kernel, core_mask); } } diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index d85a0c0408..5a896fd899 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -41,15 +44,15 @@ public: explicit KScheduler(KernelCore& kernel); ~KScheduler(); - void Initialize(KThread* main_thread, KThread* idle_thread, s32 core_id); - void Activate(); - void OnThreadStart(); - void Unload(KThread* thread); - void Reload(KThread* thread); + void Initialize(KernelCore& kernel, KThread* main_thread, KThread* idle_thread, s32 core_id); + void Activate(KernelCore& kernel); + void OnThreadStart(KernelCore& kernel); + void Unload(KernelCore& kernel, KThread* thread); + void Reload(KernelCore& kernel, KThread* thread); - void SetInterruptTaskRunnable(); - void RequestScheduleOnInterrupt(); - void PreemptSingleCore(); + void SetInterruptTaskRunnable(KernelCore& kernel); + void RequestScheduleOnInterrupt(KernelCore& kernel); + void PreemptSingleCore(KernelCore& kernel); u64 GetIdleCount() { return m_state.idle_count; @@ -122,18 +125,18 @@ private: static void RescheduleCurrentHLEThread(KernelCore& kernel); // Instanced private API. - void ScheduleImpl(); - void ScheduleImplFiber(); - void SwitchThread(KThread* next_thread); + void ScheduleImpl(KernelCore& kernel); + void ScheduleImplFiber(KernelCore& kernel); + void SwitchThread(KernelCore& kernel, KThread* next_thread); - void Schedule(); - void ScheduleOnInterrupt(); + void Schedule(KernelCore& kernel); + void ScheduleOnInterrupt(KernelCore& kernel); - void RescheduleOtherCores(u64 cores_needing_scheduling); - void RescheduleCurrentCore(); - void RescheduleCurrentCoreImpl(); + void RescheduleOtherCores(KernelCore& kernel, u64 cores_needing_scheduling); + void RescheduleCurrentCore(KernelCore& kernel); + void RescheduleCurrentCoreImpl(KernelCore& kernel); - u64 UpdateHighestPriorityThread(KThread* thread); + u64 UpdateHighestPriorityThread(KernelCore& kernel, KThread* thread); private: friend class KScopedDisableDispatch; @@ -149,14 +152,12 @@ private: KInterruptTaskManager* interrupt_task_manager{nullptr}; }; - KernelCore& m_kernel; SchedulingState m_state; bool m_is_active{false}; s32 m_core_id{0}; s64 m_last_context_switch_time{0}; KThread* m_idle_thread{nullptr}; std::atomic<KThread*> m_current_thread{nullptr}; - std::shared_ptr<Common::Fiber> m_switch_fiber{}; KThread* m_switch_cur_thread{}; KThread* m_switch_highest_priority_thread{}; diff --git a/src/core/hle/kernel/k_scoped_resource_reservation.h b/src/core/hle/kernel/k_scoped_resource_reservation.h index 2cc464612a..4fc66af725 100644 --- a/src/core/hle/kernel/k_scoped_resource_reservation.h +++ b/src/core/hle/kernel/k_scoped_resource_reservation.h @@ -1,3 +1,6 @@ +// 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 @@ -11,34 +14,42 @@ namespace Kernel { class KScopedResourceReservation { public: - explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v, s64 timeout) - : m_limit(l), m_value(v), m_resource(r) { + explicit KScopedResourceReservation(KernelCore& kernel, KResourceLimit* l, LimitableResource r, s64 v, s64 timeout) + : m_kernel{kernel} + , m_limit(l) + , m_value(v) + , m_resource(r) + { if (m_limit && m_value) { - m_succeeded = m_limit->Reserve(m_resource, m_value, timeout); + m_succeeded = m_limit->Reserve(kernel, m_resource, m_value, timeout); } else { m_succeeded = true; } } - explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v = 1) - : m_limit(l), m_value(v), m_resource(r) { + explicit KScopedResourceReservation(KernelCore& kernel, KResourceLimit* l, LimitableResource r, s64 v = 1) + : m_kernel{kernel} + , m_limit(l) + , m_value(v) + , m_resource(r) + { if (m_limit && m_value) { - m_succeeded = m_limit->Reserve(m_resource, m_value); + m_succeeded = m_limit->Reserve(kernel, m_resource, m_value); } else { m_succeeded = true; } } - explicit KScopedResourceReservation(const KProcess* p, LimitableResource r, s64 v, s64 t) - : KScopedResourceReservation(p->GetResourceLimit(), r, v, t) {} + explicit KScopedResourceReservation(KernelCore& kernel, const KProcess* p, LimitableResource r, s64 v, s64 t) + : KScopedResourceReservation(kernel, p->GetResourceLimit(), r, v, t) {} - explicit KScopedResourceReservation(const KProcess* p, LimitableResource r, s64 v = 1) - : KScopedResourceReservation(p->GetResourceLimit(), r, v) {} + explicit KScopedResourceReservation(KernelCore& kernel, const KProcess* p, LimitableResource r, s64 v = 1) + : KScopedResourceReservation(kernel, p->GetResourceLimit(), r, v) {} ~KScopedResourceReservation() noexcept { if (m_limit && m_value && m_succeeded) { // Resource was not committed, release the reservation. - m_limit->Release(m_resource, m_value); + m_limit->Release(m_kernel, m_resource, m_value); } } @@ -52,6 +63,7 @@ public: } private: + KernelCore& m_kernel; KResourceLimit* m_limit{}; s64 m_value{}; LimitableResource m_resource{}; diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp index bb6632f58e..dad6ef0678 100644 --- a/src/core/hle/kernel/k_server_port.cpp +++ b/src/core/hle/kernel/k_server_port.cpp @@ -1,3 +1,6 @@ +// 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 @@ -15,18 +18,18 @@ namespace Kernel { KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} KServerPort::~KServerPort() = default; -void KServerPort::Initialize(KPort* parent) { +void KServerPort::Initialize(KernelCore& kernel, KPort* parent) { // Set member variables. m_parent = parent; } -bool KServerPort::IsLight() const { +bool KServerPort::IsLight(KernelCore& kernel) const { return this->GetParent()->IsLight(); } -void KServerPort::CleanupSessions() { +void KServerPort::CleanupSessions(KernelCore& kernel) { // Ensure our preconditions are met. - if (this->IsLight()) { + if (this->IsLight(kernel)) { ASSERT(m_session_list.empty()); } else { ASSERT(m_light_session_list.empty()); @@ -37,7 +40,7 @@ void KServerPort::CleanupSessions() { // Get the last session in the list. KServerSession* session = nullptr; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (!m_session_list.empty()) { session = std::addressof(m_session_list.front()); m_session_list.pop_front(); @@ -46,7 +49,7 @@ void KServerPort::CleanupSessions() { // Close the session. if (session != nullptr) { - session->Close(); + session->Close(kernel); } else { break; } @@ -57,7 +60,7 @@ void KServerPort::CleanupSessions() { // Get the last session in the list. KLightServerSession* session = nullptr; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (!m_light_session_list.empty()) { session = std::addressof(m_light_session_list.front()); m_light_session_list.pop_front(); @@ -66,60 +69,60 @@ void KServerPort::CleanupSessions() { // Close the session. if (session != nullptr) { - session->Close(); + session->Close(kernel); } else { break; } } } -void KServerPort::Destroy() { +void KServerPort::Destroy(KernelCore& kernel) { // Note with our parent that we're closed. - m_parent->OnServerClosed(); + m_parent->OnServerClosed(kernel); // Perform necessary cleanup of our session lists. - this->CleanupSessions(); + this->CleanupSessions(kernel); // Close our reference to our parent. - m_parent->Close(); + m_parent->Close(kernel); } -bool KServerPort::IsSignaled() const { - if (this->IsLight()) { +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(KServerSession* session) { - ASSERT(!this->IsLight()); +void KServerPort::EnqueueSession(KernelCore& kernel, KServerSession* session) { + ASSERT(!this->IsLight(kernel)); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Add the session to our queue. m_session_list.push_back(*session); if (m_session_list.size() == 1) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } -void KServerPort::EnqueueSession(KLightServerSession* session) { - ASSERT(this->IsLight()); +void KServerPort::EnqueueSession(KernelCore& kernel, KLightServerSession* session) { + ASSERT(this->IsLight(kernel)); - KScopedSchedulerLock sl{m_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(); + this->NotifyAvailable(kernel); } } -KServerSession* KServerPort::AcceptSession() { - ASSERT(!this->IsLight()); +KServerSession* KServerPort::AcceptSession(KernelCore& kernel) { + ASSERT(!this->IsLight(kernel)); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Return the first session in the list. if (m_session_list.empty()) { @@ -131,10 +134,10 @@ KServerSession* KServerPort::AcceptSession() { return session; } -KLightServerSession* KServerPort::AcceptLightSession() { - ASSERT(this->IsLight()); +KLightServerSession* KServerPort::AcceptLightSession(KernelCore& kernel) { + ASSERT(this->IsLight(kernel)); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Return the first session in the list. if (m_light_session_list.empty()) { diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h index 72fdb6734a..5996a3a3ee 100644 --- a/src/core/hle/kernel/k_server_port.h +++ b/src/core/hle/kernel/k_server_port.h @@ -1,3 +1,6 @@ +// 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 @@ -26,29 +29,29 @@ public: explicit KServerPort(KernelCore& kernel); ~KServerPort() override; - void Initialize(KPort* parent); + void Initialize(KernelCore& kernel, KPort* parent); - void EnqueueSession(KServerSession* session); - void EnqueueSession(KLightServerSession* session); + void EnqueueSession(KernelCore& kernel, KServerSession* session); + void EnqueueSession(KernelCore& kernel, KLightServerSession* session); - KServerSession* AcceptSession(); - KLightServerSession* AcceptLightSession(); + KServerSession* AcceptSession(KernelCore& kernel); + KLightServerSession* AcceptLightSession(KernelCore& kernel); const KPort* GetParent() const { return m_parent; } - bool IsLight() const; + bool IsLight(KernelCore& kernel) const; // Overridden virtual functions. - void Destroy() override; - bool IsSignaled() const override; + void Destroy(KernelCore& kernel) override; + bool IsSignaled(KernelCore& kernel) const override; private: using SessionList = Common::IntrusiveListBaseTraits<KServerSession>::ListType; using LightSessionList = Common::IntrusiveListBaseTraits<KLightServerSession>::ListType; - void CleanupSessions(); + void CleanupSessions(KernelCore& kernel); SessionList m_session_list{}; LightSessionList m_light_session_list{}; diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 4c91235ac9..e3cfe6b6c2 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -159,7 +159,7 @@ private: }; template <bool MoveHandleAllowed> -Result ProcessMessageSpecialData(s32& offset, KProcess& dst_process, KProcess& src_process, +Result ProcessMessageSpecialData(KernelCore& kernel, s32& offset, KProcess& dst_process, KProcess& src_process, KThread& src_thread, const MessageBuffer& dst_msg, const MessageBuffer& src_msg, const MessageBuffer::SpecialHeader& src_special_header) { @@ -185,10 +185,9 @@ Result ProcessMessageSpecialData(s32& offset, KProcess& dst_process, KProcess& s // If we're in a success state, try to move the handle to the new table. if (R_SUCCEEDED(result) && src_handle != Svc::InvalidHandle) { KScopedAutoObject obj = - src_handle_table.GetObjectForIpc(src_handle, std::addressof(src_thread)); + src_handle_table.GetObjectForIpc(kernel, src_handle, std::addressof(src_thread)); if (obj.IsNotNull()) { - Result add_result = - dst_handle_table.Add(std::addressof(dst_handle), obj.GetPointerUnsafe()); + Result add_result = dst_handle_table.Add(kernel, std::addressof(dst_handle), obj.GetPointerUnsafe()); if (R_FAILED(add_result)) { result = add_result; dst_handle = Svc::InvalidHandle; @@ -213,12 +212,10 @@ Result ProcessMessageSpecialData(s32& offset, KProcess& dst_process, KProcess& s if (src_handle != Svc::InvalidHandle) { if (R_SUCCEEDED(result)) { KScopedAutoObject obj = - src_handle_table.GetObjectForIpcWithoutPseudoHandle(src_handle); + src_handle_table.GetObjectForIpcWithoutPseudoHandle(kernel, src_handle); if (obj.IsNotNull()) { - Result add_result = dst_handle_table.Add(std::addressof(dst_handle), - obj.GetPointerUnsafe()); - - src_handle_table.Remove(src_handle); + Result add_result = dst_handle_table.Add(kernel, std::addressof(dst_handle), obj.GetPointerUnsafe()); + src_handle_table.Remove(kernel, src_handle); if (R_FAILED(add_result)) { result = add_result; @@ -228,7 +225,7 @@ Result ProcessMessageSpecialData(s32& offset, KProcess& dst_process, KProcess& s result = ResultInvalidHandle; } } else { - src_handle_table.Remove(src_handle); + src_handle_table.Remove(kernel, src_handle); } } @@ -336,7 +333,7 @@ constexpr Result GetMapAliasTestStateAndAttributeMask(KMemoryState& out_state, R_SUCCEED(); } -void CleanupSpecialData(KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buffer_size) { +void CleanupSpecialData(KernelCore& kernel, KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buffer_size) { // Parse the message. const MessageBuffer dst_msg(dst_msg_ptr, dst_buffer_size); const MessageBuffer::MessageHeader dst_header(dst_msg); @@ -363,15 +360,14 @@ void CleanupSpecialData(KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buff const Handle handle = dst_msg.GetHandle(offset); if (handle != Svc::InvalidHandle) { - dst_handle_table.Remove(handle); + dst_handle_table.Remove(kernel, handle); } offset = dst_msg.SetHandle(offset, Svc::InvalidHandle); } } -Result CleanupServerHandles(KernelCore& kernel, uint64_t message, size_t buffer_size, - KPhysicalAddress message_paddr) { +Result CleanupServerHandles(KernelCore& kernel, uint64_t message, size_t buffer_size, KPhysicalAddress message_paddr) { // Server is assumed to be current thread. KThread& thread = GetCurrentThread(kernel); @@ -410,7 +406,7 @@ Result CleanupServerHandles(KernelCore& kernel, uint64_t message, size_t buffer_ // Close the handles. for (auto i = 0; i < special_header.GetMoveHandleCount(); ++i) { - handle_table.Remove(msg.GetHandle(offset)); + handle_table.Remove(kernel, msg.GetHandle(offset)); offset += static_cast<int>(sizeof(Svc::Handle) / sizeof(u32)); } } @@ -558,7 +554,7 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m recv_list_broken = false; // Set the server process for the request. - request->SetServerProcess(std::addressof(dst_process)); + request->SetServerProcess(kernel, std::addressof(dst_process)); // Determine the message buffers. u32 *dst_msg_ptr, *src_msg_ptr; @@ -639,7 +635,7 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m // Cleanup special data. if (src_header.GetHasSpecialHeader()) { - CleanupSpecialData(dst_process, dst_msg_ptr, dst_buffer_size); + CleanupSpecialData(kernel, dst_process, dst_msg_ptr, dst_buffer_size); } // Cleanup the header if the receive list isn't broken. @@ -661,7 +657,7 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m }; // Process special data. - R_TRY(ProcessMessageSpecialData<false>(offset, dst_process, src_process, src_thread, + R_TRY(ProcessMessageSpecialData<false>(kernel, offset, dst_process, src_process, src_thread, dst_msg, src_msg, src_special_header)); } @@ -922,7 +918,7 @@ Result SendMessage(KernelCore& kernel, uint64_t src_message_buffer, size_t src_b // Cleanup special data. if (processed_special_data) { if (src_header.GetHasSpecialHeader()) { - CleanupSpecialData(dst_process, dst_msg_ptr, dst_buffer_size); + CleanupSpecialData(kernel, dst_process, dst_msg_ptr, dst_buffer_size); } } else { CleanupServerHandles(kernel, src_user ? src_message_buffer : 0, src_buffer_size, @@ -987,7 +983,7 @@ Result SendMessage(KernelCore& kernel, uint64_t src_message_buffer, size_t src_b ASSERT(GetCurrentThreadPointer(kernel) == std::addressof(src_thread)); processed_special_data = true; if (src_header.GetHasSpecialHeader()) { - R_TRY(ProcessMessageSpecialData<true>(offset, dst_process, src_process, src_thread, + R_TRY(ProcessMessageSpecialData<true>(kernel, offset, dst_process, src_process, src_thread, dst_msg, src_msg, src_special_header)); } @@ -1080,19 +1076,17 @@ void ReplyAsyncError(KProcess* to_process, uint64_t to_msg_buf, size_t to_msg_bu } // namespace KServerSession::KServerSession(KernelCore& kernel) - : KSynchronizationObject{kernel}, m_lock{m_kernel} {} + : KSynchronizationObject{kernel}, m_lock{kernel} {} KServerSession::~KServerSession() = default; -void KServerSession::Destroy() { - m_parent->OnServerClosed(); - - this->CleanupRequests(); - - m_parent->Close(); +void KServerSession::Destroy(KernelCore& kernel) { + m_parent->OnServerClosed(kernel); + this->CleanupRequests(kernel); + m_parent->Close(kernel); } -Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server_buffer_size, +Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, std::shared_ptr<Service::HLERequestContext>* out_context, std::weak_ptr<Service::SessionRequestManager> manager) { @@ -1104,7 +1098,7 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server KThread* client_thread; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Ensure that we can service the request. R_UNLESS(!m_parent->IsClientClosed(), ResultSessionClosed); @@ -1124,11 +1118,11 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server R_UNLESS(client_thread != nullptr, ResultSessionClosed); // Open the client thread. - client_thread->Open(); + client_thread->Open(kernel); } SCOPE_EXIT { - client_thread->Close(); + client_thread->Close(kernel); }; // Set the request as our current. @@ -1150,13 +1144,13 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()}; u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(client_message))}; *out_context = - std::make_shared<Service::HLERequestContext>(m_kernel, memory, this, client_thread); + std::make_shared<Service::HLERequestContext>(kernel, memory, this, client_thread); (*out_context)->SetSessionRequestManager(manager); (*out_context)->PopulateFromIncomingCommandBuffer(cmd_buf); // We succeeded. R_SUCCEED(); } else { - result = ReceiveMessage(m_kernel, recv_list_broken, server_message, server_buffer_size, + result = ReceiveMessage(kernel, recv_list_broken, server_message, server_buffer_size, server_message_paddr, *client_thread, client_message, client_buffer_size, this, request); } @@ -1168,11 +1162,11 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server // Clear the current request. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); ASSERT(m_current_request == request); m_current_request = nullptr; if (!m_request_list.empty()) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } @@ -1180,7 +1174,7 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server { // After we reply, close our reference to the request. SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Get the event to check whether the request is async. @@ -1199,13 +1193,13 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server client_pt.UnlockForIpcUserBuffer(client_message, client_buffer_size); // Signal the event. - event->Signal(); + event->Signal(kernel); } else { // End the client thread's wait. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (!client_thread->IsTerminationRequested()) { - client_thread->EndWait(result_for_client); + client_thread->EndWait(kernel, result_for_client); } } } @@ -1221,7 +1215,7 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server R_RETURN(result); } -Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buffer_size, +Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, bool is_hle) { // Lock the session. KScopedLightLock lk{m_lock}; @@ -1229,7 +1223,7 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff // Get the request. KSessionRequest* request; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Get the current request. request = m_current_request; @@ -1238,13 +1232,13 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff // Clear the current request, since we're processing it. m_current_request = nullptr; if (!m_request_list.empty()) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } // Close reference to the request once we're done processing it. SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Extract relevant information from the request. @@ -1263,7 +1257,7 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff // HLE servers write directly to a pointer to the thread command buffer. Therefore // the reply has already been written in this case. } else { - result = SendMessage(m_kernel, server_message, server_buffer_size, server_message_paddr, + result = SendMessage(kernel, server_message, server_buffer_size, server_message_paddr, *client_thread, client_message, client_buffer_size, this, request); } } else if (!is_hle) { @@ -1275,7 +1269,7 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff (client_process != nullptr) ? std::addressof(client_process->GetPageTable()) : nullptr; // Cleanup server handles. - result = CleanupServerHandles(m_kernel, server_message, server_buffer_size, + result = CleanupServerHandles(kernel, server_message, server_buffer_size, server_message_paddr); // Cleanup mappings. @@ -1313,13 +1307,13 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size); // Signal the event. - event->Signal(); + event->Signal(kernel); } else { // End the client thread's wait. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (!client_thread->IsTerminationRequested()) { - client_thread->EndWait(client_result); + client_thread->EndWait(kernel, client_result); } } } @@ -1327,45 +1321,45 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff R_RETURN(result); } -Result KServerSession::OnRequest(KSessionRequest* request) { +Result KServerSession::OnRequest(KernelCore& kernel, KSessionRequest* request) { // Create the wait queue. - ThreadQueueImplForKServerSessionRequest wait_queue{m_kernel}; + ThreadQueueImplForKServerSessionRequest wait_queue{kernel}; { // Lock the scheduler. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Ensure that we can handle new requests. R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed); // Check that we're not terminating. - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // Get whether we're empty. const bool was_empty = m_request_list.empty(); // Add the request to the list. - request->Open(); + request->Open(kernel); m_request_list.push_back(*request); // If we were empty, signal. if (was_empty) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } // If we have a request event, this is asynchronous, and we don't need to wait. R_SUCCEED_IF(request->GetEvent() != nullptr); // This is a synchronous request, so we should wait for our request to complete. - GetCurrentThread(m_kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); + GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); + GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); } - return GetCurrentThread(m_kernel).GetWaitResult(); + return GetCurrentThread(kernel).GetWaitResult(); } -bool KServerSession::IsSignaled() const { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +bool KServerSession::IsSignaled(KernelCore& kernel) const { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // If the client is closed, we're always signaled. if (m_parent->IsClientClosed()) { @@ -1376,7 +1370,7 @@ bool KServerSession::IsSignaled() const { return !m_request_list.empty() && m_current_request == nullptr; } -void KServerSession::CleanupRequests() { +void KServerSession::CleanupRequests(KernelCore& kernel) { KScopedLightLock lk(m_lock); // Clean up any pending requests. @@ -1384,7 +1378,7 @@ void KServerSession::CleanupRequests() { // Get the next request. KSessionRequest* request = nullptr; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (m_current_request) { // Choose the current request if we have one. @@ -1404,7 +1398,7 @@ void KServerSession::CleanupRequests() { // Close a reference to the request once it's cleaned up. SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Extract relevant information from the request. @@ -1434,20 +1428,20 @@ void KServerSession::CleanupRequests() { client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size); // Signal the event. - event->Signal(); + event->Signal(kernel); } else { // End the client thread's wait. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (!client_thread->IsTerminationRequested()) { - client_thread->EndWait(ResultSessionClosed); + client_thread->EndWait(kernel, ResultSessionClosed); } } } } } -void KServerSession::OnClientClosed() { +void KServerSession::OnClientClosed(KernelCore& kernel) { KScopedLightLock lk{m_lock}; // Handle any pending requests. @@ -1462,12 +1456,12 @@ void KServerSession::OnClientClosed() { // Get the next request. { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (m_current_request != nullptr && m_current_request != prev_request) { // Set the request, open a reference as we process it. request = m_current_request; - request->Open(); + request->Open(kernel); cur_request = true; // Get thread and event for the request. @@ -1503,14 +1497,14 @@ void KServerSession::OnClientClosed() { // Ensure that we close the request when done. SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // If we're terminating, close a reference to the thread and event. if (terminate) { - thread->Close(); + thread->Close(kernel); if (event != nullptr) { - event->Close(); + event->Close(kernel); } } @@ -1534,12 +1528,12 @@ void KServerSession::OnClientClosed() { client_pt.UnlockForIpcUserBuffer(request->GetAddress(), request->GetSize()); // Signal the event. - event->Signal(); + event->Signal(kernel); } } // Notify. - this->NotifyAvailable(ResultSessionClosed); + this->NotifyAvailable(kernel, ResultSessionClosed); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index 2876c231b2..217e7dc7be 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -36,7 +39,7 @@ public: explicit KServerSession(KernelCore& kernel); ~KServerSession() override; - void Destroy() override; + void Destroy(KernelCore& kernel) override; void Initialize(KSession* p) { m_parent = p; @@ -46,29 +49,29 @@ public: return m_parent; } - bool IsSignaled() const override; - void OnClientClosed(); + bool IsSignaled(KernelCore& kernel) const override; + void OnClientClosed(KernelCore& kernel); - Result OnRequest(KSessionRequest* request); - Result SendReply(uintptr_t server_message, uintptr_t server_buffer_size, + Result OnRequest(KernelCore& kernel, KSessionRequest* request); + Result SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, bool is_hle = false); - Result ReceiveRequest(uintptr_t server_message, uintptr_t server_buffer_size, + Result ReceiveRequest(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, std::shared_ptr<Service::HLERequestContext>* out_context = nullptr, std::weak_ptr<Service::SessionRequestManager> manager = {}); - Result SendReplyHLE() { - R_RETURN(this->SendReply(0, 0, 0, true)); + Result SendReplyHLE(KernelCore& kernel) { + R_RETURN(this->SendReply(kernel, 0, 0, 0, true)); } - Result ReceiveRequestHLE(std::shared_ptr<Service::HLERequestContext>* out_context, + Result ReceiveRequestHLE(KernelCore& kernel, std::shared_ptr<Service::HLERequestContext>* out_context, std::weak_ptr<Service::SessionRequestManager> manager) { - R_RETURN(this->ReceiveRequest(0, 0, 0, out_context, manager)); + R_RETURN(this->ReceiveRequest(kernel, 0, 0, 0, out_context, manager)); } private: /// Frees up waiting client sessions when this server session is about to die - void CleanupRequests(); + void CleanupRequests(KernelCore& kernel); /// KSession that owns this KServerSession KSession* m_parent{}; diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp index 4a1f6027ee..58b0d5de67 100644 --- a/src/core/hle/kernel/k_session.cpp +++ b/src/core/hle/kernel/k_session.cpp @@ -1,3 +1,6 @@ +// 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 @@ -13,12 +16,12 @@ KSession::KSession(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel}, m_server{kernel}, m_client{kernel} {} KSession::~KSession() = default; -void KSession::Initialize(KClientPort* client_port, uintptr_t name) { +void KSession::Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_t 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. - this->Open(); + this->Open(kernel); // Create our sub sessions. KAutoObject::Create(std::addressof(m_server)); @@ -33,45 +36,45 @@ void KSession::Initialize(KClientPort* client_port, uintptr_t name) { m_name = name; // Set our owner process. - m_process = GetCurrentProcessPointer(m_kernel); - m_process->Open(); + m_process = GetCurrentProcessPointer(kernel); + m_process->Open(kernel); // Set our port. m_port = client_port; if (m_port != nullptr) { - m_port->Open(); + m_port->Open(kernel); } // Mark initialized. m_initialized = true; } -void KSession::Finalize() { +void KSession::Finalize(KernelCore& kernel) { if (m_port != nullptr) { - m_port->OnSessionFinalized(); - m_port->Close(); + m_port->OnSessionFinalized(kernel); + m_port->Close(kernel); } } -void KSession::OnServerClosed() { +void KSession::OnServerClosed(KernelCore& kernel) { if (this->GetState() == State::Normal) { this->SetState(State::ServerClosed); m_client.OnServerClosed(); } } -void KSession::OnClientClosed() { +void KSession::OnClientClosed(KernelCore& kernel) { if (this->GetState() == State::Normal) { - SetState(State::ClientClosed); - m_server.OnClientClosed(); + this->SetState(State::ClientClosed); + m_server.OnClientClosed(kernel); } } -void KSession::PostDestroy(uintptr_t arg) { +void KSession::PostDestroy(KernelCore& kernel, uintptr_t arg) { // Release the session count resource the owner process holds. KProcess* owner = reinterpret_cast<KProcess*>(arg); - owner->GetResourceLimit()->Release(LimitableResource::SessionCountMax, 1); - owner->Close(); + owner->GetResourceLimit()->Release(kernel, LimitableResource::SessionCountMax, 1); + owner->Close(kernel); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index 3f4dd5989f..0d77bc1fd4 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h @@ -1,3 +1,6 @@ +// 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 @@ -21,8 +24,8 @@ public: explicit KSession(KernelCore& kernel); ~KSession() override; - void Initialize(KClientPort* port, uintptr_t name); - void Finalize() override; + void Initialize(KernelCore& kernel, KClientPort* port, uintptr_t name); + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_initialized; @@ -32,11 +35,9 @@ public: return reinterpret_cast<uintptr_t>(m_process); } - static void PostDestroy(uintptr_t arg); - - void OnServerClosed(); - - void OnClientClosed(); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); + void OnServerClosed(KernelCore& kernel); + void OnClientClosed(KernelCore& kernel); bool IsServerClosed() const { return this->GetState() != State::Normal; @@ -46,8 +47,8 @@ public: return this->GetState() != State::Normal; } - Result OnRequest(KSessionRequest* request) { - R_RETURN(m_server.OnRequest(request)); + Result OnRequest(KernelCore& kernel, KSessionRequest* request) { + R_RETURN(m_server.OnRequest(kernel, request)); } KClientSession& GetClientSession() { diff --git a/src/core/hle/kernel/k_session_request.cpp b/src/core/hle/kernel/k_session_request.cpp index 9a69b4ffc1..25451a3922 100644 --- a/src/core/hle/kernel/k_session_request.cpp +++ b/src/core/hle/kernel/k_session_request.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,7 +21,7 @@ Result KSessionRequest::SessionMappings::PushMap(KProcessAddress client, KProces } else { // Allocate a page for the extra mappings. if (m_mappings == nullptr) { - KPageBuffer* page_buffer = KPageBuffer::Allocate(m_kernel); + KPageBuffer* page_buffer = KPageBuffer::Allocate(kernel); R_UNLESS(page_buffer != nullptr, ResultOutOfMemory); m_mappings = reinterpret_cast<Mapping*>(page_buffer); @@ -54,7 +57,7 @@ Result KSessionRequest::SessionMappings::PushExchange(KProcessAddress client, void KSessionRequest::SessionMappings::Finalize() { if (m_mappings) { - KPageBuffer::Free(m_kernel, reinterpret_cast<KPageBuffer*>(m_mappings)); + KPageBuffer::Free(kernel, reinterpret_cast<KPageBuffer*>(m_mappings)); m_mappings = nullptr; } } diff --git a/src/core/hle/kernel/k_session_request.h b/src/core/hle/kernel/k_session_request.h index 283669e0ac..6665eca56f 100644 --- a/src/core/hle/kernel/k_session_request.h +++ b/src/core/hle/kernel/k_session_request.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -56,7 +59,7 @@ public: }; public: - explicit SessionMappings(KernelCore& kernel) : m_kernel(kernel) {} + explicit SessionMappings(KernelCore& kernel_) : kernel(kernel_) {} void Initialize() {} void Finalize(); @@ -155,7 +158,7 @@ public: } private: - KernelCore& m_kernel; + KernelCore& kernel; std::array<Mapping, NumStaticMappings> m_static_mappings{}; Mapping* m_mappings{}; u8 m_num_send{}; @@ -174,26 +177,26 @@ public: return req; } - void Destroy() override { - this->Finalize(); - KSessionRequest::Free(m_kernel, this); + void Destroy(KernelCore& kernel) override { + this->Finalize(kernel); + KSessionRequest::Free(kernel, this); } - void Initialize(KEvent* event, uintptr_t address, size_t size) { + void Initialize(KernelCore& kernel, KEvent* event, uintptr_t address, size_t size) { m_mappings.Initialize(); - m_thread = GetCurrentThreadPointer(m_kernel); + m_thread = GetCurrentThreadPointer(kernel); m_event = event; m_address = address; m_size = size; - m_thread->Open(); + m_thread->Open(kernel); if (m_event != nullptr) { - m_event->Open(); + m_event->Open(kernel); } } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} KThread* GetThread() const { return m_thread; @@ -211,9 +214,9 @@ public: return m_server; } - void SetServerProcess(KProcess* process) { + void SetServerProcess(KernelCore& kernel, KProcess* process) { m_server = process; - m_server->Open(); + m_server->Open(kernel); } void ClearThread() { @@ -289,17 +292,16 @@ public: private: // NOTE: This is public and virtual in Nintendo's kernel. - void Finalize() override { + void Finalize(KernelCore& kernel) override { m_mappings.Finalize(); - if (m_thread) { - m_thread->Close(); + m_thread->Close(kernel); } if (m_event) { - m_event->Close(); + m_event->Close(kernel); } if (m_server) { - m_server->Close(); + m_server->Close(kernel); } } diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index f713968f68..61f2872560 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,7 +18,7 @@ namespace Kernel { KSharedMemory::KSharedMemory(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} KSharedMemory::~KSharedMemory() = default; -Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* owner_process, +Result KSharedMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory, KProcess* owner_process, Svc::MemoryPermission owner_permission, Svc::MemoryPermission user_permission, std::size_t size) { // Set members. @@ -28,11 +31,10 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* ow const size_t num_pages = Common::DivideUp(size, PageSize); // Get the resource limit. - KResourceLimit* reslimit = m_kernel.GetSystemResourceLimit(); + KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); // Reserve memory for ourselves. - KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemoryMax, - size); + KScopedResourceReservation memory_reservation(kernel, reslimit, LimitableResource::PhysicalMemoryMax, size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate the memory. @@ -40,12 +42,11 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* ow //! HACK: Open continuous mapping from sysmodule pool. auto option = KMemoryManager::EncodeOption(KMemoryManager::Pool::Secure, KMemoryManager::Direction::FromBack); - m_physical_address = m_kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, option); + m_physical_address = kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, option); R_UNLESS(m_physical_address != 0, ResultOutOfMemory); //! Insert the result into our page group. - m_page_group.emplace(m_kernel, - std::addressof(m_kernel.GetSystemSystemResource().GetBlockInfoManager())); + m_page_group.emplace(kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager())); m_page_group->AddBlock(m_physical_address, num_pages); // Commit our reservation. @@ -53,7 +54,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* ow // Set our resource limit. m_resource_limit = reslimit; - m_resource_limit->Open(); + m_resource_limit->Open(kernel); // Mark initialized. m_is_initialized = true; @@ -66,14 +67,14 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* ow R_SUCCEED(); } -void KSharedMemory::Finalize() { +void KSharedMemory::Finalize(KernelCore& kernel) { // Close and finalize the page group. - m_page_group->Close(); + m_page_group->Close(kernel); m_page_group->Finalize(); // Release the memory reservation. - m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, m_size); - m_resource_limit->Close(); + m_resource_limit->Release(kernel, LimitableResource::PhysicalMemoryMax, m_size); + m_resource_limit->Close(kernel); } Result KSharedMemory::Map(KProcess& target_process, KProcessAddress address, std::size_t map_size, diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 54b23d7ac2..3aede457c9 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,7 +29,7 @@ public: explicit KSharedMemory(KernelCore& kernel); ~KSharedMemory() override; - Result Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, + Result Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory_, KProcess* owner_process_, Svc::MemoryPermission owner_permission_, Svc::MemoryPermission user_permission_, std::size_t size_); @@ -66,12 +69,12 @@ public: return m_device_memory->GetPointer<u8>(m_physical_address + offset); } - void Finalize() override; + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_is_initialized; } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} private: Core::DeviceMemory* m_device_memory{}; diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index 3e5b735b1e..221cab655f 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -1,3 +1,6 @@ +// 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 @@ -18,12 +21,10 @@ namespace { class ThreadQueueImplForKSynchronizationObjectWait final : public KThreadQueueWithoutEndWait { public: - ThreadQueueImplForKSynchronizationObjectWait(KernelCore& kernel, KSynchronizationObject** o, - KSynchronizationObject::ThreadListNode* n, s32 c) + ThreadQueueImplForKSynchronizationObjectWait(KernelCore& kernel, KSynchronizationObject** o, KSynchronizationObject::ThreadListNode* n, s32 c) : KThreadQueueWithoutEndWait(kernel), m_objects(o), m_nodes(n), m_count(c) {} - void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, - Result wait_result) override { + void NotifyAvailable(KernelCore& kernel, KThread* waiting_thread, KSynchronizationObject* signaled_object, Result wait_result) override { // Determine the sync index, and unlink all nodes. s32 sync_index = -1; for (auto i = 0; i < m_count; ++i) { @@ -43,10 +44,10 @@ public: waiting_thread->ClearCancellable(); // Invoke the base end wait handler. - KThreadQueue::EndWait(waiting_thread, wait_result); + KThreadQueue::EndWait(kernel, waiting_thread, wait_result); } - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove all nodes from our list. for (auto i = 0; i < m_count; ++i) { m_objects[i]->UnlinkNode(std::addressof(m_nodes[i])); @@ -56,7 +57,7 @@ public: waiting_thread->ClearCancellable(); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } private: @@ -67,9 +68,9 @@ private: } // namespace -void KSynchronizationObject::Finalize() { +void KSynchronizationObject::Finalize(KernelCore& kernel) { this->OnFinalizeSynchronizationObject(); - KAutoObject::Finalize(); + KAutoObject::Finalize(kernel); } Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, @@ -98,7 +99,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, for (auto i = 0; i < num_objects; ++i) { ASSERT(objects[i] != nullptr); - if (objects[i]->IsSignaled()) { + if (objects[i]->IsSignaled(kernel)) { *out_index = i; slp.CancelSleep(); R_THROW(ResultSuccess); @@ -134,7 +135,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, // Wait for an object to be signaled. wait_queue.SetHardwareTimer(timer); - thread->BeginWait(std::addressof(wait_queue)); + thread->BeginWait(kernel, std::addressof(wait_queue)); thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); } @@ -149,26 +150,26 @@ KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : KAutoObject KSynchronizationObject::~KSynchronizationObject() = default; -void KSynchronizationObject::NotifyAvailable(Result result) { - KScopedSchedulerLock sl(m_kernel); +void KSynchronizationObject::NotifyAvailable(KernelCore& kernel, Result result) { + KScopedSchedulerLock sl(kernel); // If we're not signaled, we've nothing to notify. - if (!this->IsSignaled()) { + if (!this->IsSignaled(kernel)) { return; } // Iterate over each thread. for (auto* cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) { - cur_node->thread->NotifyAvailable(this, result); + cur_node->thread->NotifyAvailable(kernel, this, result); } } -std::vector<KThread*> KSynchronizationObject::GetWaitingThreadsForDebugging() const { +std::vector<KThread*> KSynchronizationObject::GetWaitingThreadsForDebugging(KernelCore& kernel) const { std::vector<KThread*> threads; // If debugging, dump the list of waiters. { - KScopedSchedulerLock lock(m_kernel); + KScopedSchedulerLock lock(kernel); for (auto* cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) { threads.emplace_back(cur_node->thread); } diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index d55a2673df..4c54a4d2cb 100644 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h @@ -1,3 +1,6 @@ +// 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 @@ -24,14 +27,13 @@ public: KThread* thread{}; }; - static Result Wait(KernelCore& kernel, s32* out_index, KSynchronizationObject** objects, - const s32 num_objects, s64 timeout); + static Result Wait(KernelCore& kernel, s32* out_index, KSynchronizationObject** objects, const s32 num_objects, s64 timeout); - void Finalize() override; + void Finalize(KernelCore& kernel) override; - virtual bool IsSignaled() const = 0; + virtual bool IsSignaled(KernelCore& kernel) const = 0; - std::vector<KThread*> GetWaitingThreadsForDebugging() const; + std::vector<KThread*> GetWaitingThreadsForDebugging(KernelCore& kernel) const; void LinkNode(ThreadListNode* node_) { // Link the node to the list. @@ -71,9 +73,9 @@ protected: virtual void OnFinalizeSynchronizationObject() {} - void NotifyAvailable(Result result); - void NotifyAvailable() { - return this->NotifyAvailable(ResultSuccess); + void NotifyAvailable(KernelCore& kernel, Result result); + void NotifyAvailable(KernelCore& kernel) { + return this->NotifyAvailable(kernel, ResultSuccess); } private: diff --git a/src/core/hle/kernel/k_system_resource.cpp b/src/core/hle/kernel/k_system_resource.cpp index b51941faf4..fb664eb57a 100644 --- a/src/core/hle/kernel/k_system_resource.cpp +++ b/src/core/hle/kernel/k_system_resource.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,8 +10,7 @@ namespace Kernel { -Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_limit, - KMemoryManager::Pool pool) { +Result KSecureSystemResource::Initialize(KernelCore& kernel, size_t size, KResourceLimit* resource_limit, KMemoryManager::Pool pool) { // Set members. m_resource_limit = resource_limit; m_resource_size = size; @@ -18,18 +20,17 @@ Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_l const size_t secure_size = this->CalculateRequiredSecureMemorySize(); // Reserve memory for our secure resource. - KScopedResourceReservation memory_reservation( - m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, secure_size); + KScopedResourceReservation memory_reservation(kernel, m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, secure_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate secure memory. - R_TRY(KSystemControl::AllocateSecureMemory(m_kernel, std::addressof(m_resource_address), + R_TRY(KSystemControl::AllocateSecureMemory(kernel, std::addressof(m_resource_address), m_resource_size, static_cast<u32>(m_resource_pool))); ASSERT(m_resource_address != 0); // Ensure we clean up the secure memory, if we fail past this point. ON_RESULT_FAILURE { - KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size, + KSystemControl::FreeSecureMemory(kernel, m_resource_address, m_resource_size, static_cast<u32>(m_resource_pool)); }; @@ -40,9 +41,9 @@ Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_l // Get resource pointer. KPhysicalAddress resource_paddr = - KPageTable::GetHeapPhysicalAddress(m_kernel, m_resource_address); + KPageTable::GetHeapPhysicalAddress(kernel, m_resource_address); auto* resource = - m_kernel.System().DeviceMemory().GetPointer<KPageTableManager::RefCount>(resource_paddr); + kernel.System().DeviceMemory().GetPointer<KPageTableManager::RefCount>(resource_paddr); // Initialize slab heaps. m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size, @@ -66,7 +67,7 @@ Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_l memory_reservation.Commit(); // Open reference to our resource limit. - m_resource_limit->Open(); + m_resource_limit->Open(kernel); // Set ourselves as initialized. m_is_initialized = true; @@ -74,26 +75,25 @@ Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_l R_SUCCEED(); } -void KSecureSystemResource::Finalize() { +void KSecureSystemResource::Finalize(KernelCore& kernel) { // Check that we have no outstanding allocations. ASSERT(m_memory_block_slab_manager.GetUsed() == 0); ASSERT(m_block_info_manager.GetUsed() == 0); ASSERT(m_page_table_manager.GetUsed() == 0); // Free our secure memory. - KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size, + KSystemControl::FreeSecureMemory(kernel, m_resource_address, m_resource_size, static_cast<u32>(m_resource_pool)); // Release the memory reservation. - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, this->CalculateRequiredSecureMemorySize()); // Close reference to our resource limit. - m_resource_limit->Close(); + m_resource_limit->Close(kernel); } -size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, - KMemoryManager::Pool pool) { +size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, KMemoryManager::Pool pool) { return KSystemControl::CalculateRequiredSecureMemorySize(size, static_cast<u32>(pool)); } diff --git a/src/core/hle/kernel/k_system_resource.h b/src/core/hle/kernel/k_system_resource.h index 6ea4821858..c0362497f9 100644 --- a/src/core/hle/kernel/k_system_resource.h +++ b/src/core/hle/kernel/k_system_resource.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,7 +32,7 @@ protected: } public: - virtual void Destroy() override { + virtual void Destroy(KernelCore& kernel) override { UNREACHABLE_MSG("KSystemResource::Destroy() was called"); } @@ -93,13 +96,13 @@ public: this->SetSecureResource(); } - Result Initialize(size_t size, KResourceLimit* resource_limit, KMemoryManager::Pool pool); - void Finalize(); + Result Initialize(KernelCore& kernel, size_t size, KResourceLimit* resource_limit, KMemoryManager::Pool pool); + void Finalize(KernelCore& kernel); bool IsInitialized() const { return m_is_initialized; } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} size_t CalculateRequiredSecureMemorySize() const { return CalculateRequiredSecureMemorySize(m_resource_size, m_resource_pool); diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 0af315d726..b499bd4073 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -95,12 +95,12 @@ namespace Kernel { explicit ThreadQueueImplForKThreadSetProperty(KernelCore& kernel, KThread::WaiterList* wl) : KThreadQueue(kernel), m_wait_list(wl) {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread from the wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } private: @@ -113,7 +113,7 @@ namespace Kernel { : KAutoObjectWithSlabHeapAndContainer{kernel}, m_activity_pause_lock{kernel} {} KThread::~KThread() = default; - Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, + Result KThread::Initialize(KernelCore& kernel, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner, ThreadType type) { // Assert parameters are valid. ASSERT((type == ThreadType::Main) || (type == ThreadType::Dummy) || @@ -225,12 +225,12 @@ namespace Kernel { if (owner != nullptr) { // Setup the TLS, if needed. if (type == ThreadType::User) { - R_TRY(owner->CreateThreadLocalRegion(std::addressof(m_tls_address))); + R_TRY(owner->CreateThreadLocalRegion(kernel, std::addressof(m_tls_address))); owner->GetMemory().ZeroBlock(m_tls_address, Svc::ThreadLocalRegionSize); } m_parent = owner; - m_parent->Open(); + m_parent->Open(kernel); } // Initialize thread context. @@ -247,28 +247,28 @@ namespace Kernel { this->SetInExceptionHandler(); // Set thread ID. - m_thread_id = m_kernel.CreateNewThreadID(); + m_thread_id = kernel.CreateNewThreadID(); // We initialized! m_initialized = true; // Register ourselves with our parent process. if (m_parent != nullptr) { - m_parent->RegisterThread(this); + m_parent->RegisterThread(kernel, this); if (m_parent->IsSuspended()) { - RequestSuspend(SuspendType::Process); + RequestSuspend(kernel, SuspendType::Process); } } R_SUCCEED(); } - Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, + Result KThread::InitializeThread(KernelCore& kernel, KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess* owner, ThreadType type, std::function<void()>&& init_func) { // Initialize the thread. - R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); + R_TRY(thread->Initialize(kernel, func, arg, user_stack_top, prio, core, owner, type)); // Initialize emulation parameters. thread->m_host_context = std::make_shared<Common::Fiber>(std::move(init_func)); @@ -276,9 +276,9 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::InitializeDummyThread(KThread* thread, KProcess* owner) { + Result KThread::InitializeDummyThread(Core::System& system, KThread* thread, KProcess* owner) { // Initialize the thread. - R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy)); + R_TRY(thread->Initialize(system.Kernel(), {}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy)); // Initialize emulation parameters. thread->m_stack_parameters.disable_count = 0; @@ -287,37 +287,27 @@ namespace Kernel { } Result KThread::InitializeMainThread(Core::System& system, KThread* thread, s32 virt_core) { - R_RETURN(InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, - ThreadType::Main, system.GetCpuManager().GetGuestActivateFunc())); + R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, system.GetCpuManager().GetGuestActivateFunc(system.Kernel()))); } Result KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { - R_RETURN(InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, - ThreadType::Main, system.GetCpuManager().GetIdleThreadStartFunc())); + R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, system.GetCpuManager().GetIdleThreadStartFunc(system.Kernel()))); } - Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, - KThreadFunction func, uintptr_t arg, s32 virt_core) { - R_RETURN(InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, - ThreadType::HighPriority, - system.GetCpuManager().GetShutdownThreadStartFunc())); + Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, KThreadFunction func, uintptr_t arg, s32 virt_core) { + R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, system.GetCpuManager().GetShutdownThreadStartFunc(system.Kernel()))); } - Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, - uintptr_t arg, KProcessAddress user_stack_top, s32 prio, - s32 virt_core, KProcess* owner) { + Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner) { system.Kernel().GlobalSchedulerContext().AddThread(thread); - R_RETURN(InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, - ThreadType::User, system.GetCpuManager().GetGuestThreadFunc())); + R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, user_stack_top, prio, virt_core, owner, ThreadType::User, system.GetCpuManager().GetGuestThreadFunc(system.Kernel()))); } - Result KThread::InitializeServiceThread(Core::System& system, KThread* thread, - std::function<void()>&& func, s32 prio, s32 virt_core, - KProcess* owner) { + Result KThread::InitializeServiceThread(Core::System& system, KThread* thread, std::function<void()>&& func, s32 prio, s32 virt_core, KProcess* owner) { system.Kernel().GlobalSchedulerContext().AddThread(thread); std::function<void()> func2{[&system, func_{std::move(func)}] { // Similar to UserModeThreadStarter. - system.Kernel().CurrentScheduler()->OnThreadStart(); + system.Kernel().CurrentScheduler()->OnThreadStart(system.Kernel()); // Run the guest function. func_(); @@ -326,35 +316,35 @@ namespace Kernel { Svc::ExitThread(system); }}; - R_RETURN(InitializeThread(thread, {}, {}, {}, prio, virt_core, owner, ThreadType::HighPriority, + R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, prio, virt_core, owner, ThreadType::HighPriority, std::move(func2))); } - void KThread::PostDestroy(uintptr_t arg) { + void KThread::PostDestroy(KernelCore& kernel, uintptr_t arg) { KProcess* owner = reinterpret_cast<KProcess*>(arg & ~1ULL); const bool resource_limit_release_hint = (arg & 1); const s64 hint_value = (resource_limit_release_hint ? 0 : 1); if (owner != nullptr) { - owner->GetResourceLimit()->Release(LimitableResource::ThreadCountMax, 1, hint_value); - owner->Close(); + owner->GetResourceLimit()->Release(kernel, LimitableResource::ThreadCountMax, 1, hint_value); + owner->Close(kernel); } } - void KThread::Finalize() { + void KThread::Finalize(KernelCore& kernel) { // If the thread has an owner process, unregister it. if (m_parent != nullptr) { - m_parent->UnregisterThread(this); + m_parent->UnregisterThread(kernel, this); } // If the thread has a local region, delete it. if (m_tls_address != 0) { - ASSERT(m_parent->DeleteThreadLocalRegion(m_tls_address).IsSuccess()); + ASSERT(m_parent->DeleteThreadLocalRegion(kernel, m_tls_address).IsSuccess()); } // Release any waiters. { ASSERT(m_waiting_lock_info == nullptr); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Check that we have no kernel waiters. ASSERT(m_num_kernel_waiters == 0); @@ -378,14 +368,14 @@ namespace Kernel { } // Cancel the thread's wait. - waiter->CancelWait(ResultInvalidState, true); + waiter->CancelWait(kernel, ResultInvalidState, true); } // Remove the held lock from our list. it = m_held_lock_info_list.erase(it); // Free the lock info. - LockWithPriorityInheritanceInfo::Free(m_kernel, lock_info); + LockWithPriorityInheritanceInfo::Free(kernel, lock_info); } } @@ -393,35 +383,35 @@ namespace Kernel { m_host_context.reset(); // Perform inherited finalization. - KSynchronizationObject::Finalize(); + KSynchronizationObject::Finalize(kernel); } - bool KThread::IsSignaled() const { + bool KThread::IsSignaled(KernelCore& kernel) const { return m_signaled; } - void KThread::OnTimer() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::OnTimer(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // If we're waiting, cancel the wait. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->CancelWait(this, ResultTimedOut, false); + m_wait_queue->CancelWait(kernel, this, ResultTimedOut, false); } } - void KThread::StartTermination() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::StartTermination(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Release user exception and unpin, if relevant. if (m_parent != nullptr) { - m_parent->ReleaseUserException(this); - if (m_parent->GetPinnedThread(GetCurrentCoreId(m_kernel)) == this) { - m_parent->UnpinCurrentThread(); + m_parent->ReleaseUserException(kernel, this); + if (m_parent->GetPinnedThread(GetCurrentCoreId(kernel)) == this) { + m_parent->UnpinCurrentThread(kernel); } } // Set state to terminated. - this->SetState(ThreadState::Terminated); + this->SetState(kernel, ThreadState::Terminated); // Clear the thread's status as running in parent. if (m_parent != nullptr) { @@ -429,41 +419,41 @@ namespace Kernel { } // Clear previous thread in KScheduler. - KScheduler::ClearPreviousThread(m_kernel, this); + KScheduler::ClearPreviousThread(kernel, this); // Register terminated dpc flag. this->RegisterDpc(DpcFlag::Terminated); } - void KThread::FinishTermination() { + void KThread::FinishTermination(KernelCore& kernel) { // Ensure that the thread is not executing on any core. if (m_parent != nullptr) { - for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) { + for (std::size_t i = 0; i < std::size_t(Core::Hardware::NUM_CPU_CORES); ++i) { KThread* core_thread{}; do { - core_thread = m_kernel.Scheduler(i).GetSchedulerCurrentThread(); + core_thread = kernel.Scheduler(i).GetSchedulerCurrentThread(); } while (core_thread == this); } } // Acquire the scheduler lock. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Signal. m_signaled = true; - KSynchronizationObject::NotifyAvailable(); + KSynchronizationObject::NotifyAvailable(kernel); // Close the thread. - this->Close(); + this->Close(kernel); } - void KThread::DoWorkerTaskImpl() { + void KThread::DoWorkerTaskImpl(KernelCore& kernel) { // Finish the termination that was begun by Exit(). - this->FinishTermination(); + this->FinishTermination(kernel); } - void KThread::Pin(s32 current_core) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::Pin(KernelCore& kernel, s32 current_core) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Set ourselves as pinned. GetStackParameters().is_pinned = true; @@ -487,7 +477,7 @@ namespace Kernel { if (active_core != current_core || m_physical_affinity_mask.GetAffinityMask() != m_original_physical_affinity_mask.GetAffinityMask()) { - KScheduler::OnThreadAffinityMaskChanged(m_kernel, this, + KScheduler::OnThreadAffinityMaskChanged(kernel, this, m_original_physical_affinity_mask, active_core); } } @@ -499,15 +489,15 @@ namespace Kernel { static_cast<u32>(ThreadState::SuspendShift))); // Update our state. - this->UpdateState(); + this->UpdateState(kernel); } // TODO(bunnei): Update our SVC access permissions. ASSERT(m_parent != nullptr); } - void KThread::Unpin() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::Unpin(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Set ourselves as unpinned. this->GetStackParameters().is_pinned = false; @@ -535,7 +525,7 @@ namespace Kernel { std::countl_zero(m_physical_affinity_mask.GetAffinityMask()))); } } - KScheduler::OnThreadAffinityMaskChanged(m_kernel, this, old_mask, active_core); + KScheduler::OnThreadAffinityMaskChanged(kernel, this, old_mask, active_core); } } @@ -546,20 +536,19 @@ namespace Kernel { static_cast<u32>(ThreadState::SuspendShift))); // Update our state. - this->UpdateState(); + this->UpdateState(kernel); } // TODO(bunnei): Update our SVC access permissions. ASSERT(m_parent != nullptr); // Resume any threads that began waiting on us while we were pinned. - for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); - it = m_pinned_waiter_list.erase(it)) { - it->EndWait(ResultSuccess); - } + for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); it = m_pinned_waiter_list.erase(it)) { + it->EndWait(kernel, ResultSuccess); + } } - u16 KThread::GetUserDisableCount() const { + u16 KThread::GetUserDisableCount(KernelCore& kernel) const { if (!this->IsUserThread()) { // We only emulate TLS for user threads return {}; @@ -569,7 +558,7 @@ namespace Kernel { return memory.Read16(m_tls_address + offsetof(ThreadLocalRegion, disable_count)); } - void KThread::SetInterruptFlag() { + void KThread::SetInterruptFlag(KernelCore& kernel) { if (!this->IsUserThread()) { // We only emulate TLS for user threads return; @@ -579,7 +568,7 @@ namespace Kernel { memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1); } - void KThread::ClearInterruptFlag() { + void KThread::ClearInterruptFlag(KernelCore& kernel) { if (!this->IsUserThread()) { // We only emulate TLS for user threads return; @@ -589,7 +578,7 @@ namespace Kernel { memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0); } - void KThread::UpdateTlsThreadCpuTime(s64 switch_tick) { + void KThread::UpdateTlsThreadCpuTime(KernelCore& kernel, s64 switch_tick) { if (!this->IsUserThread()) { return; } @@ -602,8 +591,8 @@ namespace Kernel { memory.Write64(m_tls_address + offsetof(ThreadLocalRegion, thread_cpu_time), static_cast<u64>(value)); } - Result KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) { - KScopedSchedulerLock sl{m_kernel}; + Result KThread::GetCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask) { + KScopedSchedulerLock sl{kernel}; // Get the virtual mask. *out_ideal_core = m_virtual_ideal_core_id; @@ -612,8 +601,8 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask) { - KScopedSchedulerLock sl{m_kernel}; + Result KThread::GetPhysicalCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask) { + KScopedSchedulerLock sl{kernel}; ASSERT(m_num_core_migration_disables >= 0); // Select between core mask and original core mask. @@ -628,7 +617,7 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { + Result KThread::SetCoreMask(KernelCore& kernel, s32 core_id, u64 v_affinity_mask) { ASSERT(m_parent != nullptr); ASSERT(v_affinity_mask != 0); KScopedLightLock lk(m_activity_pause_lock); @@ -636,7 +625,7 @@ namespace Kernel { // Set the core mask. u64 p_affinity_mask = 0; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); ASSERT(m_num_core_migration_disables >= 0); // If we're updating, set our ideal virtual core. @@ -682,7 +671,7 @@ namespace Kernel { std::countl_zero(m_physical_affinity_mask.GetAffinityMask())); SetActiveCore(new_core); } - KScheduler::OnThreadAffinityMaskChanged(m_kernel, this, old_mask, active_core); + KScheduler::OnThreadAffinityMaskChanged(kernel, this, old_mask, active_core); } } else { // Otherwise, we edit the original affinity for restoration later. @@ -692,12 +681,12 @@ namespace Kernel { } // Update the pinned waiter list. - ThreadQueueImplForKThreadSetProperty wait_queue(m_kernel, std::addressof(m_pinned_waiter_list)); + ThreadQueueImplForKThreadSetProperty wait_queue(kernel, std::addressof(m_pinned_waiter_list)); { bool retry_update{}; do { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Don't do any further management if our termination has been requested. R_SUCCEED_IF(this->IsTerminationRequested()); @@ -710,7 +699,7 @@ namespace Kernel { s32 thread_core; for (thread_core = 0; thread_core < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++thread_core) { - if (m_kernel.Scheduler(thread_core).GetSchedulerCurrentThread() == this) { + if (kernel.Scheduler(thread_core).GetSchedulerCurrentThread() == this) { thread_is_current = true; break; } @@ -722,12 +711,12 @@ namespace Kernel { // If the thread is pinned, we want to wait until it's not pinned. if (this->GetStackParameters().is_pinned) { // Verify that the current thread isn't terminating. - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // Wait until the thread isn't pinned any more. - m_pinned_waiter_list.push_back(GetCurrentThread(m_kernel)); - GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); + m_pinned_waiter_list.push_back(GetCurrentThread(kernel)); + GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); } else { // If the thread isn't pinned, release the scheduler lock and retry until it's // not current. @@ -740,25 +729,25 @@ namespace Kernel { R_SUCCEED(); } - void KThread::SetBasePriority(s32 value) { + void KThread::SetBasePriority(KernelCore& kernel, s32 value) { ASSERT(Svc::HighestThreadPriority <= value && value <= Svc::LowestThreadPriority); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Change our base priority. m_base_priority = value; // Perform a priority restoration. - RestorePriority(m_kernel, this); + RestorePriority(kernel, this); } - KThread* KThread::GetLockOwner() const { + KThread* KThread::GetLockOwner(KernelCore& kernel) const { return m_waiting_lock_info != nullptr ? m_waiting_lock_info->GetOwner() : nullptr; } - void KThread::IncreaseBasePriority(s32 priority) { + void KThread::IncreaseBasePriority(KernelCore& kernel, s32 priority) { ASSERT(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority); - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(!this->GetStackParameters().is_pinned); // Set our base priority. @@ -766,47 +755,47 @@ namespace Kernel { m_base_priority = priority; // Perform a priority restoration. - RestorePriority(m_kernel, this); + RestorePriority(kernel, this); } } - void KThread::RequestSuspend(SuspendType type) { - KScopedSchedulerLock sl{m_kernel}; + void KThread::RequestSuspend(KernelCore& kernel, SuspendType type) { + KScopedSchedulerLock sl{kernel}; // Note the request in our flags. m_suspend_request_flags |= (1U << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type))); // Try to perform the suspend. - this->TrySuspend(); + this->TrySuspend(kernel); } - void KThread::Resume(SuspendType type) { - KScopedSchedulerLock sl{m_kernel}; + void KThread::Resume(KernelCore& kernel, SuspendType type) { + KScopedSchedulerLock sl{kernel}; // Clear the request in our flags. m_suspend_request_flags &= ~(1U << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type))); // Update our state. - this->UpdateState(); + this->UpdateState(kernel); } - void KThread::WaitCancel() { - KScopedSchedulerLock sl{m_kernel}; + void KThread::WaitCancel(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; // Check if we're waiting and cancellable. if (this->GetState() == ThreadState::Waiting && m_cancellable) { m_wait_cancelled = false; - m_wait_queue->CancelWait(this, ResultCancelled, true); + m_wait_queue->CancelWait(kernel, this, ResultCancelled, true); } else { // Otherwise, note that we cancelled a wait. m_wait_cancelled = true; } } - void KThread::TrySuspend() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::TrySuspend(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(this->IsSuspendRequested()); // Ensure that we have no waiters. @@ -816,11 +805,11 @@ namespace Kernel { ASSERT(this->GetNumKernelWaiters() == 0); // Perform the suspend. - this->UpdateState(); + this->UpdateState(kernel); } - void KThread::UpdateState() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::UpdateState(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Set our suspend flags in state. const ThreadState old_state = m_thread_state.load(std::memory_order_relaxed); @@ -830,37 +819,37 @@ namespace Kernel { // Note the state change in scheduler. if (new_state != old_state) { - KScheduler::OnThreadStateChanged(m_kernel, this, old_state); + KScheduler::OnThreadStateChanged(kernel, this, old_state); } } - void KThread::Continue() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::Continue(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Clear our suspend flags in state. const ThreadState old_state = m_thread_state.load(std::memory_order_relaxed); m_thread_state.store(old_state & ThreadState::Mask, std::memory_order_relaxed); // Note the state change in scheduler. - KScheduler::OnThreadStateChanged(m_kernel, this, old_state); + KScheduler::OnThreadStateChanged(kernel, this, old_state); } - void KThread::CloneFpuStatus() { + void KThread::CloneFpuStatus(KernelCore& kernel) { // We shouldn't reach here when starting kernel threads. ASSERT(this->GetOwnerProcess() != nullptr); - ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(m_kernel)); + ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(kernel)); - m_kernel.CurrentPhysicalCore().CloneFpuStatus(this); + kernel.CurrentPhysicalCore().CloneFpuStatus(this); } - Result KThread::SetActivity(Svc::ThreadActivity activity) { + Result KThread::SetActivity(KernelCore& kernel, Svc::ThreadActivity activity) { // Lock ourselves. KScopedLightLock lk(m_activity_pause_lock); // Set the activity. { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Verify our state. const auto cur_state = this->GetState(); @@ -873,7 +862,7 @@ namespace Kernel { R_UNLESS(!this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Suspend. - this->RequestSuspend(SuspendType::Thread); + this->RequestSuspend(kernel, SuspendType::Thread); } else { ASSERT(activity == Svc::ThreadActivity::Runnable); @@ -881,19 +870,19 @@ namespace Kernel { R_UNLESS(this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Resume. - this->Resume(SuspendType::Thread); + this->Resume(kernel, SuspendType::Thread); } } // If the thread is now paused, update the pinned waiter list. if (activity == Svc::ThreadActivity::Paused) { - ThreadQueueImplForKThreadSetProperty wait_queue(m_kernel, + ThreadQueueImplForKThreadSetProperty wait_queue(kernel, std::addressof(m_pinned_waiter_list)); bool thread_is_current{}; do { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Don't do any further management if our termination has been requested. R_SUCCEED_IF(this->IsTerminationRequested()); @@ -904,17 +893,17 @@ namespace Kernel { // Check whether the thread is pinned. if (this->GetStackParameters().is_pinned) { // Verify that the current thread isn't terminating. - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // Wait until the thread isn't pinned any more. - m_pinned_waiter_list.push_back(GetCurrentThread(m_kernel)); - GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); + m_pinned_waiter_list.push_back(GetCurrentThread(kernel)); + GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); } else { // Check if the thread is currently running. // If it is, we'll need to retry. for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) { - if (m_kernel.Scheduler(i).GetSchedulerCurrentThread() == this) { + if (kernel.Scheduler(i).GetSchedulerCurrentThread() == this) { thread_is_current = true; break; } @@ -926,14 +915,14 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::GetThreadContext3(Svc::ThreadContext* out) { + Result KThread::GetThreadContext3(KernelCore& kernel, Svc::ThreadContext* out) { // Lock ourselves. KScopedLightLock lk{m_activity_pause_lock}; // Get the context. { // Lock the scheduler. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Verify that we're suspended. R_UNLESS(this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); @@ -957,8 +946,8 @@ namespace Kernel { R_SUCCEED(); } - void KThread::AddHeldLock(LockWithPriorityInheritanceInfo* lock_info) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::AddHeldLock(KernelCore& kernel, LockWithPriorityInheritanceInfo* lock_info) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Set ourselves as the lock's owner. lock_info->SetOwner(this); @@ -967,23 +956,21 @@ namespace Kernel { m_held_lock_info_list.push_front(*lock_info); } - KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(KProcessAddress address_key, - bool is_kernel_address_key) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(KernelCore& kernel, KProcessAddress address_key, bool is_kernel_address_key) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Try to find an existing held lock. for (auto& held_lock : m_held_lock_info_list) { - if (held_lock.GetAddressKey() == address_key && - held_lock.GetIsKernelAddressKey() == is_kernel_address_key) { + if (held_lock.GetAddressKey() == address_key && held_lock.GetIsKernelAddressKey() == is_kernel_address_key) { return std::addressof(held_lock); - } + } } return nullptr; } - void KThread::AddWaiterImpl(KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::AddWaiterImpl(KernelCore& kernel, KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(thread->GetConditionVariableTree() == nullptr); // Get the thread's address key. @@ -993,31 +980,31 @@ namespace Kernel { // Keep track of how many kernel waiters we have. if (is_kernel_address_key) { ASSERT((m_num_kernel_waiters++) >= 0); - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } // Get the relevant lock info. - auto* lock_info = this->FindHeldLock(address_key, is_kernel_address_key); + auto* lock_info = this->FindHeldLock(kernel, address_key, is_kernel_address_key); if (lock_info == nullptr) { // Create a new lock for the address key. lock_info = - LockWithPriorityInheritanceInfo::Create(m_kernel, address_key, is_kernel_address_key); + LockWithPriorityInheritanceInfo::Create(kernel, address_key, is_kernel_address_key); // Add the new lock to our list. - this->AddHeldLock(lock_info); + this->AddHeldLock(kernel, lock_info); } // Add the thread as waiter to the lock info. lock_info->AddWaiter(thread); } - void KThread::RemoveWaiterImpl(KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::RemoveWaiterImpl(KernelCore& kernel, KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Keep track of how many kernel waiters we have. if (thread->GetIsKernelAddressKey()) { ASSERT((m_num_kernel_waiters--) > 0); - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } // Get the info for the lock the thread is waiting on. @@ -1027,7 +1014,7 @@ namespace Kernel { // Remove the waiter. if (lock_info->RemoveWaiter(thread)) { m_held_lock_info_list.erase(m_held_lock_info_list.iterator_to(*lock_info)); - LockWithPriorityInheritanceInfo::Free(m_kernel, lock_info); + LockWithPriorityInheritanceInfo::Free(kernel, lock_info); } } @@ -1048,12 +1035,12 @@ namespace Kernel { } // Get the owner of whatever lock this thread is waiting on. - KThread* const lock_owner = thread->GetLockOwner(); + KThread* const lock_owner = thread->GetLockOwner(kernel); // If the thread is waiting on some lock, remove it as a waiter to prevent violating red // black tree invariants. if (lock_owner != nullptr) { - lock_owner->RemoveWaiterImpl(thread); + lock_owner->RemoveWaiterImpl(kernel, thread); } // Ensure we don't violate condition variable red black tree invariants. @@ -1072,7 +1059,7 @@ namespace Kernel { // If we removed the thread from some lock's waiting list, add it back. if (lock_owner != nullptr) { - lock_owner->AddWaiterImpl(thread); + lock_owner->AddWaiterImpl(kernel, thread); } // Update the scheduler. @@ -1083,32 +1070,30 @@ namespace Kernel { } } - void KThread::AddWaiter(KThread* thread) { - this->AddWaiterImpl(thread); + void KThread::AddWaiter(KernelCore& kernel, KThread* thread) { + this->AddWaiterImpl(kernel, thread); // If the thread has a higher priority than us, we should inherit. if (thread->GetPriority() < this->GetPriority()) { - RestorePriority(m_kernel, this); + RestorePriority(kernel, this); } } - void KThread::RemoveWaiter(KThread* thread) { - this->RemoveWaiterImpl(thread); + void KThread::RemoveWaiter(KernelCore& kernel, KThread* thread) { + this->RemoveWaiterImpl(kernel, thread); // If our priority is the same as the thread's (and we've inherited), we may need to restore to // lower priority. - if (this->GetPriority() == thread->GetPriority() && - this->GetPriority() < this->GetBasePriority()) { - RestorePriority(m_kernel, this); - } + if (this->GetPriority() == thread->GetPriority() && this->GetPriority() < this->GetBasePriority()) { + RestorePriority(kernel, this); + } } - KThread* KThread::RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key, - bool is_kernel_address_key_) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + KThread* KThread::RemoveWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key, bool is_kernel_address_key_) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the relevant lock info. - auto* lock_info = this->FindHeldLock(key, is_kernel_address_key_); + auto* lock_info = this->FindHeldLock(kernel, key, is_kernel_address_key_); if (lock_info == nullptr) { *out_has_waiters = false; return nullptr; @@ -1121,7 +1106,7 @@ namespace Kernel { if (lock_info->GetIsKernelAddressKey()) { m_num_kernel_waiters -= lock_info->GetWaiterCount(); ASSERT(m_num_kernel_waiters >= 0); - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } ASSERT(lock_info->GetWaiterCount() > 0); @@ -1133,13 +1118,13 @@ namespace Kernel { *out_has_waiters = false; // Free the lock info, since it has no waiters. - LockWithPriorityInheritanceInfo::Free(m_kernel, lock_info); + LockWithPriorityInheritanceInfo::Free(kernel, lock_info); } else { // There are additional waiters on the lock. *out_has_waiters = true; // Add the lock to the new owner's held list. - next_lock_owner->AddHeldLock(lock_info); + next_lock_owner->AddHeldLock(kernel, lock_info); // Keep track of any kernel waiters for the new owner. if (lock_info->GetIsKernelAddressKey()) { @@ -1155,7 +1140,7 @@ namespace Kernel { // to lower priority. if (this->GetPriority() == next_lock_owner->GetPriority() && this->GetPriority() < this->GetBasePriority()) { - RestorePriority(m_kernel, this); + RestorePriority(kernel, this); // NOTE: No need to restore priority on the next lock owner, because it was already the // highest priority waiter on the lock. } @@ -1164,91 +1149,91 @@ namespace Kernel { return next_lock_owner; } - Result KThread::Run() { + Result KThread::Run(KernelCore& kernel) { while (true) { - KScopedSchedulerLock lk{m_kernel}; + KScopedSchedulerLock lk{kernel}; // If either this thread or the current thread are requesting termination, note it. R_UNLESS(!this->IsTerminationRequested(), ResultTerminationRequested); - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // Ensure our thread state is correct. R_UNLESS(this->GetState() == ThreadState::Initialized, ResultInvalidState); // If the current thread has been asked to suspend, suspend it and retry. - if (GetCurrentThread(m_kernel).IsSuspended()) { - GetCurrentThread(m_kernel).UpdateState(); + if (GetCurrentThread(kernel).IsSuspended()) { + GetCurrentThread(kernel).UpdateState(kernel); continue; } // If we're not a kernel thread and we've been asked to suspend, suspend ourselves. if (KProcess* owner = this->GetOwnerProcess(); owner != nullptr) { if (this->IsUserThread() && this->IsSuspended()) { - this->UpdateState(); + this->UpdateState(kernel); } - owner->IncrementRunningThreadCount(); + owner->IncrementRunningThreadCount(kernel); } // Open a reference, now that we're running. - this->Open(); + this->Open(kernel); // Set our state and finish. - this->SetState(ThreadState::Runnable); + this->SetState(kernel, ThreadState::Runnable); R_SUCCEED(); } } - void KThread::Exit() { - ASSERT(this == GetCurrentThreadPointer(m_kernel)); + void KThread::Exit(KernelCore& kernel) { + ASSERT(this == GetCurrentThreadPointer(kernel)); // Release the thread resource hint, running thread count from parent. if (m_parent != nullptr) { - m_parent->GetResourceLimit()->Release(Kernel::LimitableResource::ThreadCountMax, 0, 1); + m_parent->GetResourceLimit()->Release(kernel, Kernel::LimitableResource::ThreadCountMax, 0, 1); m_resource_limit_release_hint = true; - m_parent->DecrementRunningThreadCount(); + m_parent->DecrementRunningThreadCount(kernel); } // Perform termination. { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Disallow all suspension. m_suspend_allowed_flags = 0; - this->UpdateState(); + this->UpdateState(kernel); // Disallow all suspension. m_suspend_allowed_flags = 0; // Start termination. - this->StartTermination(); + this->StartTermination(kernel); // Register the thread as a work task. - KWorkerTaskManager::AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, this); + KWorkerTaskManager::AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); } UNREACHABLE_MSG("KThread::Exit() would return"); } - Result KThread::Terminate() { - ASSERT(this != GetCurrentThreadPointer(m_kernel)); + Result KThread::Terminate(KernelCore& kernel) { + ASSERT(this != GetCurrentThreadPointer(kernel)); // Request the thread terminate if it hasn't already. - if (const auto new_state = this->RequestTerminate(); new_state != ThreadState::Terminated) { + if (const auto new_state = this->RequestTerminate(kernel); new_state != ThreadState::Terminated) { // If the thread isn't terminated, wait for it to terminate. s32 index; KSynchronizationObject* objects[] = {this}; - R_TRY(KSynchronizationObject::Wait(m_kernel, std::addressof(index), objects, 1, + R_TRY(KSynchronizationObject::Wait(kernel, std::addressof(index), objects, 1, Svc::WaitInfinite)); } R_SUCCEED(); } - ThreadState KThread::RequestTerminate() { - ASSERT(this != GetCurrentThreadPointer(m_kernel)); + ThreadState KThread::RequestTerminate(KernelCore& kernel) { + ASSERT(this != GetCurrentThreadPointer(kernel)); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Determine if this is the first termination request. const bool first_request = [&]() -> bool { @@ -1270,46 +1255,46 @@ namespace Kernel { // If the thread is pinned, unpin it. if (this->GetStackParameters().is_pinned) { - this->GetOwnerProcess()->UnpinThread(this); + this->GetOwnerProcess()->UnpinThread(kernel, this); } // If the thread is suspended, continue it. if (this->IsSuspended()) { m_suspend_allowed_flags = 0; - this->UpdateState(); + this->UpdateState(kernel); } // Change the thread's priority to be higher than any system thread's. - this->IncreaseBasePriority(TerminatingThreadPriority); + this->IncreaseBasePriority(kernel, TerminatingThreadPriority); // If the thread is runnable, send a termination interrupt to cores it may be running on. if (this->GetState() == ThreadState::Runnable) { // NOTE: We do not mask the "current core", because this code may not actually be // executing from the thread representing the "current core". if (const u64 core_mask = m_physical_affinity_mask.GetAffinityMask(); core_mask != 0) { - Kernel::KInterruptManager::SendInterProcessorInterrupt(m_kernel, core_mask); + Kernel::KInterruptManager::SendInterProcessorInterrupt(kernel, core_mask); } } // Wake up the thread. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->CancelWait(this, ResultTerminationRequested, true); + m_wait_queue->CancelWait(kernel, this, ResultTerminationRequested, true); } } return this->GetState(); } - Result KThread::Sleep(s64 timeout) { - ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); - ASSERT(this == GetCurrentThreadPointer(m_kernel)); + Result KThread::Sleep(KernelCore& kernel, s64 timeout) { + ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + ASSERT(this == GetCurrentThreadPointer(kernel)); ASSERT(timeout > 0); - ThreadQueueImplForKThreadSleep wait_queue(m_kernel); + ThreadQueueImplForKThreadSleep wait_queue(kernel); KHardwareTimer* timer{}; { // Setup the scheduling lock and sleep. - KScopedSchedulerLockAndSleep slp(m_kernel, std::addressof(timer), this, timeout); + KScopedSchedulerLockAndSleep slp(kernel, std::addressof(timer), this, timeout); // Check if the thread should terminate. if (this->IsTerminationRequested()) { @@ -1319,15 +1304,15 @@ namespace Kernel { // Wait for the sleep to end. wait_queue.SetHardwareTimer(timer); - this->BeginWait(std::addressof(wait_queue)); + this->BeginWait(kernel, std::addressof(wait_queue)); this->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); } R_SUCCEED(); } - void KThread::RequestDummyThreadWait() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::RequestDummyThreadWait(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(this->IsDummyThread()); // We will block when the scheduler lock is released. @@ -1335,8 +1320,8 @@ namespace Kernel { m_dummy_thread_runnable = false; } - void KThread::DummyThreadBeginWait() { - if (!this->IsDummyThread() || m_kernel.IsPhantomModeForSingleCore()) { + void KThread::DummyThreadBeginWait(KernelCore& kernel) { + if (!this->IsDummyThread() || kernel.IsPhantomModeForSingleCore()) { // Occurs in single core mode. return; } @@ -1346,8 +1331,8 @@ namespace Kernel { m_dummy_thread_cv.wait(lock, [this] { return m_dummy_thread_runnable; }); } - void KThread::DummyThreadEndWait() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::DummyThreadEndWait(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(this->IsDummyThread()); // Wake up the waiting thread. @@ -1358,28 +1343,26 @@ namespace Kernel { m_dummy_thread_cv.notify_one(); } - void KThread::BeginWait(KThreadQueue* queue) { + void KThread::BeginWait(KernelCore& kernel, KThreadQueue* queue) { // Set our state as waiting. - this->SetState(ThreadState::Waiting); + this->SetState(kernel, ThreadState::Waiting); // Set our wait queue. m_wait_queue = queue; } - void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, Result wait_result) { + void KThread::NotifyAvailable(KernelCore& kernel, KSynchronizationObject* signaled_object, Result wait_result) { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); - + KScopedSchedulerLock sl(kernel); // If we're waiting, notify our queue that we're available. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->NotifyAvailable(this, signaled_object, wait_result); + m_wait_queue->NotifyAvailable(kernel, this, signaled_object, wait_result); } } - void KThread::EndWait(Result wait_result) { + void KThread::EndWait(KernelCore& kernel, Result wait_result) { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); - + KScopedSchedulerLock sl(kernel); // If we're waiting, notify our queue that we're available. if (this->GetState() == ThreadState::Waiting) { if (m_wait_queue == nullptr) { @@ -1388,32 +1371,29 @@ namespace Kernel { return; } - m_wait_queue->EndWait(this, wait_result); + m_wait_queue->EndWait(kernel, this, wait_result); } } - void KThread::CancelWait(Result wait_result, bool cancel_timer_task) { + void KThread::CancelWait(KernelCore& kernel, Result wait_result, bool cancel_timer_task) { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); - + KScopedSchedulerLock sl(kernel); // If we're waiting, notify our queue that we're available. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->CancelWait(this, wait_result, cancel_timer_task); + m_wait_queue->CancelWait(kernel, this, wait_result, cancel_timer_task); } } - void KThread::SetState(ThreadState state) { - KScopedSchedulerLock sl{m_kernel}; - + void KThread::SetState(KernelCore& kernel, ThreadState state) { + KScopedSchedulerLock sl{kernel}; // Clear debugging state this->SetWaitReasonForDebugging({}); - const ThreadState old_state = m_thread_state.load(std::memory_order_relaxed); m_thread_state.store( static_cast<ThreadState>((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)), std::memory_order_relaxed); if (m_thread_state.load(std::memory_order_relaxed) != old_state) { - KScheduler::OnThreadStateChanged(m_kernel, this, old_state); + KScheduler::OnThreadStateChanged(kernel, this, old_state); } } @@ -1459,12 +1439,12 @@ namespace Kernel { auto* scheduler = m_kernel.CurrentScheduler(); if (scheduler && !m_kernel.IsPhantomModeForSingleCore()) { - scheduler->RescheduleCurrentCore(); + scheduler->RescheduleCurrentCore(m_kernel); } else { KScheduler::RescheduleCurrentHLEThread(m_kernel); } } else { - GetCurrentThread(m_kernel).EnableDispatch(); + GetCurrentThread(m_kernel).EnableDispatch(m_kernel); } } }
\ No newline at end of file diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index e79704ce4b..95ba1b4d76 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -181,21 +181,17 @@ public: return m_thread_id; } - void ContinueIfHasKernelWaiters() { + void ContinueIfHasKernelWaiters(KernelCore& kernel) { if (GetNumKernelWaiters() > 0) { - Continue(); + Continue(kernel); } } - void SetBasePriority(s32 value); - - Result Run(); - - void Exit(); - - Result Terminate(); - - ThreadState RequestTerminate(); + void SetBasePriority(KernelCore& kernel, s32 value); + Result Run(KernelCore& kernel); + void Exit(KernelCore& kernel); + Result Terminate(KernelCore& kernel); + ThreadState RequestTerminate(KernelCore& kernel); u32 GetSuspendFlags() const { return m_suspend_allowed_flags & m_suspend_request_flags; @@ -215,15 +211,11 @@ public: return m_suspend_request_flags != 0; } - void RequestSuspend(SuspendType type); - - void Resume(SuspendType type); - - void TrySuspend(); - - void UpdateState(); - - void Continue(); + void RequestSuspend(KernelCore& kernel, SuspendType type); + void Resume(KernelCore& kernel, SuspendType type); + void TrySuspend(KernelCore& kernel); + void UpdateState(KernelCore& kernel); + void Continue(KernelCore& kernel); constexpr void SetSyncedIndex(s32 index) { m_synced_index = index; @@ -262,7 +254,7 @@ public: m_thread_context.tpidr = value; } - void CloneFpuStatus(); + void CloneFpuStatus(KernelCore& kernel); Svc::ThreadContext& GetContext() { return m_thread_context; @@ -282,7 +274,7 @@ public: return m_thread_state.load(std::memory_order_relaxed); } - void SetState(ThreadState state); + void SetState(KernelCore& kernel, ThreadState state); StepState GetStepState() const { return m_step_state; @@ -342,27 +334,27 @@ public: Svc::ArgumentHandleCountMax}; } - u16 GetUserDisableCount() const; - void SetInterruptFlag(); - void ClearInterruptFlag(); + u16 GetUserDisableCount(KernelCore& kernel) const; + void SetInterruptFlag(KernelCore& kernel); + void ClearInterruptFlag(KernelCore& kernel); - void UpdateTlsThreadCpuTime(s64 switch_tick); + void UpdateTlsThreadCpuTime(KernelCore& kernel, s64 switch_tick); - KThread* GetLockOwner() const; + KThread* GetLockOwner(KernelCore& kernel) const; const KAffinityMask& GetAffinityMask() const { return m_physical_affinity_mask; } - Result GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask); + Result GetCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask); - Result GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask); + Result GetPhysicalCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask); - Result SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask); + Result SetCoreMask(KernelCore& kernel, s32 cpu_core_id, u64 v_affinity_mask); - Result SetActivity(Svc::ThreadActivity activity); + Result SetActivity(KernelCore& kernel, Svc::ThreadActivity activity); - Result Sleep(s64 timeout); + Result Sleep(KernelCore& kernel, s64 timeout); s64 GetYieldScheduleCount() const { return m_schedule_count; @@ -372,7 +364,7 @@ public: m_schedule_count = count; } - void WaitCancel(); + void WaitCancel(KernelCore& kernel); bool IsWaitCancelled() const { return m_wait_cancelled; @@ -417,17 +409,17 @@ public: return reinterpret_cast<uintptr_t>(m_parent) | (m_resource_limit_release_hint ? 1 : 0); } - void Finalize() override; + void Finalize(KernelCore& kernel) override; - bool IsSignaled() const override; + bool IsSignaled(KernelCore& kernel) const override; - void OnTimer(); + void OnTimer(KernelCore& kernel); - void DoWorkerTaskImpl(); + void DoWorkerTaskImpl(KernelCore& kernel); - static void PostDestroy(uintptr_t arg); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); - static Result InitializeDummyThread(KThread* thread, KProcess* owner); + static Result InitializeDummyThread(Core::System& system, KThread* thread, KProcess* owner); static Result InitializeMainThread(Core::System& system, KThread* thread, s32 virt_core); @@ -514,19 +506,18 @@ public: return this->GetStackParameters().disable_count; } - void DisableDispatch() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() >= 0); + void DisableDispatch(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() >= 0); this->GetStackParameters().disable_count++; } - void EnableDispatch() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() > 0); + void EnableDispatch(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() > 0); this->GetStackParameters().disable_count--; } - void Pin(s32 current_core); - - void Unpin(); + void Pin(KernelCore& kernel, s32 current_core); + void Unpin(KernelCore& kernel); void SetInExceptionHandler() { this->GetStackParameters().is_in_exception_handler = true; @@ -592,18 +583,18 @@ public: return this->GetThreadType() == ThreadType::Dummy; } - void AddWaiter(KThread* thread); + void AddWaiter(KernelCore& kernel, KThread* thread); - void RemoveWaiter(KThread* thread); + void RemoveWaiter(KernelCore& kernel, KThread* thread); - Result GetThreadContext3(Svc::ThreadContext* out); + Result GetThreadContext3(KernelCore& kernel, Svc::ThreadContext* out); - KThread* RemoveUserWaiterByKey(bool* out_has_waiters, KProcessAddress key) { - return this->RemoveWaiterByKey(out_has_waiters, key, false); + KThread* RemoveUserWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key) { + return this->RemoveWaiterByKey(kernel, out_has_waiters, key, false); } - KThread* RemoveKernelWaiterByKey(bool* out_has_waiters, KProcessAddress key) { - return this->RemoveWaiterByKey(out_has_waiters, key, true); + KThread* RemoveKernelWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key) { + return this->RemoveWaiterByKey(kernel, out_has_waiters, key, true); } KProcessAddress GetAddressKey() const { @@ -641,10 +632,10 @@ public: m_wait_queue = nullptr; } - void BeginWait(KThreadQueue* queue); - void NotifyAvailable(KSynchronizationObject* signaled_object, Result wait_result); - void EndWait(Result wait_result); - void CancelWait(Result wait_result, bool cancel_timer_task); + void BeginWait(KernelCore& kernel, KThreadQueue* queue); + void NotifyAvailable(KernelCore& kernel, KSynchronizationObject* signaled_object, Result wait_result); + void EndWait(KernelCore& kernel, Result wait_result); + void CancelWait(KernelCore& kernel, Result wait_result, bool cancel_timer_task); s32 GetNumKernelWaiters() const { return m_num_kernel_waiters; @@ -662,9 +653,9 @@ public: // therefore will not block on guest kernel synchronization primitives. These methods handle // blocking as needed. - void RequestDummyThreadWait(); - void DummyThreadBeginWait(); - void DummyThreadEndWait(); + void RequestDummyThreadWait(KernelCore& kernel); + void DummyThreadBeginWait(KernelCore& kernel); + void DummyThreadEndWait(KernelCore& kernel); uintptr_t GetArgument() const { return m_argument; @@ -690,8 +681,7 @@ public: } private: - KThread* RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key, - bool is_kernel_address_key); + KThread* RemoveWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key, bool is_kernel_address_key); static constexpr size_t PriorityInheritanceCountMax = 10; union SyncObjectBuffer { @@ -735,19 +725,19 @@ private: } }; - void AddWaiterImpl(KThread* thread); - void RemoveWaiterImpl(KThread* thread); + void AddWaiterImpl(KernelCore& kernel, KThread* thread); + void RemoveWaiterImpl(KernelCore& kernel, KThread* thread); static void RestorePriority(KernelCore& kernel, KThread* thread); - void StartTermination(); - void FinishTermination(); + void StartTermination(KernelCore& kernel); + void FinishTermination(KernelCore& kernel); - void IncreaseBasePriority(s32 priority); + void IncreaseBasePriority(KernelCore& kernel, s32 priority); - Result Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, + Result Initialize(KernelCore& kernel, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner, ThreadType type); - static Result InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, + static Result InitializeThread(KernelCore& kernel, KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess* owner, ThreadType type, std::function<void()>&& init_func); @@ -878,9 +868,8 @@ public: return m_waiting_lock_info; } - void AddHeldLock(LockWithPriorityInheritanceInfo* lock_info); - LockWithPriorityInheritanceInfo* FindHeldLock(KProcessAddress address_key, - bool is_kernel_address_key); + void AddHeldLock(KernelCore& kernel, LockWithPriorityInheritanceInfo* lock_info); + LockWithPriorityInheritanceInfo* FindHeldLock(KernelCore& kernel, KProcessAddress address_key, bool is_kernel_address_key); private: using LockWithPriorityInheritanceInfoList = @@ -996,7 +985,7 @@ public: if (m_kernel.IsShuttingDown()) { return; } - GetCurrentThread(kernel).DisableDispatch(); + GetCurrentThread(kernel).DisableDispatch(kernel); } ~KScopedDisableDispatch(); @@ -1005,8 +994,8 @@ private: KernelCore& m_kernel; }; -inline void KTimerTask::OnTimer() { - static_cast<KThread*>(this)->OnTimer(); +inline void KTimerTask::OnTimer(KernelCore& kernel) { + static_cast<KThread*>(this)->OnTimer(kernel); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_thread_queue.cpp b/src/core/hle/kernel/k_thread_queue.cpp index 61488f4ce6..7c4bfe5a49 100644 --- a/src/core/hle/kernel/k_thread_queue.cpp +++ b/src/core/hle/kernel/k_thread_queue.cpp @@ -1,3 +1,6 @@ +// 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 @@ -7,17 +10,16 @@ namespace Kernel { -void KThreadQueue::NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, - Result wait_result) { +void KThreadQueue::NotifyAvailable(KernelCore& kernel, KThread* waiting_thread, KSynchronizationObject* signaled_object, Result wait_result) { UNREACHABLE(); } -void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) { +void KThreadQueue::EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) { // Set the thread's wait result. waiting_thread->SetWaitResult(wait_result); // Set the thread as runnable. - waiting_thread->SetState(ThreadState::Runnable); + waiting_thread->SetState(kernel, ThreadState::Runnable); // Clear the thread's wait queue. waiting_thread->ClearWaitQueue(); @@ -28,12 +30,12 @@ void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) { } } -void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { +void KThreadQueue::CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { // Set the thread's wait result. waiting_thread->SetWaitResult(wait_result); // Set the thread as runnable. - waiting_thread->SetState(ThreadState::Runnable); + waiting_thread->SetState(kernel, ThreadState::Runnable); // Clear the thread's wait queue. waiting_thread->ClearWaitQueue(); @@ -44,7 +46,7 @@ void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool } } -void KThreadQueueWithoutEndWait::EndWait(KThread* waiting_thread, Result wait_result) { +void KThreadQueueWithoutEndWait::EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) { UNREACHABLE(); } diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index 117af0919a..953bb78ac6 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h @@ -1,3 +1,6 @@ +// 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 @@ -12,28 +15,25 @@ class KHardwareTimer; class KThreadQueue { public: - explicit KThreadQueue(KernelCore& kernel) : m_kernel{kernel}, m_hardware_timer{} {} + explicit KThreadQueue(KernelCore& kernel) : m_hardware_timer{} {} virtual ~KThreadQueue() = default; void SetHardwareTimer(KHardwareTimer* timer) { m_hardware_timer = timer; } - virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, - Result wait_result); - virtual void EndWait(KThread* waiting_thread, Result wait_result); - virtual void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task); + virtual void NotifyAvailable(KernelCore& kernel, KThread* waiting_thread, KSynchronizationObject* signaled_object, Result wait_result); + virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result); + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task); private: - KernelCore& m_kernel; KHardwareTimer* m_hardware_timer{}; }; class KThreadQueueWithoutEndWait : public KThreadQueue { public: explicit KThreadQueueWithoutEndWait(KernelCore& kernel) : KThreadQueue(kernel) {} - - void EndWait(KThread* waiting_thread, Result wait_result) override final; + void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override final; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_timer_task.h b/src/core/hle/kernel/k_timer_task.h index 66f0a5a908..7625c1fee1 100644 --- a/src/core/hle/kernel/k_timer_task.h +++ b/src/core/hle/kernel/k_timer_task.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,6 +10,7 @@ namespace Kernel { +class KernelCore; class KTimerTask : public Common::IntrusiveRedBlackTreeBaseNode<KTimerTask> { public: static constexpr int Compare(const KTimerTask& lhs, const KTimerTask& rhs) { @@ -30,7 +34,7 @@ public: // NOTE: This is virtual in Nintendo's kernel. Prior to 13.0.0, KWaitObject was also a // TimerTask; this is no longer the case. Since this is now KThread exclusive, we have // devirtualized (see inline declaration for this inside k_thread.h). - void OnTimer(); + void OnTimer(KernelCore& kernel); private: // Absolute time in nanoseconds diff --git a/src/core/hle/kernel/k_trace.h b/src/core/hle/kernel/k_trace.h index d61af48303..84dd4134e1 100644 --- a/src/core/hle/kernel/k_trace.h +++ b/src/core/hle/kernel/k_trace.h @@ -1,8 +1,13 @@ +// 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 #pragma once +#include "common/literals.h" + namespace Kernel { using namespace Common::Literals; diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp index 09295e8ad8..a4ef530b5b 100644 --- a/src/core/hle/kernel/k_transfer_memory.cpp +++ b/src/core/hle/kernel/k_transfer_memory.cpp @@ -1,3 +1,6 @@ +// 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 @@ -14,16 +17,15 @@ KTransferMemory::KTransferMemory(KernelCore& kernel) KTransferMemory::~KTransferMemory() = default; -Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size, - Svc::MemoryPermission own_perm) { +Result KTransferMemory::Initialize(KernelCore& kernel, KProcessAddress addr, std::size_t size, Svc::MemoryPermission own_perm) { // Set members. - m_owner = GetCurrentProcessPointer(m_kernel); + m_owner = GetCurrentProcessPointer(kernel); // Get the owner page table. auto& page_table = m_owner->GetPageTable(); // Construct the page group, guarding to make sure our state is valid on exit. - m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager()); + m_page_group.emplace(kernel, page_table.GetBlockInfoManager()); auto pg_guard = SCOPE_GUARD { m_page_group.reset(); }; @@ -33,7 +35,7 @@ Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size, ConvertToKMemoryPermission(own_perm))); // Set remaining tracking members. - m_owner->Open(); + m_owner->Open(kernel); m_owner_perm = own_perm; m_address = addr; m_is_initialized = true; @@ -44,7 +46,7 @@ Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size, R_SUCCEED(); } -void KTransferMemory::Finalize() { +void KTransferMemory::Finalize(KernelCore& kernel) { // Unlock. if (!m_is_mapped) { const size_t size = m_page_group->GetNumPages() * PageSize; @@ -53,17 +55,17 @@ void KTransferMemory::Finalize() { } // Close the page group. - m_page_group->Close(); + m_page_group->Close(kernel); m_page_group->Finalize(); } -void KTransferMemory::PostDestroy(uintptr_t arg) { +void KTransferMemory::PostDestroy(KernelCore& kernel, uintptr_t arg) { KProcess* owner = reinterpret_cast<KProcess*>(arg); - owner->GetResourceLimit()->Release(LimitableResource::TransferMemoryCountMax, 1); - owner->Close(); + owner->GetResourceLimit()->Release(kernel, LimitableResource::TransferMemoryCountMax, 1); + owner->Close(kernel); } -Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPermission map_perm) { +Result KTransferMemory::Map(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission map_perm) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -80,7 +82,7 @@ Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPer const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) ? KMemoryState::Transferred : KMemoryState::SharedTransferred; - R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup( + R_TRY(GetCurrentProcess(kernel).GetPageTable().MapPageGroup( address, *m_page_group, state, KMemoryPermission::UserReadWrite)); // Mark ourselves as mapped. @@ -89,7 +91,7 @@ Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPer R_SUCCEED(); } -Result KTransferMemory::Unmap(KProcessAddress address, size_t size) { +Result KTransferMemory::Unmap(KernelCore& kernel, KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -100,7 +102,7 @@ Result KTransferMemory::Unmap(KProcessAddress address, size_t size) { const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) ? KMemoryState::Transferred : KMemoryState::SharedTransferred; - R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state)); + R_TRY(GetCurrentProcess(kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state)); // Mark ourselves as unmapped. ASSERT(m_is_mapped); diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index 530b452182..0753b4fd6d 100644 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h @@ -1,3 +1,6 @@ +// 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 @@ -30,9 +33,9 @@ public: explicit KTransferMemory(KernelCore& kernel); ~KTransferMemory() override; - Result Initialize(KProcessAddress address, std::size_t size, Svc::MemoryPermission owner_perm); + Result Initialize(KernelCore& kernel, KProcessAddress address, std::size_t size, Svc::MemoryPermission owner_perm); - void Finalize() override; + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_is_initialized; @@ -42,7 +45,7 @@ public: return reinterpret_cast<uintptr_t>(m_owner); } - static void PostDestroy(uintptr_t arg); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); KProcess* GetOwner() const override { return m_owner; @@ -54,8 +57,8 @@ public: size_t GetSize() const; - Result Map(KProcessAddress address, size_t size, Svc::MemoryPermission map_perm); - Result Unmap(KProcessAddress address, size_t size); + Result Map(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission map_perm); + Result Unmap(KernelCore& kernel, KProcessAddress address, size_t size); private: std::optional<KPageGroup> m_page_group{}; diff --git a/src/core/hle/kernel/k_worker_task.h b/src/core/hle/kernel/k_worker_task.h index 9a230c03c4..a4820bc412 100644 --- a/src/core/hle/kernel/k_worker_task.h +++ b/src/core/hle/kernel/k_worker_task.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,8 +13,7 @@ namespace Kernel { class KWorkerTask : public KSynchronizationObject { public: explicit KWorkerTask(KernelCore& kernel); - - void DoWorkerTask(); + void DoWorkerTask(KernelCore& kernel); }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_worker_task_manager.cpp b/src/core/hle/kernel/k_worker_task_manager.cpp index 8ead395911..4427f9859a 100644 --- a/src/core/hle/kernel/k_worker_task_manager.cpp +++ b/src/core/hle/kernel/k_worker_task_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -12,14 +15,14 @@ namespace Kernel { KWorkerTask::KWorkerTask(KernelCore& kernel) : KSynchronizationObject{kernel} {} -void KWorkerTask::DoWorkerTask() { +void KWorkerTask::DoWorkerTask(KernelCore& kernel) { if (auto* const thread = this->DynamicCast<KThread*>(); thread != nullptr) { - return thread->DoWorkerTaskImpl(); + return thread->DoWorkerTaskImpl(kernel); } else { auto* const process = this->DynamicCast<KProcess*>(); ASSERT(process != nullptr); - return process->DoWorkerTaskImpl(); + return process->DoWorkerTaskImpl(kernel); } } @@ -32,9 +35,9 @@ void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTas void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) { KScopedSchedulerLock sl(kernel); - m_waiting_thread.QueueWork([task]() { + m_waiting_thread.QueueWork([&kernel, task]() { // Do the task. - task->DoWorkerTask(); + task->DoWorkerTask(kernel); }); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 5f88fa498f..d25ac37df4 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -121,14 +121,14 @@ struct KernelCore::Impl { void TerminateAllProcesses() { std::scoped_lock lk{process_list_lock}; for (auto& process : process_list) { - process->Terminate(); - process->Close(); + process->Terminate(system.Kernel()); + process->Close(system.Kernel()); process = nullptr; } process_list.clear(); } - void Shutdown() { + void Shutdown(KernelCore& kernel) { is_shutting_down.store(true, std::memory_order_relaxed); SCOPE_EXIT { is_shutting_down.store(false, std::memory_order_relaxed); @@ -137,7 +137,7 @@ struct KernelCore::Impl { CloseServices(); if (application_process) { - application_process->Close(); + application_process->Close(system.Kernel()); application_process = nullptr; } @@ -149,9 +149,9 @@ struct KernelCore::Impl { preemption_event = nullptr; // Cleanup persistent kernel objects - auto CleanupObject = [](KAutoObject* obj) { + auto CleanupObject = [&kernel](KAutoObject* obj) { if (obj) { - obj->Close(); + obj->Close(kernel); obj = nullptr; } }; @@ -163,7 +163,7 @@ struct KernelCore::Impl { for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { if (shutdown_threads[core_id]) { - shutdown_threads[core_id]->Close(); + shutdown_threads[core_id]->Close(kernel); shutdown_threads[core_id] = nullptr; } @@ -178,7 +178,7 @@ struct KernelCore::Impl { std::scoped_lock lk{registered_in_use_objects_lock}; if (registered_in_use_objects.size()) { for (auto& object : registered_in_use_objects) { - object->Close(); + object->Close(kernel); } registered_in_use_objects.clear(); } @@ -226,7 +226,7 @@ struct KernelCore::Impl { ASSERT(Kernel::KThread::InitializeIdleThread(system, idle_thread, core).IsSuccess()); KThread::Register(system.Kernel(), idle_thread); - schedulers[i]->Initialize(main_thread, idle_thread, core); + schedulers[i]->Initialize(system.Kernel(), main_thread, idle_thread, core); } } @@ -247,19 +247,18 @@ struct KernelCore::Impl { ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 1133).IsSuccess()); - system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, kernel_size); + system_resource_limit->Reserve(kernel, LimitableResource::PhysicalMemoryMax, kernel_size); // Reserve secure applet memory, introduced in firmware 5.0.0 constexpr u64 secure_applet_memory_size{4_MiB}; - ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, - secure_applet_memory_size)); + ASSERT(system_resource_limit->Reserve(kernel, LimitableResource::PhysicalMemoryMax, secure_applet_memory_size)); } void InitializePreemption(KernelCore& kernel) { preemption_event = Core::Timing::CreateEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> { { KScopedSchedulerLock lock(kernel); - global_scheduler_context->PreemptThreads(); + global_scheduler_context->PreemptThreads(kernel); } return std::nullopt; }); @@ -350,9 +349,9 @@ struct KernelCore::Impl { object_name_global_data.emplace(kernel); } - void MakeApplicationProcess(KProcess* process) { + void MakeApplicationProcess(KernelCore& kernel, KProcess* process) { application_process = process; - application_process->Open(); + application_process->Open(kernel); } /// Sets the host thread ID for the caller. @@ -374,10 +373,10 @@ struct KernelCore::Impl { // Gets the dummy KThread for the caller, allocating a new one if this is the first time KThread* GetHostDummyThread(ThreadLocalData& t, KThread* existing_thread) { if (t.thread == nullptr) { - auto const initialize{[](KThread* thread) { - ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); + auto const initialize = [this](KThread* thread) { + ASSERT(KThread::InitializeDummyThread(system, thread, nullptr).IsSuccess()); return thread; - }}; + }; t.raw_thread.emplace(system.Kernel()); t.thread = existing_thread ? existing_thread : initialize(&*t.raw_thread); ASSERT(t.thread != nullptr); @@ -418,8 +417,7 @@ struct KernelCore::Impl { return is_shutting_down.load(std::memory_order_relaxed); } - KThread* GetCurrentEmuThread() { - auto& t = tls_data; + KThread* GetCurrentEmuThread(ThreadLocalData& t) { return t.current_thread ? t.current_thread : (t.current_thread = GetHostDummyThread(t, nullptr)); } @@ -742,19 +740,19 @@ struct KernelCore::Impl { time_shared_mem = KSharedMemory::Create(system.Kernel()); hidbus_shared_mem = KSharedMemory::Create(system.Kernel()); - font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + font_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, font_size); KSharedMemory::Register(kernel, font_shared_mem); - irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + irs_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, irs_size); KSharedMemory::Register(kernel, irs_shared_mem); - time_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + time_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, time_size); KSharedMemory::Register(kernel, time_shared_mem); - hidbus_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + hidbus_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, hidbus_size); KSharedMemory::Register(kernel, hidbus_shared_mem); } @@ -852,7 +850,7 @@ void KernelCore::Initialize() { } void KernelCore::Shutdown() { - impl->Shutdown(); + impl->Shutdown(*this); } void KernelCore::CloseServices() { @@ -868,7 +866,7 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() { } void KernelCore::AppendNewProcess(KProcess* process) { - process->Open(); + process->Open(*this); std::scoped_lock lk{impl->process_list_lock}; impl->process_list.push_back(process); @@ -877,12 +875,12 @@ void KernelCore::AppendNewProcess(KProcess* process) { void KernelCore::RemoveProcess(KProcess* process) { std::scoped_lock lk{impl->process_list_lock}; if (std::erase(impl->process_list, process)) { - process->Close(); + process->Close(*this); } } void KernelCore::MakeApplicationProcess(KProcess* process) { - impl->MakeApplicationProcess(process); + impl->MakeApplicationProcess(*this, process); } KProcess* KernelCore::ApplicationProcess() { @@ -896,11 +894,8 @@ const KProcess* KernelCore::ApplicationProcess() const { std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() { std::list<KScopedAutoObject<KProcess>> processes; std::scoped_lock lk{impl->process_list_lock}; - - for (auto* const process : impl->process_list) { - processes.emplace_back(process); - } - + for (auto* const process : impl->process_list) + processes.emplace_back(*this, process); return processes; } @@ -1029,15 +1024,14 @@ void KernelCore::RegisterHostThread(KThread* existing_thread) { } } -static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, - std::string&& thread_name, std::function<void()>&& func) { +static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, std::string&& thread_name, std::function<void()>&& func) { // Reserve a new thread from the process resource limit. - KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(kernel, process, LimitableResource::ThreadCountMax); ASSERT(thread_reservation.Succeeded()); // Initialize the thread. KThread* thread = KThread::Create(kernel); - ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(thread, process))); + ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(kernel.System(), thread, process))); // Commit the thread reservation. thread_reservation.Commit(); @@ -1057,7 +1051,7 @@ static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, // Close the thread. // This will free the process if it is the last reference. - thread->Close(); + thread->Close(kernel); }); } @@ -1066,11 +1060,11 @@ std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name, // Make a new process. KProcess* process = KProcess::Create(*this); ASSERT(R_SUCCEEDED( - process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); + process->Initialize(*this, Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); // Ensure that we don't hold onto any extra references. SCOPE_EXIT { - process->Close(); + process->Close(*this); }; // Register the new process. @@ -1096,18 +1090,18 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function // Make a new process. KProcess* process = KProcess::Create(*this); ASSERT(R_SUCCEEDED( - process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); + process->Initialize(*this, Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); // Ensure that we don't hold onto any extra references. SCOPE_EXIT { - process->Close(); + process->Close(*this); }; // Register the new process. KProcess::Register(*this, process); // Reserve a new thread from the process resource limit. - KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(*this, process, LimitableResource::ThreadCountMax); ASSERT(thread_reservation.Succeeded()); // Initialize the thread. @@ -1122,7 +1116,7 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function KThread::Register(*this, thread); // Begin running the thread. - ASSERT(R_SUCCEEDED(thread->Run())); + ASSERT(R_SUCCEEDED(thread->Run(*this))); } u32 KernelCore::GetCurrentHostThreadID() const { @@ -1130,7 +1124,7 @@ u32 KernelCore::GetCurrentHostThreadID() const { } KThread* KernelCore::GetCurrentEmuThread() const { - return impl->GetCurrentEmuThread(); + return impl->GetCurrentEmuThread(Impl::tls_data); } void KernelCore::SetCurrentEmuThread(KThread* thread) { @@ -1206,9 +1200,9 @@ void KernelCore::SuspendEmulation(bool suspended) { for (auto& thread : process->GetThreadList()) { if (should_suspend) { - thread.RequestSuspend(SuspendType::System); + thread.RequestSuspend(*this, SuspendType::System); } else { - thread.Resume(SuspendType::System); + thread.Resume(*this, SuspendType::System); } } } @@ -1244,12 +1238,9 @@ void KernelCore::SuspendEmulation(bool suspended) { void KernelCore::ShutdownCores() { impl->TerminateAllProcesses(); - KScopedSchedulerLock lk{*this}; - - for (auto* thread : impl->shutdown_threads) { - void(thread->Run()); - } + for (auto* thread : impl->shutdown_threads) + void(thread->Run(*this)); } bool KernelCore::IsMulticore() const { diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index f394122764..a81c14f643 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -17,14 +17,15 @@ namespace Kernel { PhysicalCore::PhysicalCore(KernelCore& kernel, std::size_t core_index) - : m_kernel{kernel}, m_core_index{core_index} { + : m_core_index{core_index} +{ m_is_single_core = !kernel.IsMulticore(); } PhysicalCore::~PhysicalCore() = default; -void PhysicalCore::RunThread(Kernel::KThread* thread) { +void PhysicalCore::RunThread(KernelCore& kernel, Kernel::KThread* thread) { auto* process = thread->GetOwnerProcess(); - auto& system = m_kernel.System(); + auto& system = kernel.System(); auto* interface = process->GetArmInterface(m_core_index); interface->Initialize(); @@ -72,14 +73,14 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { while (true) { // If the thread is scheduled for termination, exit. if (thread->HasDpc() && thread->IsTerminationRequested()) { - thread->Exit(); + thread->Exit(kernel); } // Notify the debugger and go to sleep if a step was performed // and this thread has been scheduled again. if (thread->GetStepState() == StepState::StepPerformed) { system.GetDebugger().NotifyThreadStopped(thread); - thread->RequestSuspend(SuspendType::Debug); + thread->RequestSuspend(kernel, SuspendType::Debug); return; } @@ -135,7 +136,7 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { } else { interface->LogBacktrace(process); } - thread->RequestSuspend(SuspendType::Debug); + thread->RequestSuspend(kernel, SuspendType::Debug); return; } @@ -144,7 +145,7 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { if (system.DebuggerEnabled()) { system.GetDebugger().NotifyThreadWatchpoint(thread, *interface->HaltedWatchpoint()); } - thread->RequestSuspend(SuspendType::Debug); + thread->RequestSuspend(kernel, SuspendType::Debug); return; } @@ -208,8 +209,8 @@ void PhysicalCore::CloneFpuStatus(KThread* dst) const { dst->GetContext().fpsr = ctx.fpsr; } -void PhysicalCore::LogBacktrace() { - auto* process = GetCurrentProcessPointer(m_kernel); +void PhysicalCore::LogBacktrace(KernelCore& kernel) { + auto* process = GetCurrentProcessPointer(kernel); if (!process) { return; } diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index bae4fe5b88..b92201204a 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +33,7 @@ public: YUZU_NON_MOVEABLE(PhysicalCore); // Execute guest code running on the given thread. - void RunThread(KThread* thread); + void RunThread(KernelCore& kernel, KThread* thread); // Copy context from thread to current core. void LoadContext(const KThread* thread); @@ -44,7 +47,7 @@ public: void CloneFpuStatus(KThread* dst) const; // Log backtrace of current processor state. - void LogBacktrace(); + void LogBacktrace(KernelCore& kernel); // Wait for an interrupt. void Idle(); @@ -63,9 +66,7 @@ public: } private: - KernelCore& m_kernel; const std::size_t m_core_index; - std::mutex m_guard; std::condition_variable m_on_interrupt; Core::ArmInterface* m_arm_interface{}; diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h index d1bbc76709..95e6b9f6e6 100644 --- a/src/core/hle/kernel/slab_helpers.h +++ b/src/core/hle/kernel/slab_helpers.h @@ -1,3 +1,6 @@ +// 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 @@ -69,16 +72,16 @@ public: explicit KAutoObjectWithSlabHeap(KernelCore& kernel) : Base(kernel) {} virtual ~KAutoObjectWithSlabHeap() = default; - virtual void Destroy() override { + virtual void Destroy(KernelCore& kernel) override { const bool is_initialized = this->IsInitialized(); uintptr_t arg = 0; if (is_initialized) { arg = this->GetPostDestroyArgument(); - this->Finalize(); + this->Finalize(kernel); } - Free(Base::m_kernel, static_cast<Derived*>(this)); + Free(kernel, static_cast<Derived*>(this)); if (is_initialized) { - Derived::PostDestroy(arg); + Derived::PostDestroy(kernel, arg); } } @@ -89,8 +92,8 @@ public: return 0; } - size_t GetSlabIndex() const { - return SlabHeap<Derived>(Base::m_kernel).GetObjectIndex(static_cast<const Derived*>(this)); + size_t GetSlabIndex(KernelCore& kernel) const { + return SlabHeap<Derived>(kernel).GetObjectIndex(static_cast<const Derived*>(this)); } public: @@ -144,17 +147,17 @@ public: KAutoObjectWithSlabHeapAndContainer(KernelCore& kernel) : Base(kernel) {} virtual ~KAutoObjectWithSlabHeapAndContainer() {} - virtual void Destroy() override { + virtual void Destroy(KernelCore& kernel) override { const bool is_initialized = this->IsInitialized(); uintptr_t arg = 0; if (is_initialized) { - Base::m_kernel.ObjectListContainer().Unregister(this); + kernel.ObjectListContainer().Unregister(this); arg = this->GetPostDestroyArgument(); - this->Finalize(); + this->Finalize(kernel); } - Free(Base::m_kernel, static_cast<Derived*>(this)); + Free(kernel, static_cast<Derived*>(this)); if (is_initialized) { - Derived::PostDestroy(arg); + Derived::PostDestroy(kernel, arg); } } @@ -165,8 +168,8 @@ public: return 0; } - size_t GetSlabIndex() const { - return SlabHeap<Derived>(Base::m_kernel).GetObjectIndex(static_cast<const Derived*>(this)); + size_t GetSlabIndex(KernelCore& kernel) const { + return SlabHeap<Derived>(kernel).GetObjectIndex(static_cast<const Derived*>(this)); } public: @@ -177,9 +180,8 @@ public: static Derived* Create(KernelCore& kernel) { Derived* obj = Allocate(kernel); - if (obj != nullptr) { + if (obj != nullptr) KAutoObject::Create(obj); - } return obj; } diff --git a/src/core/hle/kernel/svc/svc_activity.cpp b/src/core/hle/kernel/svc/svc_activity.cpp index 63bc085554..c1ab3daab3 100644 --- a/src/core/hle/kernel/svc/svc_activity.cpp +++ b/src/core/hle/kernel/svc/svc_activity.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,17 +25,15 @@ Result SetThreadActivity(Core::System& system, Handle thread_handle, R_UNLESS(IsValidThreadActivity(thread_activity), ResultInvalidEnumValue); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Check that the activity is being set on a non-current thread for the current process. - R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()), - ResultInvalidHandle); + R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()), ResultInvalidHandle); R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy); // Set the activity. - R_TRY(thread->SetActivity(thread_activity)); + R_TRY(thread->SetActivity(system.Kernel(), thread_activity)); return ResultSuccess; } diff --git a/src/core/hle/kernel/svc/svc_cache.cpp b/src/core/hle/kernel/svc/svc_cache.cpp index c2c8be10f5..24f64f28f1 100644 --- a/src/core/hle/kernel/svc/svc_cache.cpp +++ b/src/core/hle/kernel/svc/svc_cache.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -37,8 +40,7 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad R_UNLESS(size == static_cast<uint64_t>(size), ResultInvalidCurrentMemory); // Get the process from its handle. - KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle); + KScopedAutoObject process = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Verify the region is within range. diff --git a/src/core/hle/kernel/svc/svc_code_memory.cpp b/src/core/hle/kernel/svc/svc_code_memory.cpp index 4e7af9f575..4133586d11 100644 --- a/src/core/hle/kernel/svc/svc_code_memory.cpp +++ b/src/core/hle/kernel/svc/svc_code_memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -35,9 +35,6 @@ constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(MemoryPermission perm) Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t size) { LOG_TRACE(Kernel_SVC, "called, address={:#X}, size=0x{:X}", address, size); - // Get kernel instance. - auto& kernel = system.Kernel(); - // Validate address / size. R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); @@ -46,24 +43,23 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t // Create the code memory. - KCodeMemory* code_mem = KCodeMemory::Create(kernel); + KCodeMemory* code_mem = KCodeMemory::Create(system.Kernel()); R_UNLESS(code_mem != nullptr, ResultOutOfResource); SCOPE_EXIT { - code_mem->Close(); + code_mem->Close(system.Kernel()); }; // Verify that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size), - ResultInvalidCurrentMemory); + R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size), ResultInvalidCurrentMemory); // Initialize the code memory. - R_TRY(code_mem->Initialize(system.DeviceMemory(), address, size)); + R_TRY(code_mem->Initialize(system.Kernel(), system.DeviceMemory(), address, size)); // Register the code memory. - KCodeMemory::Register(kernel, code_mem); + KCodeMemory::Register(system.Kernel(), code_mem); // Add the code memory to the handle table. - R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, code_mem)); + R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(system.Kernel(), out, code_mem)); R_SUCCEED(); } @@ -85,8 +81,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, // Get the code memory from its handle. KScopedAutoObject code_mem = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KCodeMemory>(code_memory_handle); + .GetHandleTable() + .GetObject<KCodeMemory>(system.Kernel(), code_memory_handle); R_UNLESS(code_mem.IsNotNull(), ResultInvalidHandle); // NOTE: Here, Atmosphere extends the SVC to allow code memory operations on one's own process. @@ -96,29 +92,23 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, switch (operation) { case CodeMemoryOperation::Map: { // Check that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()) - .GetPageTable() - .CanContain(address, size, KMemoryState::CodeOut), - ResultInvalidMemoryRegion); + R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().CanContain(address, size, KMemoryState::CodeOut), ResultInvalidMemoryRegion); // Check the memory permission. R_UNLESS(IsValidMapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Map the memory. - R_TRY(code_mem->Map(address, size)); + R_TRY(code_mem->Map(system.Kernel(), address, size)); } break; case CodeMemoryOperation::Unmap: { // Check that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()) - .GetPageTable() - .CanContain(address, size, KMemoryState::CodeOut), - ResultInvalidMemoryRegion); + R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().CanContain(address, size, KMemoryState::CodeOut), ResultInvalidMemoryRegion); // Check the memory permission. R_UNLESS(IsValidUnmapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Unmap the memory. - R_TRY(code_mem->Unmap(address, size)); + R_TRY(code_mem->Unmap(system.Kernel(), address, size)); } break; case CodeMemoryOperation::MapToOwner: { // Check that the region is in range. @@ -130,7 +120,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, R_UNLESS(IsValidMapToOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Map the memory to its owner. - R_TRY(code_mem->MapToOwner(address, size, perm)); + R_TRY(code_mem->MapToOwner(system.Kernel(), address, size, perm)); } break; case CodeMemoryOperation::UnmapFromOwner: { // Check that the region is in range. @@ -142,7 +132,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, R_UNLESS(IsValidUnmapFromOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Unmap the memory from its owner. - R_TRY(code_mem->UnmapFromOwner(address, size)); + R_TRY(code_mem->UnmapFromOwner(system.Kernel(), address, size)); } break; default: R_THROW(ResultInvalidEnumValue); diff --git a/src/core/hle/kernel/svc/svc_device_address_space.cpp b/src/core/hle/kernel/svc/svc_device_address_space.cpp index ac828320f4..2deb683d4b 100644 --- a/src/core/hle/kernel/svc/svc_device_address_space.cpp +++ b/src/core/hle/kernel/svc/svc_device_address_space.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,17 +32,17 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_ KDeviceAddressSpace* das = KDeviceAddressSpace::Create(system.Kernel()); R_UNLESS(das != nullptr, ResultOutOfResource); SCOPE_EXIT { - das->Close(); + das->Close(system.Kernel()); }; // Initialize the device address space. - R_TRY(das->Initialize(das_address, das_size)); + R_TRY(das->Initialize(system.Kernel(), das_address, das_size)); // Register the device address space. KDeviceAddressSpace::Register(system.Kernel(), das); // Add to the handle table. - R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, das)); + R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(system.Kernel(), out, das)); R_SUCCEED(); } @@ -47,8 +50,8 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_ Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) { // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KDeviceAddressSpace>(das_handle); + .GetHandleTable() + .GetObject<KDeviceAddressSpace>(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Attach. @@ -58,8 +61,8 @@ Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Ha Result DetachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) { // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KDeviceAddressSpace>(das_handle); + .GetHandleTable() + .GetObject<KDeviceAddressSpace>(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Detach. @@ -99,13 +102,13 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KDeviceAddressSpace>(das_handle); + .GetHandleTable() + .GetObject<KDeviceAddressSpace>(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Get the process. KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. @@ -140,13 +143,13 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KDeviceAddressSpace>(das_handle); + .GetHandleTable() + .GetObject<KDeviceAddressSpace>(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Get the process. KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. @@ -172,13 +175,12 @@ Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle p // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KDeviceAddressSpace>(das_handle); + .GetHandleTable() + .GetObject<KDeviceAddressSpace>(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Get the process. - KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle); + KScopedAutoObject process = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. diff --git a/src/core/hle/kernel/svc/svc_event.cpp b/src/core/hle/kernel/svc/svc_event.cpp index 586cb2b14e..36de3b9096 100644 --- a/src/core/hle/kernel/svc/svc_event.cpp +++ b/src/core/hle/kernel/svc/svc_event.cpp @@ -22,9 +22,9 @@ Result SignalEvent(Core::System& system, Handle event_handle) { // Fail-safe for system applets const auto program_id = GetCurrentProcess(system.Kernel()).GetProgramId(); if ((program_id & 0xFFFFFFFFFFFFFF00ull) == 0x0100000000001000ull) { - KScopedAutoObject event = handle_table.GetObject<KEvent>(event_handle); + KScopedAutoObject event = handle_table.GetObject<KEvent>(system.Kernel(), event_handle); if (event.IsNotNull()) { - event->Signal(); + event->Signal(system.Kernel()); } else { LOG_WARNING(Kernel_SVC, "SignalEvent best-effort unknown handle=0x{:08X} (ignored)", event_handle); @@ -34,10 +34,10 @@ Result SignalEvent(Core::System& system, Handle event_handle) { // Get the event. - KScopedAutoObject event = handle_table.GetObject<KEvent>(event_handle); + KScopedAutoObject event = handle_table.GetObject<KEvent>(system.Kernel(), event_handle); R_UNLESS(event.IsNotNull(), ResultInvalidHandle); - R_RETURN(event->Signal()); + R_RETURN(event->Signal(system.Kernel())); } Result ClearEvent(Core::System& system, Handle event_handle) { @@ -48,18 +48,18 @@ Result ClearEvent(Core::System& system, Handle event_handle) { // Try to clear the writable event. { - KScopedAutoObject event = handle_table.GetObject<KEvent>(event_handle); + KScopedAutoObject event = handle_table.GetObject<KEvent>(system.Kernel(), event_handle); if (event.IsNotNull()) { - event->Clear(); + event->Clear(system.Kernel()); R_SUCCEED(); } } // Try to clear the readable event. { - KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(event_handle); + KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(system.Kernel(), event_handle); if (readable_event.IsNotNull()) { - readable_event->Clear(); + readable_event->Clear(system.Kernel()); R_SUCCEED(); } } @@ -71,43 +71,42 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) { LOG_DEBUG(Kernel_SVC, "called"); // Get the kernel reference and handle table. - auto& kernel = system.Kernel(); - auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); + auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); // Reserve a new event from the process resource limit - KScopedResourceReservation event_reservation(GetCurrentProcessPointer(kernel), + KScopedResourceReservation event_reservation(system.Kernel(), GetCurrentProcessPointer(system.Kernel()), LimitableResource::EventCountMax); R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); // Create a new event. - KEvent* event = KEvent::Create(kernel); + KEvent* event = KEvent::Create(system.Kernel()); R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. - event->Initialize(GetCurrentProcessPointer(kernel)); + event->Initialize(system.Kernel(), GetCurrentProcessPointer(system.Kernel())); // Commit the thread reservation. event_reservation.Commit(); // Ensure that we clean up the event (and its only references are handle table) on function end. SCOPE_EXIT { - event->GetReadableEvent().Close(); - event->Close(); + event->GetReadableEvent().Close(system.Kernel()); + event->Close(system.Kernel()); }; // Register the event. - KEvent::Register(kernel, event); + KEvent::Register(system.Kernel(), event); // Add the event to the handle table. - R_TRY(handle_table.Add(out_write, event)); + R_TRY(handle_table.Add(system.Kernel(), out_write, event)); // Ensure that we maintain a clean handle state on exit. ON_RESULT_FAILURE { - handle_table.Remove(*out_write); + handle_table.Remove(system.Kernel(), *out_write); }; // Add the readable event to the handle table. - R_RETURN(handle_table.Add(out_read, std::addressof(event->GetReadableEvent()))); + R_RETURN(handle_table.Add(system.Kernel(), out_read, std::addressof(event->GetReadableEvent()))); } Result SignalEvent64(Core::System& system, Handle event_handle) { diff --git a/src/core/hle/kernel/svc/svc_exception.cpp b/src/core/hle/kernel/svc/svc_exception.cpp index bf09641bad..e1b0fa7b95 100644 --- a/src/core/hle/kernel/svc/svc_exception.cpp +++ b/src/core/hle/kernel/svc/svc_exception.cpp @@ -106,14 +106,14 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) { handle_debug_buffer(info1, info2); - system.CurrentPhysicalCore().LogBacktrace(); + system.CurrentPhysicalCore().LogBacktrace(system.Kernel()); } const bool should_break = !notification_only; if (system.DebuggerEnabled() && should_break) { auto* thread = system.Kernel().GetCurrentEmuThread(); system.GetDebugger().NotifyThreadStopped(thread); - thread->RequestSuspend(Kernel::SuspendType::Debug); + thread->RequestSuspend(system.Kernel(), Kernel::SuspendType::Debug); } } diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp index 9e651e1171..62f203476e 100644 --- a/src/core/hle/kernel/svc/svc_info.cpp +++ b/src/core/hle/kernel/svc/svc_info.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -46,7 +46,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_UNLESS(info_sub_id == 0, ResultInvalidEnumValue); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject<KProcess>(handle); + KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); switch (info_id_type) { @@ -90,11 +90,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_SUCCEED(); case InfoType::TotalMemorySize: - *result = process->GetTotalUserPhysicalMemorySize(); + *result = process->GetTotalUserPhysicalMemorySize(system.Kernel()); R_SUCCEED(); case InfoType::UsedMemorySize: - *result = process->GetUsedUserPhysicalMemorySize(); + *result = process->GetUsedUserPhysicalMemorySize(system.Kernel()); R_SUCCEED(); case InfoType::SystemResourceSizeTotal: @@ -114,11 +114,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_SUCCEED(); case InfoType::TotalNonSystemMemorySize: - *result = process->GetTotalNonSystemUserPhysicalMemorySize(); + *result = process->GetTotalNonSystemUserPhysicalMemorySize(system.Kernel()); R_SUCCEED(); case InfoType::UsedNonSystemMemorySize: - *result = process->GetUsedNonSystemUserPhysicalMemorySize(); + *result = process->GetUsedNonSystemUserPhysicalMemorySize(system.Kernel()); R_SUCCEED(); case InfoType::IsApplication: @@ -175,7 +175,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle } Handle resource_handle{}; - R_TRY(handle_table.Add(std::addressof(resource_handle), resource_limit)); + R_TRY(handle_table.Add(system.Kernel(), std::addressof(resource_handle), resource_limit)); *result = resource_handle; R_SUCCEED(); @@ -203,8 +203,8 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle } KScopedAutoObject thread = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KThread>(static_cast<Handle>(handle)); + .GetHandleTable() + .GetObject<KThread>(system.Kernel(), Handle(handle)); if (thread.IsNull()) { LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", static_cast<Handle>(handle)); @@ -256,7 +256,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle // Get a new handle for the current process. Handle tmp; - R_TRY(handle_table.Add(std::addressof(tmp), current_process)); + R_TRY(handle_table.Add(system.Kernel(), std::addressof(tmp), current_process)); // Set the output. *result = tmp; diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp index db912b71fb..875590d6f7 100644 --- a/src/core/hle/kernel/svc/svc_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_ipc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -20,19 +20,17 @@ namespace Kernel::Svc { namespace { -Result SendSyncRequestImpl(KernelCore& kernel, uintptr_t message, size_t buffer_size, - Handle session_handle) { +Result SendSyncRequestImpl(KernelCore& kernel, uintptr_t message, size_t buffer_size, Handle session_handle) { // Get the client session. - KScopedAutoObject session = - GetCurrentProcess(kernel).GetHandleTable().GetObject<KClientSession>(session_handle); + KScopedAutoObject session = GetCurrentProcess(kernel).GetHandleTable().GetObject<KClientSession>(kernel, session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Get the parent, and persist a reference to it until we're done. - KScopedAutoObject parent = session->GetParent(); + KScopedAutoObject parent = {kernel, session->GetParent()}; ASSERT(parent.IsNotNull()); // Send the request. - R_RETURN(session->SendSyncRequest(message, buffer_size)); + R_RETURN(session->SendSyncRequest(kernel, message, buffer_size)); } Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t message, @@ -41,8 +39,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes int64_t timeout_ns) { // Reply to the target, if one is specified. if (reply_target != InvalidHandle) { - KScopedAutoObject session = - GetCurrentProcess(kernel).GetHandleTable().GetObject<KServerSession>(reply_target); + KScopedAutoObject session = GetCurrentProcess(kernel).GetHandleTable().GetObject<KServerSession>(kernel, reply_target); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // If we fail to reply, we want to set the output index to -1. @@ -51,7 +48,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes }; // Send the reply. - R_TRY(session->SendReply(message, buffer_size, message_paddr)); + R_TRY(session->SendReply(kernel, message, buffer_size, message_paddr)); } // Receive a message. @@ -77,8 +74,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes while (true) { // Wait for an object. s32 index; - Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs, - num_objects, timeout); + Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs, num_objects, timeout); if (ResultTimedOut == result) { R_THROW(result); } @@ -87,7 +83,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes if (R_SUCCEEDED(result)) { KServerSession* session = objs[index]->DynamicCast<KServerSession*>(); if (session != nullptr) { - result = session->ReceiveRequest(message, buffer_size, message_paddr); + result = session->ReceiveRequest(kernel, message, buffer_size, message_paddr); if (ResultNotFound == result) { continue; } @@ -127,14 +123,14 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes // Convert the handles to objects. R_UNLESS( - handle_table.GetMultipleObjects<KSynchronizationObject>(objs, handles, num_handles), + handle_table.GetMultipleObjects<KSynchronizationObject>(kernel, objs, handles, num_handles), ResultInvalidHandle); } // Ensure handles are closed when we're done. SCOPE_EXIT { for (auto i = 0; i < num_handles; ++i) { - objs[i]->Close(); + objs[i]->Close(kernel); } }; @@ -188,16 +184,15 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha auto& handle_table = process.GetHandleTable(); // Reserve a new event from the process resource limit. - KScopedResourceReservation event_reservation(std::addressof(process), - Svc::LimitableResource::EventCountMax); + KScopedResourceReservation event_reservation(system.Kernel(), std::addressof(process), Svc::LimitableResource::EventCountMax); R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); // Get the client session. - KScopedAutoObject session = process.GetHandleTable().GetObject<KClientSession>(session_handle); + KScopedAutoObject session = process.GetHandleTable().GetObject<KClientSession>(system.Kernel(), session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Get the parent, and persist a reference to it until we're done. - KScopedAutoObject parent = session->GetParent(); + KScopedAutoObject parent = {system.Kernel(), session->GetParent()}; ASSERT(parent.IsNotNull()); // Create a new event. @@ -205,30 +200,30 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. - event->Initialize(std::addressof(process)); + event->Initialize(system.Kernel(), std::addressof(process)); // Commit our reservation. event_reservation.Commit(); // At end of scope, kill the standing references to the sub events. SCOPE_EXIT { - event->GetReadableEvent().Close(); - event->Close(); + event->GetReadableEvent().Close(system.Kernel()); + event->Close(system.Kernel()); }; // Register the event. KEvent::Register(system.Kernel(), event); // Add the readable event to the handle table. - R_TRY(handle_table.Add(out_event_handle, std::addressof(event->GetReadableEvent()))); + R_TRY(handle_table.Add(system.Kernel(), out_event_handle, std::addressof(event->GetReadableEvent()))); // Ensure that if we fail to send the request, we close the readable handle. ON_RESULT_FAILURE { - handle_table.Remove(*out_event_handle); + handle_table.Remove(system.Kernel(), *out_event_handle); }; // Send the async request. - R_RETURN(session->SendAsyncRequest(event, message, buffer_size)); + R_RETURN(session->SendAsyncRequest(system.Kernel(), event, message, buffer_size)); } Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles, s32 num_handles, diff --git a/src/core/hle/kernel/svc/svc_light_ipc.cpp b/src/core/hle/kernel/svc/svc_light_ipc.cpp index 4772cbda17..ae3ff85a88 100644 --- a/src/core/hle/kernel/svc/svc_light_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_light_ipc.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,12 +17,12 @@ namespace Kernel::Svc { Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) { // Get the light client session from its handle. KScopedAutoObject session = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KLightClientSession>(session_handle); + .GetHandleTable() + .GetObject<KLightClientSession>(system.Kernel(), session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Send the request. - R_TRY(session->SendSyncRequest(args)); + R_TRY(session->SendSyncRequest(system.Kernel(), args)); R_SUCCEED(); } @@ -27,12 +30,12 @@ Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* ar Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) { // Get the light server session from its handle. KScopedAutoObject session = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KLightServerSession>(session_handle); + .GetHandleTable() + .GetObject<KLightServerSession>(system.Kernel(), session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Handle the request. - R_TRY(session->ReplyAndReceive(args)); + R_TRY(session->ReplyAndReceive(system.Kernel(), args)); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp index 9a22dadaf7..bddd57e8f9 100644 --- a/src/core/hle/kernel/svc/svc_port.cpp +++ b/src/core/hle/kernel/svc/svc_port.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -33,18 +36,18 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) { // Reserve a handle for the port. // NOTE: Nintendo really does write directly to the output handle here. - R_TRY(handle_table.Reserve(out)); + R_TRY(handle_table.Reserve(system.Kernel(), out)); ON_RESULT_FAILURE { - handle_table.Unreserve(*out); + handle_table.Unreserve(system.Kernel(), *out); }; // Create a session. KClientSession* session; - R_TRY(port->CreateSession(std::addressof(session))); + R_TRY(port->CreateSession(system.Kernel(), std::addressof(session))); // Register the session in the table, close the extra reference. - handle_table.Register(*out, session); - session->Close(); + handle_table.Register(system.Kernel(), *out, session); + session->Close(system.Kernel()); // We succeeded. R_SUCCEED(); @@ -65,27 +68,27 @@ Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client, R_UNLESS(port != nullptr, ResultOutOfResource); // Initialize the port. - port->Initialize(max_sessions, is_light, name); + port->Initialize(system.Kernel(), max_sessions, is_light, name); // Ensure that we clean up the port (and its only references are handle table) on function end. SCOPE_EXIT { - port->GetServerPort().Close(); - port->GetClientPort().Close(); + port->GetServerPort().Close(system.Kernel()); + port->GetClientPort().Close(system.Kernel()); }; // Register the port. KPort::Register(kernel, port); // Add the client to the handle table. - R_TRY(handle_table.Add(out_client, std::addressof(port->GetClientPort()))); + R_TRY(handle_table.Add(system.Kernel(), out_client, std::addressof(port->GetClientPort()))); // Ensure that we maintain a clean handle state on exit. ON_RESULT_FAILURE { - handle_table.Remove(*out_client); + handle_table.Remove(system.Kernel(), *out_client); }; // Add the server to the handle table. - R_RETURN(handle_table.Add(out_server, std::addressof(port->GetServerPort()))); + R_RETURN(handle_table.Add(system.Kernel(), out_server, std::addressof(port->GetServerPort()))); } Result ConnectToPort(Core::System& system, Handle* out, Handle port) { @@ -93,36 +96,33 @@ Result ConnectToPort(Core::System& system, Handle* out, Handle port) { auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); // Get the client port. - KScopedAutoObject client_port = handle_table.GetObject<KClientPort>(port); + KScopedAutoObject client_port = handle_table.GetObject<KClientPort>(system.Kernel(), port); R_UNLESS(client_port.IsNotNull(), ResultInvalidHandle); // Reserve a handle for the port. // NOTE: Nintendo really does write directly to the output handle here. - R_TRY(handle_table.Reserve(out)); + R_TRY(handle_table.Reserve(system.Kernel(), out)); ON_RESULT_FAILURE { - handle_table.Unreserve(*out); + handle_table.Unreserve(system.Kernel(), *out); }; // Create the session. KAutoObject* session; - if (client_port->IsLight()) { - R_TRY(client_port->CreateLightSession( - reinterpret_cast<KLightClientSession**>(std::addressof(session)))); + if (client_port->IsLight(system.Kernel())) { + R_TRY(client_port->CreateLightSession(system.Kernel(), reinterpret_cast<KLightClientSession**>(std::addressof(session)))); } else { - R_TRY(client_port->CreateSession( - reinterpret_cast<KClientSession**>(std::addressof(session)))); + R_TRY(client_port->CreateSession(system.Kernel(), reinterpret_cast<KClientSession**>(std::addressof(session)))); } // Register the session. - handle_table.Register(*out, session); - session->Close(); + handle_table.Register(system.Kernel(), *out, session); + session->Close(system.Kernel()); // We succeeded. R_SUCCEED(); } -Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, - int32_t max_sessions) { +Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, int32_t max_sessions) { // Copy the provided name from user memory to kernel memory. auto string_name = GetCurrentMemory(system.Kernel()).ReadCString(user_name, KObjectName::NameLengthMax); @@ -144,21 +144,21 @@ Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t R_UNLESS(port != nullptr, ResultOutOfResource); // Initialize the new port. - port->Initialize(max_sessions, false, 0); + port->Initialize(system.Kernel(), max_sessions, false, 0); // Register the port. KPort::Register(system.Kernel(), port); // Ensure that our only reference to the port is in the handle table when we're done. SCOPE_EXIT { - port->GetClientPort().Close(); - port->GetServerPort().Close(); + port->GetClientPort().Close(system.Kernel()); + port->GetServerPort().Close(system.Kernel()); }; // Register the handle in the table. - R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort()))); + R_TRY(handle_table.Add(system.Kernel(), out_server_handle, std::addressof(port->GetServerPort()))); ON_RESULT_FAILURE { - handle_table.Remove(*out_server_handle); + handle_table.Remove(system.Kernel(), *out_server_handle); }; // Create a new object name. diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp index 6d63892a94..dc2566e85a 100644 --- a/src/core/hle/kernel/svc/svc_process.cpp +++ b/src/core/hle/kernel/svc/svc_process.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -27,8 +27,8 @@ Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) { // Get the object from the handle table. KScopedAutoObject obj = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KAutoObject>(static_cast<Handle>(handle)); + .GetHandleTable() + .GetObject<KAutoObject>(system.Kernel(), Handle(handle)); R_UNLESS(obj.IsNotNull(), ResultInvalidHandle); // Get the process from the object. @@ -98,7 +98,7 @@ Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle, LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type={:#X}", process_handle, info_type); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); + KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); diff --git a/src/core/hle/kernel/svc/svc_process_memory.cpp b/src/core/hle/kernel/svc/svc_process_memory.cpp index 3313118dfa..0c18be91ba 100644 --- a/src/core/hle/kernel/svc/svc_process_memory.cpp +++ b/src/core/hle/kernel/svc/svc_process_memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -48,7 +48,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u // Get the process from its handle. KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the address is in range. @@ -76,7 +76,7 @@ Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_ha // Get the processes. KProcess* dst_process = GetCurrentProcessPointer(system.Kernel()); KScopedAutoObject src_process = - dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle); + dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(system.Kernel(), process_handle); R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); // Get the page tables. @@ -117,7 +117,7 @@ Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_ // Get the processes. KProcess* dst_process = GetCurrentProcessPointer(system.Kernel()); KScopedAutoObject src_process = - dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle); + dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(system.Kernel(), process_handle); R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); // Get the page tables. @@ -174,7 +174,7 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst } const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); + KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); @@ -234,7 +234,7 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d } const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); + KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); diff --git a/src/core/hle/kernel/svc/svc_query_memory.cpp b/src/core/hle/kernel/svc/svc_query_memory.cpp index 816dcb8d0f..ad7a667bb5 100644 --- a/src/core/hle/kernel/svc/svc_query_memory.cpp +++ b/src/core/hle/kernel/svc/svc_query_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,7 +26,7 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn Handle process_handle, uint64_t address) { LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); + KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); diff --git a/src/core/hle/kernel/svc/svc_resource_limit.cpp b/src/core/hle/kernel/svc/svc_resource_limit.cpp index 6f3972482f..7f78aa8b10 100644 --- a/src/core/hle/kernel/svc/svc_resource_limit.cpp +++ b/src/core/hle/kernel/svc/svc_resource_limit.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -19,7 +22,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) { // Ensure we don't leak a reference to the limit. SCOPE_EXIT { - resource_limit->Close(); + resource_limit->Close(system.Kernel()); }; // Initialize the resource limit. @@ -29,7 +32,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) { KResourceLimit::Register(kernel, resource_limit); // Add the limit to the handle table. - R_RETURN(GetCurrentProcess(kernel).GetHandleTable().Add(out_handle, resource_limit)); + R_RETURN(GetCurrentProcess(kernel).GetHandleTable().Add(system.Kernel(), out_handle, resource_limit)); } Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value, @@ -42,8 +45,8 @@ Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value, // Get the resource limit. KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KResourceLimit>(resource_limit_handle); + .GetHandleTable() + .GetObject<KResourceLimit>(system.Kernel(), resource_limit_handle); R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); // Get the limit value. @@ -62,8 +65,8 @@ Result GetResourceLimitCurrentValue(Core::System& system, s64* out_current_value // Get the resource limit. KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject<KResourceLimit>(resource_limit_handle); + .GetHandleTable() + .GetObject<KResourceLimit>(system.Kernel(), resource_limit_handle); R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); // Get the current value. @@ -83,7 +86,7 @@ Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_ha // Get the resource limit. KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel()) .GetHandleTable() - .GetObject<KResourceLimit>(resource_limit_handle); + .GetObject<KResourceLimit>(system.Kernel(), resource_limit_handle); R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); // Set the limit value. diff --git a/src/core/hle/kernel/svc/svc_session.cpp b/src/core/hle/kernel/svc/svc_session.cpp index b034d21d15..4d04f0c5a3 100644 --- a/src/core/hle/kernel/svc/svc_session.cpp +++ b/src/core/hle/kernel/svc/svc_session.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,7 +26,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien // Reserve a new session from the process resource limit. // TODO: Dynamic resource limits - KScopedResourceReservation session_reservation(std::addressof(process), + KScopedResourceReservation session_reservation(system.Kernel(), std::addressof(process), LimitableResource::SessionCountMax); if (session_reservation.Succeeded()) { session = T::Create(system.Kernel()); @@ -62,7 +65,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien R_UNLESS(session != nullptr, ResultOutOfResource); // Initialize the session. - session->Initialize(nullptr, name); + session->Initialize(system.Kernel(), nullptr, name); // Commit the session reservation. session_reservation.Commit(); @@ -70,23 +73,23 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien // Ensure that we clean up the session (and its only references are handle table) on function // end. SCOPE_EXIT { - session->GetClientSession().Close(); - session->GetServerSession().Close(); + session->GetClientSession().Close(system.Kernel()); + session->GetServerSession().Close(system.Kernel()); }; // Register the session. T::Register(system.Kernel(), session); // Add the server session to the handle table. - R_TRY(handle_table.Add(out_server, std::addressof(session->GetServerSession()))); + R_TRY(handle_table.Add(system.Kernel(), out_server, std::addressof(session->GetServerSession()))); // Ensure that we maintain a clean handle state on exit. ON_RESULT_FAILURE { - handle_table.Remove(*out_server); + handle_table.Remove(system.Kernel(), *out_server); }; // Add the client session to the handle table. - R_RETURN(handle_table.Add(out_client, std::addressof(session->GetClientSession()))); + R_RETURN(handle_table.Add(system.Kernel(), out_client, std::addressof(session->GetClientSession()))); } } // namespace @@ -105,29 +108,29 @@ Result AcceptSession(Core::System& system, Handle* out, Handle port_handle) { auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); // Get the server port. - KScopedAutoObject port = handle_table.GetObject<KServerPort>(port_handle); + KScopedAutoObject port = handle_table.GetObject<KServerPort>(system.Kernel(), port_handle); R_UNLESS(port.IsNotNull(), ResultInvalidHandle); // Reserve an entry for the new session. - R_TRY(handle_table.Reserve(out)); + R_TRY(handle_table.Reserve(system.Kernel(), out)); ON_RESULT_FAILURE { - handle_table.Unreserve(*out); + handle_table.Unreserve(system.Kernel(), *out); }; // Accept the session. KAutoObject* session; - if (port->IsLight()) { - session = port->AcceptLightSession(); + if (port->IsLight(system.Kernel())) { + session = port->AcceptLightSession(system.Kernel()); } else { - session = port->AcceptSession(); + session = port->AcceptSession(system.Kernel()); } // Ensure we accepted successfully. R_UNLESS(session != nullptr, ResultNotFound); // Register the session. - handle_table.Register(*out, session); - session->Close(); + handle_table.Register(system.Kernel(), *out, session); + session->Close(system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_shared_memory.cpp b/src/core/hle/kernel/svc/svc_shared_memory.cpp index 3ca07abe8b..66cf5902ec 100644 --- a/src/core/hle/kernel/svc/svc_shared_memory.cpp +++ b/src/core/hle/kernel/svc/svc_shared_memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -49,18 +49,18 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u auto& page_table = process.GetPageTable(); // Get the shared memory. - KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); + KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(system.Kernel(), shmem_handle); R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion); // Add the shared memory to the process. - R_TRY(process.AddSharedMemory(shmem.GetPointerUnsafe(), address, size)); + R_TRY(process.AddSharedMemory(system.Kernel(), shmem.GetPointerUnsafe(), address, size)); // Ensure that we clean up the shared memory if we fail to map it. ON_RESULT_FAILURE { - process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); + process.RemoveSharedMemory(system.Kernel(), shmem.GetPointerUnsafe(), address, size); }; // Map the shared memory. @@ -79,7 +79,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, auto& page_table = process.GetPageTable(); // Get the shared memory. - KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); + KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(system.Kernel(), shmem_handle); R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. @@ -89,7 +89,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, R_TRY(shmem->Unmap(process, address, size)); // Remove the shared memory from the process. - process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); + process.RemoveSharedMemory(system.Kernel(), shmem.GetPointerUnsafe(), address, size); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index fdd4408d4d..1b29fd5865 100644 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -20,7 +20,7 @@ Result CloseHandle(Core::System& system, Handle handle) { LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); // Remove the handle. - R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(handle), + R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(system.Kernel(), handle), ResultInvalidHandle); R_SUCCEED(); @@ -35,17 +35,17 @@ Result ResetSignal(Core::System& system, Handle handle) { // Try to reset as readable event. { - KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(handle); + KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(system.Kernel(), handle); if (readable_event.IsNotNull()) { - R_RETURN(readable_event->Reset()); + R_RETURN(readable_event->Reset(system.Kernel())); } } // Try to reset as process. { - KScopedAutoObject process = handle_table.GetObject<KProcess>(handle); + KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), handle); if (process.IsNotNull()) { - R_RETURN(process->Reset()); + R_RETURN(process->Reset(system.Kernel())); } } @@ -62,35 +62,30 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); // Get the synchronization context. - auto& kernel = system.Kernel(); - auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); - auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer(); - auto handles = GetCurrentThread(kernel).GetHandleBuffer(); + auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); + auto objs = GetCurrentThread(system.Kernel()).GetSynchronizationObjectBuffer(); + auto handles = GetCurrentThread(system.Kernel()).GetHandleBuffer(); // Copy user handles. if (num_handles > 0) { // Get the handles. - R_UNLESS(GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(), - sizeof(Handle) * num_handles), - ResultInvalidPointer); + R_UNLESS(GetCurrentMemory(system.Kernel()).ReadBlock(user_handles, handles.data(), sizeof(Handle) * num_handles), ResultInvalidPointer); // Convert the handles to objects. - R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( - objs.data(), handles.data(), num_handles), - ResultInvalidHandle); + R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(system.Kernel(), objs.data(), handles.data(), num_handles), ResultInvalidHandle); } // Ensure handles are closed when we're done. SCOPE_EXIT { for (auto i = 0; i < num_handles; ++i) { - objs[i]->Close(); + objs[i]->Close(system.Kernel()); } }; // Convert the timeout from nanoseconds to ticks. s64 timeout; if (timeout_ns > 0) { - u64 ticks = kernel.HardwareTimer().GetTick(); + u64 ticks = system.Kernel().HardwareTimer().GetTick(); ticks += timeout_ns; ticks += 2; @@ -100,7 +95,7 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha } // Wait on the objects. - Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout); + Result res = KSynchronizationObject::Wait(system.Kernel(), out_index, objs.data(), num_handles, timeout); R_SUCCEED_IF(res == ResultSessionClosed); R_RETURN(res); @@ -111,31 +106,28 @@ Result CancelSynchronization(Core::System& system, Handle handle) { LOG_TRACE(Kernel_SVC, "called handle={:#X}", handle); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Cancel the thread's wait. - thread->WaitCancel(); + thread->WaitCancel(system.Kernel()); R_SUCCEED(); } void SynchronizePreemptionState(Core::System& system) { - auto& kernel = system.Kernel(); - // Lock the scheduler. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{system.Kernel()}; // If the current thread is pinned, unpin it. - KProcess* cur_process = GetCurrentProcessPointer(kernel); - const auto core_id = GetCurrentCoreId(kernel); + KProcess* cur_process = GetCurrentProcessPointer(system.Kernel()); + const auto core_id = GetCurrentCoreId(system.Kernel()); - if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(kernel)) { + if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(system.Kernel())) { // Clear the current thread's interrupt flag. - GetCurrentThread(kernel).ClearInterruptFlag(); + GetCurrentThread(system.Kernel()).ClearInterruptFlag(system.Kernel()); // Unpin the current thread. - cur_process->UnpinCurrentThread(); + cur_process->UnpinCurrentThread(system.Kernel()); } } diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index 1aa6f87c04..b1159020d3 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -46,7 +46,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); // Reserve a new thread from the process resource limit (waiting up to 100ms). - KScopedResourceReservation thread_reservation(std::addressof(process), + KScopedResourceReservation thread_reservation(system.Kernel(), std::addressof(process), LimitableResource::ThreadCountMax, 1, kernel.HardwareTimer().GetTick() + 100000000); R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached); @@ -55,7 +55,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u KThread* thread = KThread::Create(kernel); R_UNLESS(thread != nullptr, ResultOutOfResource) SCOPE_EXIT { - thread->Close(); + thread->Close(system.Kernel()); }; // Initialize the thread. @@ -69,13 +69,13 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u thread_reservation.Commit(); // Clone the current fpu status to the new thread. - thread->CloneFpuStatus(); + thread->CloneFpuStatus(system.Kernel()); // Register the new thread. KThread::Register(kernel, thread); // Add the thread to the handle table. - R_TRY(process.GetHandleTable().Add(out_handle, thread)); + R_TRY(process.GetHandleTable().Add(system.Kernel(), out_handle, thread)); // Pass the thread handle to the thread local region. process.GetMemory().Write32(GetInteger(thread->GetTlsAddress()) + 0x110, *out_handle); @@ -88,12 +88,11 @@ Result StartThread(Core::System& system, Handle thread_handle) { LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Try to start the thread. - R_TRY(thread->Run()); + R_TRY(thread->Run(system.Kernel())); R_SUCCEED(); } @@ -102,7 +101,7 @@ Result StartThread(Core::System& system, Handle thread_handle) { void ExitThread(Core::System& system) { auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); system.GlobalSchedulerContext().RemoveThread(current_thread); - current_thread->Exit(); + current_thread->Exit(system.Kernel()); } /// Sleep the current thread @@ -130,7 +129,7 @@ void SleepThread(Core::System& system, s64 ns) { // Sleep. // NOTE: Nintendo does not check the result of this sleep. - static_cast<void>(GetCurrentThread(kernel).Sleep(timeout)); + static_cast<void>(GetCurrentThread(kernel).Sleep(kernel, timeout)); } else if (yield_type == Svc::YieldType::WithoutCoreMigration) { KScheduler::YieldWithoutCoreMigration(kernel); } else if (yield_type == Svc::YieldType::WithCoreMigration) { @@ -144,27 +143,23 @@ void SleepThread(Core::System& system, s64 ns) { /// Gets the thread context Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_handle) { - LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle={:#X}", out_context, - thread_handle); - - auto& kernel = system.Kernel(); + LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle={:#X}", out_context, thread_handle); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(kernel).GetHandleTable().GetObject<KThread>(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Require the handle be to a non-current thread in the current process. - R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(kernel), ResultInvalidHandle); - R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultBusy); + R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()), ResultInvalidHandle); + R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy); // Get the thread context. Svc::ThreadContext context{}; - R_TRY(thread->GetThreadContext3(std::addressof(context))); + R_TRY(thread->GetThreadContext3(system.Kernel(), std::addressof(context))); // Copy the thread context to user space. R_UNLESS( - GetCurrentMemory(kernel).WriteBlock(out_context, std::addressof(context), sizeof(context)), + GetCurrentMemory(system.Kernel()).WriteBlock(out_context, std::addressof(context), sizeof(context)), ResultInvalidPointer); R_SUCCEED(); @@ -175,8 +170,7 @@ Result GetThreadPriority(Core::System& system, s32* out_priority, Handle handle) LOG_TRACE(Kernel_SVC, "called"); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the thread's priority. @@ -195,11 +189,11 @@ Result SetThreadPriority(Core::System& system, Handle thread_handle, s32 priorit R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); // Get the thread from its handle. - KScopedAutoObject thread = process.GetHandleTable().GetObject<KThread>(thread_handle); + KScopedAutoObject thread = process.GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Set the thread priority. - thread->SetBasePriority(priority); + thread->SetBasePriority(system.Kernel(), priority); R_SUCCEED(); } @@ -248,12 +242,11 @@ Result GetThreadCoreMask(Core::System& system, s32* out_core_id, u64* out_affini LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the core mask. - R_RETURN(thread->GetCoreMask(out_core_id, out_affinity_mask)); + R_RETURN(thread->GetCoreMask(system.Kernel(), out_core_id, out_affinity_mask)); } Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, @@ -279,18 +272,17 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id // Get the thread from its handle. KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Set the core mask. - R_RETURN(thread->SetCoreMask(core_id, affinity_mask)); + R_RETURN(thread->SetCoreMask(system.Kernel(), core_id, affinity_mask)); } /// Get the ID for the specified thread. Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the thread's id. diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp index 2ea0d44215..e539eee911 100644 --- a/src/core/hle/kernel/svc/svc_transfer_memory.cpp +++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -43,8 +46,7 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 auto& handle_table = process.GetHandleTable(); // Reserve a new transfer memory from the process resource limit. - KScopedResourceReservation trmem_reservation(std::addressof(process), - LimitableResource::TransferMemoryCountMax); + KScopedResourceReservation trmem_reservation(system.Kernel(), std::addressof(process), LimitableResource::TransferMemoryCountMax); R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); // Create the transfer memory. @@ -53,14 +55,14 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 // Ensure the only reference is in the handle table when we're done. SCOPE_EXIT { - trmem->Close(); + trmem->Close(system.Kernel()); }; // Ensure that the region is in range. R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory); // Initialize the transfer memory. - R_TRY(trmem->Initialize(address, size, map_perm)); + R_TRY(trmem->Initialize(system.Kernel(), address, size, map_perm)); // Commit the reservation. trmem_reservation.Commit(); @@ -69,7 +71,7 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 KTransferMemory::Register(kernel, trmem); // Add the transfer memory to the handle table. - R_RETURN(handle_table.Add(out, trmem)); + R_RETURN(handle_table.Add(system.Kernel(), out, trmem)); } Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size, @@ -86,7 +88,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add // Get the transfer memory. KScopedAutoObject trmem = GetCurrentProcess(system.Kernel()) .GetHandleTable() - .GetObject<KTransferMemory>(trmem_handle); + .GetObject<KTransferMemory>(system.Kernel(), trmem_handle); R_UNLESS(trmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. @@ -96,7 +98,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add ResultInvalidMemoryRegion); // Map the transfer memory. - R_TRY(trmem->Map(address, size, map_perm)); + R_TRY(trmem->Map(system.Kernel(), address, size, map_perm)); // We succeeded. R_SUCCEED(); @@ -113,7 +115,7 @@ Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t a // Get the transfer memory. KScopedAutoObject trmem = GetCurrentProcess(system.Kernel()) .GetHandleTable() - .GetObject<KTransferMemory>(trmem_handle); + .GetObject<KTransferMemory>(system.Kernel(), trmem_handle); R_UNLESS(trmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. @@ -123,7 +125,7 @@ Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t a ResultInvalidMemoryRegion); // Unmap the transfer memory. - R_TRY(trmem->Unmap(address, size)); + R_TRY(trmem->Unmap(system.Kernel(), address, size)); R_SUCCEED(); } diff --git a/src/core/hle/service/acc/async_context.cpp b/src/core/hle/service/acc/async_context.cpp index c9e0af90ce..c767e46e8f 100644 --- a/src/core/hle/service/acc/async_context.cpp +++ b/src/core/hle/service/acc/async_context.cpp @@ -1,3 +1,6 @@ +// 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 @@ -64,7 +67,7 @@ void IAsyncContext::GetResult(HLERequestContext& ctx) { void IAsyncContext::MarkComplete() { is_complete.store(true); - completion_event->Signal(); + completion_event->Signal(system.Kernel()); } } // namespace Service::Account diff --git a/src/core/hle/service/am/applet.cpp b/src/core/hle/service/am/applet.cpp index 2ae3102aff..efedcc5692 100644 --- a/src/core/hle/service/am/applet.cpp +++ b/src/core/hle/service/am/applet.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator @@ -52,7 +52,7 @@ void Applet::UpdateSuspensionStateLocked(bool force_message) { // Signal if the focus state was changed or the process state was changed. if (update_requested_focus_state || was_changed || force_message) { - lifecycle_manager.SignalSystemEventIfNeeded(); + lifecycle_manager.SignalSystemEventIfNeeded(context.kernel); } } @@ -76,7 +76,7 @@ void Applet::SetInteractibleLocked(bool interactible) { void Applet::OnProcessTerminatedLocked() { is_completed = true; - state_changed_event.Signal(); + state_changed_event.Signal(context.kernel); } } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_data_broker.cpp b/src/core/hle/service/am/applet_data_broker.cpp index fff78c5afb..f75baac282 100644 --- a/src/core/hle/service/am/applet_data_broker.cpp +++ b/src/core/hle/service/am/applet_data_broker.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,22 +14,23 @@ namespace Service::AM { AppletStorageChannel::AppletStorageChannel(KernelHelpers::ServiceContext& context) - : m_event(context) {} + : m_event(context) +{} AppletStorageChannel::~AppletStorageChannel() = default; -void AppletStorageChannel::Push(std::shared_ptr<IStorage> storage) { +void AppletStorageChannel::Push(Kernel::KernelCore& kernel, std::shared_ptr<IStorage> storage) { std::scoped_lock lk{m_lock}; m_data.emplace_back(std::move(storage)); - m_event.Signal(); + m_event.Signal(kernel); } -Result AppletStorageChannel::Pop(std::shared_ptr<IStorage>* out_storage) { +Result AppletStorageChannel::Pop(Kernel::KernelCore& kernel, std::shared_ptr<IStorage>* out_storage) { std::scoped_lock lk{m_lock}; SCOPE_EXIT { if (m_data.empty()) { - m_event.Clear(); + m_event.Clear(kernel); } }; diff --git a/src/core/hle/service/am/applet_data_broker.h b/src/core/hle/service/am/applet_data_broker.h index 2718f608ad..36ce8a24d4 100644 --- a/src/core/hle/service/am/applet_data_broker.h +++ b/src/core/hle/service/am/applet_data_broker.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,8 +25,8 @@ public: explicit AppletStorageChannel(KernelHelpers::ServiceContext& ctx); ~AppletStorageChannel(); - void Push(std::shared_ptr<IStorage> storage); - Result Pop(std::shared_ptr<IStorage>* out_storage); + void Push(Kernel::KernelCore& kernel, std::shared_ptr<IStorage> storage); + Result Pop(Kernel::KernelCore& kernel, std::shared_ptr<IStorage>* out_storage); Kernel::KReadableEvent* GetEvent(); private: diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp index c2920f91ae..2388faa541 100644 --- a/src/core/hle/service/am/applet_manager.cpp +++ b/src/core/hle/service/am/applet_manager.cpp @@ -34,8 +34,7 @@ struct LaunchParameterAccountPreselectedUser { }; static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); -AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system, - std::shared_ptr<Applet>& applet) { +AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system, std::shared_ptr<Applet>& applet) { applet->caller_applet_broker = std::make_shared<AppletDataBroker>(system); return applet->caller_applet_broker->GetInData(); } @@ -52,7 +51,7 @@ void PushInShowQlaunch(Core::System& system, AppletStorageChannel& channel) { std::vector<u8> argument_data(sizeof(arguments)); std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); - channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(argument_data))); } void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) { @@ -68,8 +67,8 @@ void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) { std::vector<u8> argument_data(sizeof(arguments)); std::vector<u8> settings_data{2}; std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); - channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); - channel.Push(std::make_shared<IStorage>(system, std::move(settings_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(settings_data))); } void PushInShowController(Core::System& system, AppletStorageChannel& channel) { @@ -116,9 +115,9 @@ void PushInShowController(Core::System& system, AppletStorageChannel& channel) { std::memcpy(private_args_data.data(), &private_args, sizeof(private_args)); std::memcpy(user_args_data.data(), &user_args, sizeof(user_args)); - channel.Push(std::make_shared<IStorage>(system, std::move(common_args_data))); - channel.Push(std::make_shared<IStorage>(system, std::move(private_args_data))); - channel.Push(std::make_shared<IStorage>(system, std::move(user_args_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(common_args_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(private_args_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(user_args_data))); } void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) { @@ -146,8 +145,8 @@ void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) std::vector<u8> settings_data(sizeof(amiibo_settings)); std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings)); - channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); - channel.Push(std::make_shared<IStorage>(system, std::move(settings_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(settings_data))); } void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel) { @@ -169,7 +168,7 @@ void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel) std::vector<u8> argument_data(sizeof(mii_arguments)); std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments)); - channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(argument_data))); } void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& channel) { @@ -222,9 +221,9 @@ void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& chan std::memcpy(work_buffer.data(), initial_string.data(), swkbd_config.initial_string_length * sizeof(char16_t)); - channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); - channel.Push(std::make_shared<IStorage>(system, std::move(swkbd_data))); - channel.Push(std::make_shared<IStorage>(system, std::move(work_buffer))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(swkbd_data))); + channel.Push(system.Kernel(), std::make_shared<IStorage>(system, std::move(work_buffer))); } } // namespace @@ -268,7 +267,7 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) { if (Settings::values.enable_overlay && m_window_system->GetOverlayDisplayApplet() == nullptr) { if (auto overlay_process = CreateProcess(m_system, static_cast<u64>(AppletProgramId::OverlayDisplay), 0, 0)) { - auto overlay_applet = std::make_shared<Applet>(m_system, std::move(overlay_process), false); + auto overlay_applet = std::make_shared<Applet>(m_system, std::make_unique<Service::Process>(*std::move(overlay_process)), false); overlay_applet->program_id = static_cast<u64>(AppletProgramId::OverlayDisplay); overlay_applet->applet_id = AppletId::OverlayDisplay; overlay_applet->type = AppletType::OverlayApplet; @@ -340,7 +339,7 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) { } // Applet was started by frontend, so it is foreground. - applet->lifecycle_manager.SetFocusState(FocusState::InFocus); + applet->lifecycle_manager.SetFocusState(m_system.Kernel(), FocusState::InFocus); if (applet->applet_id == AppletId::QLaunch) { applet->lifecycle_manager.SetFocusHandlingMode(false); diff --git a/src/core/hle/service/am/button_poller.cpp b/src/core/hle/service/am/button_poller.cpp index 069a1934d4..6999acfa12 100644 --- a/src/core/hle/service/am/button_poller.cpp +++ b/src/core/hle/service/am/button_poller.cpp @@ -1,9 +1,11 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include <thread> +#include "common/thread.h" #include "core/core.h" #include "core/hle/service/am/am_types.h" #include "core/hle/service/am/button_poller.h" @@ -34,16 +36,15 @@ ButtonPressDuration ClassifyPressDuration(std::chrono::steady_clock::time_point } // namespace -ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) - : m_window_system(window_system) { +ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) { // TODO: am reads this from the home button state in hid, which is controller-agnostic. Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = - [this](Core::HID::ControllerTriggerType type) { - if (type == Core::HID::ControllerTriggerType::Button) { - this->OnButtonStateChanged(); - } - }, + .on_change = [this, &window_system](Core::HID::ControllerTriggerType type) { + if (type == Core::HID::ControllerTriggerType::Button) { + std::unique_lock lk{m_mutex}; + OnButtonStateChanged(window_system); + } + }, .is_npad_service = true, }; @@ -52,25 +53,35 @@ ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) m_player1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); m_player1_key = m_player1->SetCallback(engine_callback); - m_thread = std::thread([this] { this->ThreadLoop(); }); + m_thread = std::jthread([this, &window_system](std::stop_token stop_token) { + Common::SetCurrentThreadName("ButtonPoller"); + while (!stop_token.stop_requested()) { + using namespace std::chrono_literals; + std::unique_lock lk{m_mutex}; + m_cv.wait_for(lk, 50ms); + if (stop_token.stop_requested()) + break; + OnButtonStateChanged(window_system); + std::this_thread::sleep_for(5ms); + } + }); } ButtonPoller::~ButtonPoller() { m_handheld->DeleteCallback(m_handheld_key); m_player1->DeleteCallback(m_player1_key); - m_stop = true; m_cv.notify_all(); if (m_thread.joinable()) { + m_thread.request_stop(); m_thread.join(); } } -void ButtonPoller::OnButtonStateChanged() { - std::lock_guard lk{m_mutex}; - const bool home_button = - m_handheld->GetHomeButtons().home.Value() || m_player1->GetHomeButtons().home.Value(); - const bool capture_button = m_handheld->GetCaptureButtons().capture.Value() || - m_player1->GetCaptureButtons().capture.Value(); +void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) { + auto const home_button = m_handheld->GetHomeButtons().home.Value() + || m_player1->GetHomeButtons().home.Value(); + auto const capture_button = m_handheld->GetCaptureButtons().capture.Value() + || m_player1->GetCaptureButtons().capture.Value(); // Buttons pressed which were not previously pressed if (home_button && !m_home_button_press_start) { @@ -90,7 +101,7 @@ void ButtonPoller::OnButtonStateChanged() { if (home_button && m_home_button_press_start && !m_home_button_long_sent) { const auto duration = ClassifyPressDuration(*m_home_button_press_start); if (duration != ButtonPressDuration::ShortPressing) { - m_window_system.OnSystemButtonPress(SystemButtonType::HomeButtonLongPressing); + window_system.OnSystemButtonPress(SystemButtonType::HomeButtonLongPressing); m_home_button_long_sent = true; } } @@ -98,7 +109,7 @@ void ButtonPoller::OnButtonStateChanged() { if (capture_button && m_capture_button_press_start && !m_capture_button_long_sent) { const auto duration = ClassifyPressDuration(*m_capture_button_press_start); if (duration != ButtonPressDuration::ShortPressing) { - m_window_system.OnSystemButtonPress(SystemButtonType::CaptureButtonLongPressing); + window_system.OnSystemButtonPress(SystemButtonType::CaptureButtonLongPressing); m_capture_button_long_sent = true; } } @@ -107,9 +118,8 @@ void ButtonPoller::OnButtonStateChanged() { if (!home_button && m_home_button_press_start) { if(!m_home_button_long_sent) { const auto duration = ClassifyPressDuration(*m_home_button_press_start); - m_window_system.OnSystemButtonPress( - duration == ButtonPressDuration::ShortPressing ? SystemButtonType::HomeButtonShortPressing - : SystemButtonType::HomeButtonLongPressing); + window_system.OnSystemButtonPress(duration == ButtonPressDuration::ShortPressing + ? SystemButtonType::HomeButtonShortPressing : SystemButtonType::HomeButtonLongPressing); } m_home_button_press_start = std::nullopt; m_home_button_long_sent = false; @@ -117,9 +127,8 @@ void ButtonPoller::OnButtonStateChanged() { if (!capture_button && m_capture_button_press_start) { if (!m_capture_button_long_sent) { const auto duration = ClassifyPressDuration(*m_capture_button_press_start); - m_window_system.OnSystemButtonPress( - duration == ButtonPressDuration::ShortPressing ? SystemButtonType::CaptureButtonShortPressing - : SystemButtonType::CaptureButtonLongPressing); + window_system.OnSystemButtonPress(duration == ButtonPressDuration::ShortPressing + ? SystemButtonType::CaptureButtonShortPressing : SystemButtonType::CaptureButtonLongPressing); } m_capture_button_press_start = std::nullopt; m_capture_button_long_sent = false; @@ -130,16 +139,4 @@ void ButtonPoller::OnButtonStateChanged() { // } } -void ButtonPoller::ThreadLoop() { - using namespace std::chrono_literals; - std::unique_lock lk{m_mutex}; - while (!m_stop) { - m_cv.wait_for(lk, 50ms); - if (m_stop) break; - lk.unlock(); - OnButtonStateChanged(); - lk.lock(); - } -} - } // namespace Service::AM diff --git a/src/core/hle/service/am/button_poller.h b/src/core/hle/service/am/button_poller.h index 12e7035aa1..11d147d328 100644 --- a/src/core/hle/service/am/button_poller.h +++ b/src/core/hle/service/am/button_poller.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -30,31 +30,23 @@ class ButtonPoller { public: explicit ButtonPoller(Core::System& system, WindowSystem& window_system); ~ButtonPoller(); + void OnButtonStateChanged(WindowSystem& window_system); private: - void OnButtonStateChanged(); - void ThreadLoop(); - -private: - WindowSystem& m_window_system; - - Core::HID::EmulatedController* m_handheld{}; - int m_handheld_key{}; - Core::HID::EmulatedController* m_player1{}; - int m_player1_key{}; - + std::mutex m_mutex; + std::condition_variable m_cv; + std::jthread m_thread; std::optional<std::chrono::steady_clock::time_point> m_home_button_press_start{}; std::optional<std::chrono::steady_clock::time_point> m_capture_button_press_start{}; std::optional<std::chrono::steady_clock::time_point> m_power_button_press_start{}; - bool m_home_button_long_sent{}; - bool m_capture_button_long_sent{}; - bool m_power_button_long_sent{}; - - std::thread m_thread; - std::atomic<bool> m_stop{false}; - std::condition_variable m_cv; - std::mutex m_mutex; + Core::HID::EmulatedController* m_handheld{}; + Core::HID::EmulatedController* m_player1{}; + int32_t m_handheld_key{}; + int32_t m_player1_key{}; + bool m_home_button_long_sent : 1 = false; + bool m_capture_button_long_sent : 1 = false; + bool m_power_button_long_sent : 1 = false; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/event_observer.cpp b/src/core/hle/service/am/event_observer.cpp index 5d1d303ed3..32cb35ee30 100644 --- a/src/core/hle/service/am/event_observer.cpp +++ b/src/core/hle/service/am/event_observer.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,18 +18,30 @@ enum class UserDataTag : u32 { }; EventObserver::EventObserver(Core::System& system, WindowSystem& window_system) - : m_system(system), m_context(system, "am:EventObserver"), m_window_system(window_system), - m_wakeup_event(m_context), m_wakeup_holder(m_wakeup_event.GetHandle()) { + : m_system(system), m_context(system, "am:EventObserver") + , m_window_system(window_system) + , m_wakeup_event(m_context) + , m_wakeup_holder(m_wakeup_event.GetHandle()) +{ m_window_system.SetEventObserver(this); m_wakeup_holder.SetUserData(static_cast<uintptr_t>(UserDataTag::WakeupEvent)); m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait)); - m_thread = std::thread([&] { this->ThreadFunc(); }); + m_thread = std::thread([this] { + Common::SetCurrentThreadName("am:EventObserver"); + while (true) { + auto* signaled_holder = this->WaitSignaled(); + if (!signaled_holder) { + break; + } + this->Process(signaled_holder); + } + }); } EventObserver::~EventObserver() { // Signal thread and wait for processing to finish. m_stop_source.request_stop(); - m_wakeup_event.Signal(); + m_wakeup_event.Signal(m_system.Kernel()); m_thread.join(); // Free remaining owned sessions. @@ -61,11 +76,11 @@ void EventObserver::TrackAppletProcess(Applet& applet) { } // Signal wakeup. - m_wakeup_event.Signal(); + m_wakeup_event.Signal(m_system.Kernel()); } void EventObserver::RequestUpdate() { - m_wakeup_event.Signal(); + m_wakeup_event.Signal(m_system.Kernel()); } void EventObserver::LinkDeferred() { @@ -106,7 +121,7 @@ void EventObserver::Process(MultiWaitHolder* holder) { } void EventObserver::OnWakeupEvent(MultiWaitHolder* holder) { - m_wakeup_event.Clear(); + m_wakeup_event.Clear(m_system.Kernel()); // Perform recalculation. m_window_system.Update(); @@ -146,17 +161,4 @@ void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) { delete holder; } -void EventObserver::ThreadFunc() { - Common::SetCurrentThreadName("am:EventObserver"); - - while (true) { - auto* signaled_holder = this->WaitSignaled(); - if (!signaled_holder) { - break; - } - - this->Process(signaled_holder); - } -} - } // namespace Service::AM diff --git a/src/core/hle/service/am/event_observer.h b/src/core/hle/service/am/event_observer.h index 3e52e8494d..a0fa13f823 100644 --- a/src/core/hle/service/am/event_observer.h +++ b/src/core/hle/service/am/event_observer.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -42,9 +45,6 @@ private: void DestroyAppletProcessHolderLocked(ProcessHolder* holder); private: - void ThreadFunc(); - -private: // System reference and context. Core::System& m_system; KernelHelpers::ServiceContext m_context; diff --git a/src/core/hle/service/am/frontend/applet_general.cpp b/src/core/hle/service/am/frontend/applet_general.cpp index 5345fdec33..22cad54b66 100644 --- a/src/core/hle/service/am/frontend/applet_general.cpp +++ b/src/core/hle/service/am/frontend/applet_general.cpp @@ -20,16 +20,16 @@ namespace Service::AM::Frontend { constexpr Result ERROR_INVALID_PIN{ErrorModule::PCTL, 221}; -static void LogCurrentStorage(std::shared_ptr<Applet> applet, std::string_view prefix) { +static void LogCurrentStorage(Kernel::KernelCore& kernel, std::shared_ptr<Applet> applet, std::string_view prefix) { std::shared_ptr<IStorage> storage; - while (R_SUCCEEDED(applet->caller_applet_broker->GetInData().Pop(&storage))) { + while (R_SUCCEEDED(applet->caller_applet_broker->GetInData().Pop(kernel, &storage))) { const auto data = storage->GetData(); LOG_INFO(Service_AM, "called (STUBBED), during {} received normal data with size={:08X}, data={}", prefix, data.size(), Common::HexToString(data)); } - while (R_SUCCEEDED(applet->caller_applet_broker->GetInteractiveInData().Pop(&storage))) { + while (R_SUCCEEDED(applet->caller_applet_broker->GetInteractiveInData().Pop(kernel, &storage))) { const auto data = storage->GetData(); LOG_INFO(Service_AM, "called (STUBBED), during {} received interactive data with size={:08X}, data={}", @@ -219,7 +219,7 @@ void StubApplet::Initialize() { LOG_WARNING(Service_AM, "called (STUBBED)"); FrontendApplet::Initialize(); - LogCurrentStorage(applet.lock(), "Initialize"); + LogCurrentStorage(system.Kernel(), applet.lock(), "Initialize"); } Result StubApplet::GetStatus() const { @@ -229,7 +229,7 @@ Result StubApplet::GetStatus() const { void StubApplet::ExecuteInteractive() { LOG_WARNING(Service_AM, "called (STUBBED)"); - LogCurrentStorage(applet.lock(), "ExecuteInteractive"); + LogCurrentStorage(system.Kernel(), applet.lock(), "ExecuteInteractive"); PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); PushInteractiveOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); @@ -238,7 +238,7 @@ void StubApplet::ExecuteInteractive() { void StubApplet::Execute() { LOG_WARNING(Service_AM, "called (STUBBED)"); - LogCurrentStorage(applet.lock(), "Execute"); + LogCurrentStorage(system.Kernel(), applet.lock(), "Execute"); PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); PushInteractiveOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); diff --git a/src/core/hle/service/am/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp index 2ff2bcdbb6..407ca10602 100644 --- a/src/core/hle/service/am/frontend/applets.cpp +++ b/src/core/hle/service/am/frontend/applets.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include <cstring> @@ -52,22 +52,22 @@ void FrontendApplet::Initialize() { std::shared_ptr<IStorage> FrontendApplet::PopInData() { std::shared_ptr<IStorage> ret; - applet.lock()->caller_applet_broker->GetInData().Pop(&ret); + applet.lock()->caller_applet_broker->GetInData().Pop(system.Kernel(), &ret); return ret; } std::shared_ptr<IStorage> FrontendApplet::PopInteractiveInData() { std::shared_ptr<IStorage> ret; - applet.lock()->caller_applet_broker->GetInteractiveInData().Pop(&ret); + applet.lock()->caller_applet_broker->GetInteractiveInData().Pop(system.Kernel(), &ret); return ret; } void FrontendApplet::PushOutData(std::shared_ptr<IStorage> storage) { - applet.lock()->caller_applet_broker->GetOutData().Push(storage); + applet.lock()->caller_applet_broker->GetOutData().Push(system.Kernel(), storage); } void FrontendApplet::PushInteractiveOutData(std::shared_ptr<IStorage> storage) { - applet.lock()->caller_applet_broker->GetInteractiveOutData().Push(storage); + applet.lock()->caller_applet_broker->GetInteractiveOutData().Push(system.Kernel(), storage); } void FrontendApplet::Exit() { @@ -75,7 +75,7 @@ void FrontendApplet::Exit() { std::scoped_lock lk{applet_->lock}; applet_->is_completed = true; - applet_->state_changed_event.Signal(); + applet_->state_changed_event.Signal(system.Kernel()); } FrontendAppletSet::FrontendAppletSet() = default; diff --git a/src/core/hle/service/am/library_applet_storage.cpp b/src/core/hle/service/am/library_applet_storage.cpp index 0412c215d5..8b14511c72 100644 --- a/src/core/hle/service/am/library_applet_storage.cpp +++ b/src/core/hle/service/am/library_applet_storage.cpp @@ -1,7 +1,11 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/kernel/kernel.h" #include "core/hle/service/am/am_results.h" #include "core/hle/service/am/library_applet_storage.h" #include "core/memory.h" @@ -55,15 +59,18 @@ private: class TransferMemoryLibraryAppletStorage : public LibraryAppletStorage { public: - explicit TransferMemoryLibraryAppletStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, bool is_writable, - s64 size) - : m_memory(memory), m_trmem(trmem), m_is_writable(is_writable), m_size(size) { - m_trmem->Open(); + explicit TransferMemoryLibraryAppletStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, bool is_writable, s64 size) + : m_kernel{kernel} + , m_memory(memory) + , m_trmem(trmem) + , m_is_writable(is_writable) + , m_size(size) + { + m_trmem->Open(m_kernel); } ~TransferMemoryLibraryAppletStorage() { - m_trmem->Close(); + m_trmem->Close(m_kernel); m_trmem = nullptr; } @@ -93,6 +100,7 @@ public: } protected: + Kernel::KernelCore& m_kernel; Core::Memory::Memory& m_memory; Kernel::KTransferMemory* m_trmem; bool m_is_writable; @@ -101,9 +109,9 @@ protected: class HandleLibraryAppletStorage : public TransferMemoryLibraryAppletStorage { public: - explicit HandleLibraryAppletStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, s64 size) - : TransferMemoryLibraryAppletStorage(memory, trmem, true, size) {} + explicit HandleLibraryAppletStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, s64 size) + : TransferMemoryLibraryAppletStorage(kernel, memory, trmem, true, size) + {} ~HandleLibraryAppletStorage() = default; Kernel::KTransferMemory* GetHandle() override { @@ -125,16 +133,12 @@ std::shared_ptr<LibraryAppletStorage> CreateStorage(std::vector<u8>&& data) { return std::make_shared<BufferLibraryAppletStorage>(std::move(data)); } -std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, - bool is_writable, s64 size) { - return std::make_shared<TransferMemoryLibraryAppletStorage>(memory, trmem, is_writable, size); +std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, bool is_writable, s64 size) { + return std::make_shared<TransferMemoryLibraryAppletStorage>(kernel, memory, trmem, is_writable, size); } -std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, - s64 size) { - return std::make_shared<HandleLibraryAppletStorage>(memory, trmem, size); +std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, s64 size) { + return std::make_shared<HandleLibraryAppletStorage>(kernel, memory, trmem, size); } } // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_storage.h b/src/core/hle/service/am/library_applet_storage.h index 7f53f3a9cd..cfdbef96d0 100644 --- a/src/core/hle/service/am/library_applet_storage.h +++ b/src/core/hle/service/am/library_applet_storage.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,6 +13,7 @@ class Memory; } namespace Kernel { +class KernelCore; class KTransferMemory; } @@ -27,10 +31,7 @@ public: }; std::shared_ptr<LibraryAppletStorage> CreateStorage(std::vector<u8>&& data); -std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, - bool is_writable, s64 size); -std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, s64 size); +std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, bool is_writable, s64 size); +std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, s64 size); } // namespace Service::AM diff --git a/src/core/hle/service/am/lifecycle_manager.cpp b/src/core/hle/service/am/lifecycle_manager.cpp index a79ef6f5f5..8d6965a06c 100644 --- a/src/core/hle/service/am/lifecycle_manager.cpp +++ b/src/core/hle/service/am/lifecycle_manager.cpp @@ -28,9 +28,9 @@ Event& LifecycleManager::GetHDCPStateChangedEvent() { return m_hdcp_state_changed_event; } -void LifecycleManager::PushUnorderedMessage(AppletMessage message) { +void LifecycleManager::PushUnorderedMessage(Kernel::KernelCore& kernel, AppletMessage message) { m_unordered_messages.push_back(message); - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } AppletMessage LifecycleManager::PopMessageInOrderOfPriority() { @@ -144,36 +144,36 @@ bool LifecycleManager::ShouldSignalSystemEvent() { m_has_album_screen_shot_taken || m_has_album_recording_saved; } -void LifecycleManager::OnOperationAndPerformanceModeChanged() { +void LifecycleManager::OnOperationAndPerformanceModeChanged(Kernel::KernelCore& kernel) { if (m_operation_mode_changed_notification_enabled) { m_has_operation_mode_changed = true; } if (m_performance_mode_changed_notification_enabled) { m_has_performance_mode_changed = true; } - m_operation_mode_changed_system_event.Signal(); - this->SignalSystemEventIfNeeded(); + m_operation_mode_changed_system_event.Signal(kernel); + this->SignalSystemEventIfNeeded(kernel); } -void LifecycleManager::SignalSystemEventIfNeeded() { +void LifecycleManager::SignalSystemEventIfNeeded(Kernel::KernelCore& kernel) { // Check our cached value for the system event. const bool applet_message_available = m_applet_message_available; // If it's not current, we need to do an update, either clearing or signaling. if (applet_message_available != this->ShouldSignalSystemEvent()) { if (!applet_message_available) { - m_system_event.Signal(); + m_system_event.Signal(kernel); m_applet_message_available = true; } else { - m_system_event.Clear(); + m_system_event.Clear(kernel); m_applet_message_available = false; } } } -bool LifecycleManager::PopMessage(AppletMessage* out_message) { +bool LifecycleManager::PopMessage(Kernel::KernelCore& kernel, AppletMessage* out_message) { const auto message = this->PopMessageInOrderOfPriority(); - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); *out_message = message; return message != AppletMessage::None; diff --git a/src/core/hle/service/am/lifecycle_manager.h b/src/core/hle/service/am/lifecycle_manager.h index a1ddb9e2df..615aeed591 100644 --- a/src/core/hle/service/am/lifecycle_manager.h +++ b/src/core/hle/service/am/lifecycle_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -66,17 +69,17 @@ public: return m_acknowledged_focus_state; } - void SetFocusState(FocusState state) { + void SetFocusState(Kernel::KernelCore& kernel, FocusState state) { if (m_requested_focus_state != state) { m_has_focus_state_changed = true; } m_requested_focus_state = state; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } - void RequestExit() { + void RequestExit(Kernel::KernelCore& kernel) { m_has_requested_exit = true; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } void RequestResumeNotification() { @@ -89,22 +92,22 @@ public: } } - void OnOperationAndPerformanceModeChanged(); + void OnOperationAndPerformanceModeChanged(Kernel::KernelCore& kernel); public: - void SetFocusStateChangedNotificationEnabled(bool enabled) { + void SetFocusStateChangedNotificationEnabled(Kernel::KernelCore& kernel, bool enabled) { m_focus_state_changed_notification_enabled = enabled; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } - void SetOperationModeChangedNotificationEnabled(bool enabled) { + void SetOperationModeChangedNotificationEnabled(Kernel::KernelCore& kernel, bool enabled) { m_operation_mode_changed_notification_enabled = enabled; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } - void SetPerformanceModeChangedNotificationEnabled(bool enabled) { + void SetPerformanceModeChangedNotificationEnabled(Kernel::KernelCore& kernel, bool enabled) { m_performance_mode_changed_notification_enabled = enabled; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } void SetResumeNotificationEnabled(bool enabled) { @@ -129,11 +132,11 @@ public: void RemoveForceResumeIfPossible(); bool IsRunnable() const; bool UpdateRequestedFocusState(); - void SignalSystemEventIfNeeded(); + void SignalSystemEventIfNeeded(Kernel::KernelCore& kernel); public: - void PushUnorderedMessage(AppletMessage message); - bool PopMessage(AppletMessage* out_message); + void PushUnorderedMessage(Kernel::KernelCore& kernel, AppletMessage message); + bool PopMessage(Kernel::KernelCore& kernel, AppletMessage* out_message); private: FocusState GetFocusStateWhileForegroundObscured() const; diff --git a/src/core/hle/service/am/process_creation.cpp b/src/core/hle/service/am/process_creation.cpp index b5e31353a2..e34e86a82c 100644 --- a/src/core/hle/service/am/process_creation.cpp +++ b/src/core/hle/service/am/process_creation.cpp @@ -1,6 +1,10 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include <optional> #include "core/core.h" #include "core/file_sys/content_archive.h" #include "core/file_sys/nca_metadata.h" @@ -16,7 +20,7 @@ namespace Service::AM { namespace { -FileSys::StorageId GetStorageIdForFrontendSlot( +[[nodiscard]] FileSys::StorageId GetStorageIdForFrontendSlot( std::optional<FileSys::ContentProviderUnionSlot> slot) { if (!slot.has_value()) { return FileSys::StorageId::None; @@ -36,31 +40,23 @@ FileSys::StorageId GetStorageIdForFrontendSlot( } } -std::unique_ptr<Process> CreateProcessImpl(std::unique_ptr<Loader::AppLoader>& out_loader, - Loader::ResultStatus& out_load_result, - Core::System& system, FileSys::VirtualFile file, - u64 program_id, u64 program_index) { +[[nodiscard]] inline std::optional<Process> CreateProcessImpl(std::unique_ptr<Loader::AppLoader>& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) { // Get the appropriate loader to parse this NCA. out_loader = Loader::GetLoader(system, file, program_id, program_index); - // Ensure we have a loader which can parse the NCA. - if (!out_loader) { - return nullptr; - } - - // Try to load the process. - auto process = std::make_unique<Process>(system); - if (process->Initialize(*out_loader, out_load_result)) { - return process; + if (out_loader) { + // Try to load the process. + auto process = std::make_optional<Process>(system); + if (process->Initialize(*out_loader, out_load_result)) { + return process; + } } - - return nullptr; + return std::nullopt; } } // Anonymous namespace -std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, - u8 minimum_key_generation, u8 maximum_key_generation) { +std::optional<Process> CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation) { // Attempt to load program NCA. FileSys::VirtualFile nca_raw{}; @@ -70,7 +66,7 @@ std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, // Ensure we retrieved a program NCA. if (!nca_raw) { - return nullptr; + return std::nullopt; } // Ensure we have a suitable version. @@ -79,9 +75,8 @@ std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, if (nca.GetStatus() == Loader::ResultStatus::Success && (nca.GetKeyGeneration() < minimum_key_generation || nca.GetKeyGeneration() > maximum_key_generation)) { - LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id, - nca.GetKeyGeneration()); - return nullptr; + LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id, nca.GetKeyGeneration()); + return std::nullopt; } } @@ -90,42 +85,32 @@ std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, return CreateProcessImpl(loader, status, system, nca_raw, program_id, 0); } -std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control, - std::unique_ptr<Loader::AppLoader>& out_loader, - Loader::ResultStatus& out_load_result, - Core::System& system, FileSys::VirtualFile file, - u64 program_id, u64 program_index) { - auto process = - CreateProcessImpl(out_loader, out_load_result, system, file, program_id, program_index); - if (!process) { - return nullptr; - } - - FileSys::NACP nacp; - if (out_loader->ReadControlData(nacp) == Loader::ResultStatus::Success) { - out_control = nacp.GetRawBytes(); - } else { - out_control.resize(sizeof(FileSys::RawNACP)); - std::fill(out_control.begin(), out_control.end(), (u8) 0); - } - - auto& storage = system.GetContentProviderUnion(); - Service::Glue::ApplicationLaunchProperty launch{}; - launch.title_id = process->GetProgramId(); +std::optional<Process> CreateApplicationProcess(std::vector<u8>& out_control, std::unique_ptr<Loader::AppLoader>& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) { + if (auto process = CreateProcessImpl(out_loader, out_load_result, system, file, program_id, program_index); process) { + FileSys::NACP nacp; + if (out_loader->ReadControlData(nacp) == Loader::ResultStatus::Success) { + out_control = nacp.GetRawBytes(); + } else { + out_control.resize(sizeof(FileSys::RawNACP)); + std::fill(out_control.begin(), out_control.end(), (u8) 0); + } - FileSys::PatchManager pm{launch.title_id, system.GetFileSystemController(), storage}; - launch.version = pm.GetGameVersion().value_or(0); + auto& storage = system.GetContentProviderUnion(); + Service::Glue::ApplicationLaunchProperty launch{}; + launch.title_id = process->GetProgramId(); - // TODO(DarkLordZach): When FSController/Game Card Support is added, if - // current_process_game_card use correct StorageId - launch.base_game_storage_id = GetStorageIdForFrontendSlot( - storage.GetSlotForEntry(launch.title_id, FileSys::ContentRecordType::Program)); - launch.update_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry( - FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program)); + FileSys::PatchManager pm{launch.title_id, system.GetFileSystemController(), storage}; + launch.version = pm.GetGameVersion().value_or(0); - system.GetARPManager().Register(launch.title_id, launch, out_control); + // TODO(DarkLordZach): When FSController/Game Card Support is added, if + // current_process_game_card use correct StorageId + launch.base_game_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry(launch.title_id, FileSys::ContentRecordType::Program)); + launch.update_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry(FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program)); - return process; + system.GetARPManager().Register(launch.title_id, launch, out_control); + return process; + } + return std::nullopt; } } // namespace Service::AM diff --git a/src/core/hle/service/am/process_creation.h b/src/core/hle/service/am/process_creation.h index 8cfb9e0c9e..57d8b8f815 100644 --- a/src/core/hle/service/am/process_creation.h +++ b/src/core/hle/service/am/process_creation.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -24,12 +27,7 @@ class Process; namespace Service::AM { -std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, - u8 minimum_key_generation, u8 maximum_key_generation); -std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control, - std::unique_ptr<Loader::AppLoader>& out_loader, - Loader::ResultStatus& out_load_result, - Core::System& system, FileSys::VirtualFile file, - u64 program_id, u64 program_index); +std::optional<Process> CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation); +std::optional<Process> CreateApplicationProcess(std::vector<u8>& out_control, std::unique_ptr<Loader::AppLoader>& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index); } // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_accessor.cpp b/src/core/hle/service/am/service/application_accessor.cpp index 88a1724fc6..f357871706 100644 --- a/src/core/hle/service/am/service/application_accessor.cpp +++ b/src/core/hle/service/am/service/application_accessor.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -69,7 +69,7 @@ Result IApplicationAccessor::RequestExit() { std::scoped_lock lk{m_applet->lock}; if (m_applet->exit_locked) { - m_applet->lifecycle_manager.RequestExit(); + m_applet->lifecycle_manager.RequestExit(system.Kernel()); m_applet->UpdateSuspensionStateLocked(true); } else { m_applet->process->Terminate(); diff --git a/src/core/hle/service/am/service/application_creator.cpp b/src/core/hle/service/am/service/application_creator.cpp index 81620a5067..983ac700bc 100644 --- a/src/core/hle/service/am/service/application_creator.cpp +++ b/src/core/hle/service/am/service/application_creator.cpp @@ -21,8 +21,7 @@ namespace Service::AM { namespace { -Result CreateGuestApplication(SharedPointer<IApplicationAccessor>* out_application_accessor, - Core::System& system, WindowSystem& window_system, u64 program_id) { +Result CreateGuestApplication(SharedPointer<IApplicationAccessor>* out_application_accessor, Core::System& system, WindowSystem& window_system, u64 program_id) { FileSys::VirtualFile nca_raw{}; // Get the program NCA from storage. @@ -35,11 +34,10 @@ Result CreateGuestApplication(SharedPointer<IApplicationAccessor>* out_applicati std::vector<u8> control; std::unique_ptr<Loader::AppLoader> loader; Loader::ResultStatus result; - auto process = - CreateApplicationProcess(control, loader, result, system, nca_raw, program_id, 0); - R_UNLESS(process != nullptr, ResultUnknown); + auto process = CreateApplicationProcess(control, loader, result, system, nca_raw, program_id, 0); + R_UNLESS(process != std::nullopt, ResultUnknown); - const auto applet = std::make_shared<Applet>(system, std::move(process), true); + const auto applet = std::make_shared<Applet>(system, std::make_unique<Service::Process>(*std::move(process)), true); applet->program_id = program_id; applet->applet_id = AppletId::Application; applet->type = AppletType::Application; @@ -47,8 +45,7 @@ Result CreateGuestApplication(SharedPointer<IApplicationAccessor>* out_applicati window_system.TrackApplet(applet, true); - *out_application_accessor = - std::make_shared<IApplicationAccessor>(system, applet, window_system); + *out_application_accessor = std::make_shared<IApplicationAccessor>(system, applet, window_system); R_SUCCEED(); } @@ -90,12 +87,10 @@ Result IApplicationCreator::CreateSystemApplication( std::vector<u8> control; std::unique_ptr<Loader::AppLoader> loader; + auto process = CreateProcess(system, application_id, 1, 22); + R_UNLESS(process != std::nullopt, ResultUnknown); - auto process = - CreateProcess(system, application_id, 1, 22); - R_UNLESS(process != nullptr, ResultUnknown); - - const auto applet = std::make_shared<Applet>(system, std::move(process), true); + const auto applet = std::make_shared<Applet>(system, std::make_unique<Service::Process>(*std::move(process)), true); applet->program_id = application_id; applet->applet_id = AppletId::Starter; applet->type = AppletType::LibraryApplet; @@ -103,8 +98,7 @@ Result IApplicationCreator::CreateSystemApplication( m_window_system.TrackApplet(applet, true); - *out_application_accessor = - std::make_shared<IApplicationAccessor>(system, applet, m_window_system); + *out_application_accessor = std::make_shared<IApplicationAccessor>(system, applet, m_window_system); Core::LaunchTimestampCache::SaveLaunchTimestamp(application_id); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp index 5b5e21b8e0..23f67dcf17 100644 --- a/src/core/hle/service/am/service/common_state_getter.cpp +++ b/src/core/hle/service/am/service/common_state_getter.cpp @@ -99,7 +99,7 @@ Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) { LOG_DEBUG(Service_AM, "called"); - if (!m_applet->lifecycle_manager.PopMessage(out_applet_message)) { + if (!m_applet->lifecycle_manager.PopMessage(system.Kernel(), out_applet_message)) { LOG_ERROR(Service_AM, "Tried to pop message but none was available!"); R_THROW(AM::ResultNoMessages); } @@ -123,21 +123,21 @@ Result ICommonStateGetter::RequestToAcquireSleepLock() { LOG_WARNING(Service_AM, "(STUBBED) called"); // Sleep lock is acquired immediately. - m_applet->sleep_lock_event.Signal(); + m_applet->sleep_lock_event.Signal(system.Kernel()); R_SUCCEED(); } Result ICommonStateGetter::ReleaseSleepLock() { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->sleep_lock_event.Clear(); + m_applet->sleep_lock_event.Clear(system.Kernel()); R_SUCCEED(); } Result ICommonStateGetter::ReleaseSleepLockTransiently() { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->sleep_lock_event.Clear(); + m_applet->sleep_lock_event.Clear(system.Kernel()); R_SUCCEED(); } @@ -281,25 +281,25 @@ Result ICommonStateGetter::PerformSystemButtonPressingIfInFocus(SystemButtonType switch (type) { case SystemButtonType::HomeButtonShortPressing: if (!m_applet->home_button_short_pressed_blocked) { - m_applet->lifecycle_manager.PushUnorderedMessage( + m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), AppletMessage::DetectShortPressingHomeButton); } break; case SystemButtonType::HomeButtonLongPressing: if (!m_applet->home_button_long_pressed_blocked) { - m_applet->lifecycle_manager.PushUnorderedMessage( + m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), AppletMessage::DetectLongPressingHomeButton); } break; case SystemButtonType::CaptureButtonShortPressing: if (m_applet->handling_capture_button_short_pressed_message_enabled_for_applet) { - m_applet->lifecycle_manager.PushUnorderedMessage( + m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), AppletMessage::DetectShortPressingCaptureButton); } break; case SystemButtonType::CaptureButtonLongPressing: if (m_applet->handling_capture_button_long_pressed_message_enabled_for_applet) { - m_applet->lifecycle_manager.PushUnorderedMessage( + m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), AppletMessage::DetectLongPressingCaptureButton); } break; diff --git a/src/core/hle/service/am/service/library_applet_accessor.cpp b/src/core/hle/service/am/service/library_applet_accessor.cpp index ef91f69c23..366a26de0a 100644 --- a/src/core/hle/service/am/service/library_applet_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_accessor.cpp @@ -123,7 +123,7 @@ Result ILibraryAppletAccessor::RequestExit() { LOG_DEBUG(Service_AM, "called"); { std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.RequestExit(); + m_applet->lifecycle_manager.RequestExit(system.Kernel()); } FrontendRequestExit(); R_SUCCEED(); @@ -157,7 +157,7 @@ Result ILibraryAppletAccessor::PushInData(SharedPointer<IStorage> storage) { } } - m_broker->GetInData().Push(storage); + m_broker->GetInData().Push(system.Kernel(), storage); R_SUCCEED(); } @@ -165,13 +165,13 @@ Result ILibraryAppletAccessor::PopOutData(Out<SharedPointer<IStorage>> out_stora LOG_DEBUG(Service_AM, "called"); if (auto caller_applet = m_applet->caller_applet.lock(); caller_applet) { - caller_applet->lifecycle_manager.GetSystemEvent().Signal(); + caller_applet->lifecycle_manager.GetSystemEvent().Signal(system.Kernel()); caller_applet->lifecycle_manager.RequestResumeNotification(); - caller_applet->lifecycle_manager.GetSystemEvent().Clear(); + caller_applet->lifecycle_manager.GetSystemEvent().Clear(system.Kernel()); caller_applet->lifecycle_manager.UpdateRequestedFocusState(); } - R_TRY(m_broker->GetOutData().Pop(out_storage.Get())); + R_TRY(m_broker->GetOutData().Pop(system.Kernel(), out_storage.Get())); if (m_applet->applet_id == AppletId::ProfileSelect && *out_storage) { auto impl = (*out_storage)->GetImpl(); @@ -186,14 +186,14 @@ Result ILibraryAppletAccessor::PopOutData(Out<SharedPointer<IStorage>> out_stora Result ILibraryAppletAccessor::PushInteractiveInData(SharedPointer<IStorage> storage) { LOG_DEBUG(Service_AM, "called"); - m_broker->GetInteractiveInData().Push(storage); + m_broker->GetInteractiveInData().Push(system.Kernel(), storage); FrontendExecuteInteractive(); R_SUCCEED(); } Result ILibraryAppletAccessor::PopInteractiveOutData(Out<SharedPointer<IStorage>> out_storage) { LOG_DEBUG(Service_AM, "called"); - R_RETURN(m_broker->GetInteractiveOutData().Pop(out_storage.Get())); + R_RETURN(m_broker->GetInteractiveOutData().Pop(system.Kernel(), out_storage.Get())); } Result ILibraryAppletAccessor::GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) { diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp index 3de5740237..92c9fd4ad9 100644 --- a/src/core/hle/service/am/service/library_applet_creator.cpp +++ b/src/core/hle/service/am/service/library_applet_creator.cpp @@ -122,26 +122,23 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system, }; auto process = CreateProcess(system, program_id, Firmware1400, Firmware2200); - if (!process) { - // Couldn't initialize the guest process - return {}; + if (process) { + const auto applet = std::make_shared<Applet>(system, std::make_unique<Service::Process>(*std::move(process)), false); + applet->program_id = program_id; + applet->applet_id = applet_id; + applet->type = AppletType::LibraryApplet; + applet->library_applet_mode = mode; + applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden; + + auto broker = std::make_shared<AppletDataBroker>(system); + applet->caller_applet = caller_applet; + applet->caller_applet_broker = broker; + caller_applet->child_applets.push_back(applet); + window_system.TrackApplet(applet, false); + return std::make_shared<ILibraryAppletAccessor>(system, broker, applet); } - - const auto applet = std::make_shared<Applet>(system, std::move(process), false); - applet->program_id = program_id; - applet->applet_id = applet_id; - applet->type = AppletType::LibraryApplet; - applet->library_applet_mode = mode; - applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden; - - auto broker = std::make_shared<AppletDataBroker>(system); - applet->caller_applet = caller_applet; - applet->caller_applet_broker = broker; - caller_applet->child_applets.push_back(applet); - - window_system.TrackApplet(applet, false); - - return std::make_shared<ILibraryAppletAccessor>(system, broker, applet); + // Couldn't initialize the guest process + return {}; } std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system, @@ -210,7 +207,7 @@ Result ILibraryAppletCreator::CreateLibraryApplet( } // Applet is created, can now be launched. - m_applet->library_applet_launchable_event.Signal(); + m_applet->library_applet_launchable_event.Signal(system.Kernel()); *out_library_applet_accessor = library_applet; R_SUCCEED(); } @@ -236,7 +233,7 @@ Result ILibraryAppletCreator::CreateLibraryAppletEx( } // Applet is created, can now be launched. - m_applet->library_applet_launchable_event.Signal(); + m_applet->library_applet_launchable_event.Signal(system.Kernel()); *out_library_applet_accessor = library_applet; R_SUCCEED(); } @@ -269,7 +266,7 @@ Result ILibraryAppletCreator::CreateTransferMemoryStorage( } *out_storage = std::make_shared<IStorage>( - system, AM::CreateTransferMemoryStorage(transfer_memory_handle->GetOwner()->GetMemory(), + system, AM::CreateTransferMemoryStorage(system.Kernel(), transfer_memory_handle->GetOwner()->GetMemory(), transfer_memory_handle.Get(), is_writable, size)); R_SUCCEED(); } @@ -290,7 +287,7 @@ Result ILibraryAppletCreator::CreateHandleStorage( } *out_storage = std::make_shared<IStorage>( - system, AM::CreateHandleStorage(transfer_memory_handle->GetOwner()->GetMemory(), + system, AM::CreateHandleStorage(system.Kernel(), transfer_memory_handle->GetOwner()->GetMemory(), transfer_memory_handle.Get(), size)); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.cpp b/src/core/hle/service/am/service/library_applet_self_accessor.cpp index 4a1d1f97d3..473a4bc955 100644 --- a/src/core/hle/service/am/service/library_applet_self_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp @@ -93,23 +93,23 @@ ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; Result ILibraryAppletSelfAccessor::PopInData(Out<SharedPointer<IStorage>> out_storage) { LOG_INFO(Service_AM, "called"); - R_RETURN(m_broker->GetInData().Pop(out_storage)); + R_RETURN(m_broker->GetInData().Pop(system.Kernel(), out_storage)); } Result ILibraryAppletSelfAccessor::PushOutData(SharedPointer<IStorage> storage) { LOG_INFO(Service_AM, "called"); - m_broker->GetOutData().Push(storage); + m_broker->GetOutData().Push(system.Kernel(), storage); R_SUCCEED(); } Result ILibraryAppletSelfAccessor::PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage) { LOG_INFO(Service_AM, "called"); - R_RETURN(m_broker->GetInteractiveInData().Pop(out_storage)); + R_RETURN(m_broker->GetInteractiveInData().Pop(system.Kernel(), out_storage)); } Result ILibraryAppletSelfAccessor::PushInteractiveOutData(SharedPointer<IStorage> storage) { LOG_INFO(Service_AM, "called"); - m_broker->GetInteractiveOutData().Push(storage); + m_broker->GetInteractiveOutData().Push(system.Kernel(), storage); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/lock_accessor.cpp b/src/core/hle/service/am/service/lock_accessor.cpp index 8e556fdd68..0341254449 100644 --- a/src/core/hle/service/am/service/lock_accessor.cpp +++ b/src/core/hle/service/am/service/lock_accessor.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -20,7 +23,7 @@ ILockAccessor::ILockAccessor(Core::System& system_) RegisterHandlers(functions); - m_event.Signal(); + m_event.Signal(system.Kernel()); } ILockAccessor::~ILockAccessor() = default; @@ -55,7 +58,7 @@ Result ILockAccessor::Unlock() { m_is_locked = false; } - m_event.Signal(); + m_event.Signal(system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp index 89e393bb97..4279483727 100644 --- a/src/core/hle/service/am/service/self_controller.cpp +++ b/src/core/hle/service/am/service/self_controller.cpp @@ -151,7 +151,7 @@ Result ISelfController::GetLibraryAppletLaunchableEvent( OutCopyHandle<Kernel::KReadableEvent> out_event) { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->library_applet_launchable_event.Signal(); + m_applet->library_applet_launchable_event.Signal(system.Kernel()); *out_event = m_applet->library_applet_launchable_event.GetHandle(); R_SUCCEED(); @@ -170,7 +170,7 @@ Result ISelfController::SetOperationModeChangedNotification(bool enabled) { LOG_INFO(Service_AM, "called, enabled={}", enabled); std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.SetOperationModeChangedNotificationEnabled(enabled); + m_applet->lifecycle_manager.SetOperationModeChangedNotificationEnabled(system.Kernel(), enabled); R_SUCCEED(); } @@ -179,7 +179,7 @@ Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) { LOG_INFO(Service_AM, "called, enabled={}", enabled); std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.SetPerformanceModeChangedNotificationEnabled(enabled); + m_applet->lifecycle_manager.SetPerformanceModeChangedNotificationEnabled(system.Kernel(), enabled); R_SUCCEED(); } @@ -188,7 +188,7 @@ Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool LOG_INFO(Service_AM, "called, notify={} background={} suspend={}", notify, background, suspend); std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.SetFocusStateChangedNotificationEnabled(notify); + m_applet->lifecycle_manager.SetFocusStateChangedNotificationEnabled(system.Kernel(), notify); m_applet->lifecycle_manager.SetFocusHandlingMode(suspend); m_applet->UpdateSuspensionStateLocked(true); diff --git a/src/core/hle/service/am/window_system.cpp b/src/core/hle/service/am/window_system.cpp index 5f20a98322..90115d73be 100644 --- a/src/core/hle/service/am/window_system.cpp +++ b/src/core/hle/service/am/window_system.cpp @@ -154,7 +154,7 @@ void WindowSystem::OnOperationModeChanged() { for (const auto& [aruid, applet] : m_applets) { std::scoped_lock lk2{applet->lock}; - applet->lifecycle_manager.OnOperationAndPerformanceModeChanged(); + applet->lifecycle_manager.OnOperationAndPerformanceModeChanged(m_system.Kernel()); } } @@ -163,22 +163,22 @@ void WindowSystem::OnExitRequested() { for (const auto& [aruid, applet] : m_applets) { std::scoped_lock lk2{applet->lock}; - applet->lifecycle_manager.RequestExit(); + applet->lifecycle_manager.RequestExit(m_system.Kernel()); } } void WindowSystem::SendButtonAppletMessageLocked(AppletMessage message) { if (m_home_menu) { std::scoped_lock lk_home{m_home_menu->lock}; - m_home_menu->lifecycle_manager.PushUnorderedMessage(message); + m_home_menu->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message); } if (m_overlay_display) { std::scoped_lock lk_overlay{m_overlay_display->lock}; - m_overlay_display->lifecycle_manager.PushUnorderedMessage(message); + m_overlay_display->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message); } if (m_application) { std::scoped_lock lk_application{m_application->lock}; - m_application->lifecycle_manager.PushUnorderedMessage(message); + m_application->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message); } if (m_event_observer) { m_event_observer->RequestUpdate(); @@ -277,8 +277,7 @@ void WindowSystem::PruneTerminatedAppletsLocked() { // If we have a home menu, send it the application exited message. if (m_home_menu) { - m_home_menu->lifecycle_manager.PushUnorderedMessage( - AppletMessage::ApplicationExited); + m_home_menu->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), AppletMessage::ApplicationExited); } } diff --git a/src/core/hle/service/audio/audio_device.cpp b/src/core/hle/service/audio/audio_device.cpp index eb64892ed8..e9f7e074a1 100644 --- a/src/core/hle/service/audio/audio_device.cpp +++ b/src/core/hle/service/audio/audio_device.cpp @@ -42,7 +42,7 @@ IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u }; RegisterHandlers(functions); - event->Signal(); + event->Signal(system.Kernel()); } IAudioDevice::~IAudioDevice() { @@ -128,7 +128,7 @@ Result IAudioDevice::GetActiveAudioDeviceNameAuto( Result IAudioDevice::QueryAudioDeviceSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) { LOG_DEBUG(Service_Audio, "(STUBBED) called"); - event->Signal(); + event->Signal(system.Kernel()); *out_event = &event->GetReadableEvent(); R_SUCCEED(); } diff --git a/src/core/hle/service/audio/audio_in.cpp b/src/core/hle/service/audio/audio_in.cpp index 416803acc3..6208c2d104 100644 --- a/src/core/hle/service/audio/audio_in.cpp +++ b/src/core/hle/service/audio/audio_in.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -37,7 +40,7 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id, RegisterHandlers(functions); - process->Open(); + process->Open(system.Kernel()); if (impl->GetSystem() .Initialize(device_name, in_params, handle, applet_resource_user_id) @@ -49,7 +52,7 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id, IAudioIn::~IAudioIn() { impl->Free(); service_context.CloseEvent(event); - process->Close(); + process->Close(system.Kernel()); } Result IAudioIn::GetAudioInState(Out<u32> out_state) { diff --git a/src/core/hle/service/audio/audio_out.cpp b/src/core/hle/service/audio/audio_out.cpp index 53009d5d74..996eeede58 100644 --- a/src/core/hle/service/audio/audio_out.cpp +++ b/src/core/hle/service/audio/audio_out.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -39,13 +42,13 @@ IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id, // clang-format on RegisterHandlers(functions); - process->Open(); + process->Open(system.Kernel()); } IAudioOut::~IAudioOut() { impl->Free(); service_context.CloseEvent(event); - process->Close(); + process->Close(system.Kernel()); } Result IAudioOut::GetAudioOutState(Out<u32> out_state) { diff --git a/src/core/hle/service/audio/audio_out_manager.cpp b/src/core/hle/service/audio/audio_out_manager.cpp index 0a8e1ec256..3b2087932c 100644 --- a/src/core/hle/service/audio/audio_out_manager.cpp +++ b/src/core/hle/service/audio/audio_out_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -14,7 +14,9 @@ namespace Service::Audio { using namespace AudioCore::AudioOut; IAudioOutManager::IAudioOutManager(Core::System& system_) - : ServiceFramework{system_, "audout:u"}, impl{std::make_unique<Manager>(system_)} { + : ServiceFramework{system_, "audout:u"} + , impl(system_) +{ // clang-format off static const FunctionInfo functions[] = { {0, D<&IAudioOutManager::ListAudioOuts>, "ListAudioOuts"}, diff --git a/src/core/hle/service/audio/audio_out_manager.h b/src/core/hle/service/audio/audio_out_manager.h index 791274d5e9..ec974aaba4 100644 --- a/src/core/hle/service/audio/audio_out_manager.h +++ b/src/core/hle/service/audio/audio_out_manager.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -43,7 +43,7 @@ private: AudioCore::AudioOut::AudioOutParameter parameter, InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid); - std::unique_ptr<AudioCore::AudioOut::Manager> impl; + std::optional<AudioCore::AudioOut::Manager> impl; }; } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_renderer.cpp b/src/core/hle/service/audio/audio_renderer.cpp index 21cc742b69..49c6083109 100644 --- a/src/core/hle/service/audio/audio_renderer.cpp +++ b/src/core/hle/service/audio/audio_renderer.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -39,7 +39,7 @@ IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_, // clang-format on RegisterHandlers(functions); - process_handle->Open(); + process_handle->Open(system_.Kernel()); impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, applet_resource_user_id, session_id); } @@ -47,7 +47,7 @@ IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_, IAudioRenderer::~IAudioRenderer() { impl->Finalize(); service_context.CloseEvent(rendered_event); - process_handle->Close(); + process_handle->Close(system.Kernel()); } Result IAudioRenderer::GetSampleRate(Out<u32> out_sample_rate) { diff --git a/src/core/hle/service/audio/audio_renderer_manager.cpp b/src/core/hle/service/audio/audio_renderer_manager.cpp index 6a1345c074..972e930a89 100644 --- a/src/core/hle/service/audio/audio_renderer_manager.cpp +++ b/src/core/hle/service/audio/audio_renderer_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,7 +18,9 @@ namespace Service::Audio { using namespace AudioCore::Renderer; IAudioRendererManager::IAudioRendererManager(Core::System& system_) - : ServiceFramework{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} { + : ServiceFramework{system_, "audren:u"} + , impl(system_) +{ // clang-format off static const FunctionInfo functions[] = { {0, D<&IAudioRendererManager::OpenAudioRenderer>, "OpenAudioRenderer"}, diff --git a/src/core/hle/service/audio/audio_renderer_manager.h b/src/core/hle/service/audio/audio_renderer_manager.h index 69eee664c3..fdce8b6ffa 100644 --- a/src/core/hle/service/audio/audio_renderer_manager.h +++ b/src/core/hle/service/audio/audio_renderer_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +33,7 @@ private: Result GetAudioDeviceServiceWithRevisionInfo(Out<SharedPointer<IAudioDevice>> out_audio_device, u32 revision, ClientAppletResourceUserId aruid); - std::unique_ptr<AudioCore::Renderer::Manager> impl; + std::optional<AudioCore::Renderer::Manager> impl; u32 num_audio_devices{0}; }; diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp index 491416254c..3ef70aaacc 100644 --- a/src/core/hle/service/bcat/backend/backend.cpp +++ b/src/core/hle/service/bcat/backend/backend.cpp @@ -13,9 +13,9 @@ namespace Service::BCAT { ProgressServiceBackend::ProgressServiceBackend(Core::System& system, std::string_view event_name) - : service_context{system, "ProgressServiceBackend"} { - update_event = service_context.CreateEvent("ProgressServiceBackend:UpdateEvent:" + - std::string(event_name)); + : service_context{system, "ProgressServiceBackend"} +{ + update_event = service_context.CreateEvent("ProgressServiceBackend:UpdateEvent:" + std::string(event_name)); } ProgressServiceBackend::~ProgressServiceBackend() { @@ -30,103 +30,90 @@ DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() { return impl; } -void ProgressServiceBackend::SetTotalSize(u64 size) { +void ProgressServiceBackend::SetTotalSize(Kernel::KernelCore& kernel, u64 size) { impl.total_bytes = size; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::StartConnecting() { +void ProgressServiceBackend::StartConnecting(Kernel::KernelCore& kernel) { impl.status = DeliveryCacheProgressStatus::Connecting; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::StartProcessingDataList() { +void ProgressServiceBackend::StartProcessingDataList(Kernel::KernelCore& kernel) { impl.status = DeliveryCacheProgressStatus::ProcessingDataList; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::StartDownloadingFile(std::string_view dir_name, - std::string_view file_name, u64 file_size) { +void ProgressServiceBackend::StartDownloadingFile(Kernel::KernelCore& kernel, std::string_view dir_name, std::string_view file_name, u64 file_size) { impl.status = DeliveryCacheProgressStatus::Downloading; impl.current_downloaded_bytes = 0; impl.current_total_bytes = file_size; - std::memcpy(impl.current_directory.data(), dir_name.data(), - std::min<u64>(dir_name.size(), 0x31ull)); - std::memcpy(impl.current_file.data(), file_name.data(), - std::min<u64>(file_name.size(), 0x31ull)); - SignalUpdate(); + std::memcpy(impl.current_directory.data(), dir_name.data(), std::min<u64>(dir_name.size(), 0x31ull)); + std::memcpy(impl.current_file.data(), file_name.data(), std::min<u64>(file_name.size(), 0x31ull)); + SignalUpdate(kernel); } -void ProgressServiceBackend::UpdateFileProgress(u64 downloaded) { +void ProgressServiceBackend::UpdateFileProgress(Kernel::KernelCore& kernel, u64 downloaded) { impl.current_downloaded_bytes = downloaded; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::FinishDownloadingFile() { +void ProgressServiceBackend::FinishDownloadingFile(Kernel::KernelCore& kernel) { impl.total_downloaded_bytes += impl.current_total_bytes; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::CommitDirectory(std::string_view dir_name) { +void ProgressServiceBackend::CommitDirectory(Kernel::KernelCore& kernel, std::string_view dir_name) { impl.status = DeliveryCacheProgressStatus::Committing; impl.current_file.fill(0); impl.current_downloaded_bytes = 0; impl.current_total_bytes = 0; - std::memcpy(impl.current_directory.data(), dir_name.data(), - std::min<u64>(dir_name.size(), 0x31ull)); - SignalUpdate(); + std::memcpy(impl.current_directory.data(), dir_name.data(), std::min<u64>(dir_name.size(), 0x31ull)); + SignalUpdate(kernel); } -void ProgressServiceBackend::FinishDownload(Result result) { +void ProgressServiceBackend::FinishDownload(Kernel::KernelCore& kernel, Result result) { impl.total_downloaded_bytes = impl.total_bytes; impl.status = DeliveryCacheProgressStatus::Done; impl.result = result; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::SignalUpdate() { - update_event->Signal(); +void ProgressServiceBackend::SignalUpdate(Kernel::KernelCore& kernel) { + update_event->Signal(kernel); } BcatBackend::BcatBackend(DirectoryGetter getter) : dir_getter(std::move(getter)) {} - BcatBackend::~BcatBackend() = default; NullBcatBackend::NullBcatBackend(DirectoryGetter getter) : BcatBackend(std::move(getter)) {} - NullBcatBackend::~NullBcatBackend() = default; -bool NullBcatBackend::Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, - title.build_id); - - progress.FinishDownload(ResultSuccess); +bool NullBcatBackend::Synchronize(Kernel::KernelCore& kernel, TitleIDVersion title, ProgressServiceBackend& progress) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, title.build_id); + progress.FinishDownload(kernel, ResultSuccess); return true; } -bool NullBcatBackend::SynchronizeDirectory(TitleIDVersion title, std::string name, - ProgressServiceBackend& progress) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}, name={}", title.title_id, - title.build_id, name); - - progress.FinishDownload(ResultSuccess); +bool NullBcatBackend::SynchronizeDirectory(Kernel::KernelCore& kernel, TitleIDVersion title, std::string name, ProgressServiceBackend& progress) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}, name={}", title.title_id, title.build_id, name); + progress.FinishDownload(kernel, ResultSuccess); return true; } -bool NullBcatBackend::Clear(u64 title_id) { +bool NullBcatBackend::Clear(Kernel::KernelCore& kernel, u64 title_id) { LOG_DEBUG(Service_BCAT, "called, title_id={:016X}", title_id); return true; } -void NullBcatBackend::SetPassphrase(u64 title_id, const Passphrase& passphrase) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, passphrase={}", title_id, - Common::HexToString(passphrase)); +void NullBcatBackend::SetPassphrase(Kernel::KernelCore& kernel, u64 title_id, const Passphrase& passphrase) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, passphrase={}", title_id, Common::HexToString(passphrase)); } -std::optional<std::vector<u8>> NullBcatBackend::GetLaunchParameter(TitleIDVersion title) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, - title.build_id); +std::optional<std::vector<u8>> NullBcatBackend::GetLaunchParameter(Kernel::KernelCore& kernel, TitleIDVersion title) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, title.build_id); return std::nullopt; } diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h index 3680f6c9c8..8419399a62 100644 --- a/src/core/hle/service/bcat/backend/backend.h +++ b/src/core/hle/service/bcat/backend/backend.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -34,26 +37,26 @@ public: ~ProgressServiceBackend(); // Sets the number of bytes total in the entire download. - void SetTotalSize(u64 size); + void SetTotalSize(Kernel::KernelCore& kernel, u64 size); // Notifies the application that the backend has started connecting to the server. - void StartConnecting(); + void StartConnecting(Kernel::KernelCore& kernel); // Notifies the application that the backend has begun accumulating and processing metadata. - void StartProcessingDataList(); + void StartProcessingDataList(Kernel::KernelCore& kernel); // Notifies the application that a file is starting to be downloaded. - void StartDownloadingFile(std::string_view dir_name, std::string_view file_name, u64 file_size); + void StartDownloadingFile(Kernel::KernelCore& kernel, std::string_view dir_name, std::string_view file_name, u64 file_size); // Updates the progress of the current file to the size passed. - void UpdateFileProgress(u64 downloaded); + void UpdateFileProgress(Kernel::KernelCore& kernel, u64 downloaded); // Notifies the application that the current file has completed download. - void FinishDownloadingFile(); + void FinishDownloadingFile(Kernel::KernelCore& kernel); // Notifies the application that all files in this directory have completed and are being // finalized. - void CommitDirectory(std::string_view dir_name); + void CommitDirectory(Kernel::KernelCore& kernel, std::string_view dir_name); // Notifies the application that the operation completed with result code result. - void FinishDownload(Result result); + void FinishDownload(Kernel::KernelCore& kernel, Result result); private: explicit ProgressServiceBackend(Core::System& system, std::string_view event_name); @@ -61,7 +64,7 @@ private: Kernel::KReadableEvent& GetEvent(); DeliveryCacheProgressImpl& GetImpl(); - void SignalUpdate(); + void SignalUpdate(Kernel::KernelCore& kernel); KernelHelpers::ServiceContext service_context; @@ -74,25 +77,19 @@ class BcatBackend { public: explicit BcatBackend(DirectoryGetter getter); virtual ~BcatBackend(); - // Called when the backend is needed to synchronize the data for the game with title ID and // version in title. A ProgressServiceBackend object is provided to alert the application of // status. - virtual bool Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) = 0; + virtual bool Synchronize(Kernel::KernelCore& kernel, TitleIDVersion title, ProgressServiceBackend& progress) = 0; // Very similar to Synchronize, but only for the directory provided. Backends should not alter // the data for any other directories. - virtual bool SynchronizeDirectory(TitleIDVersion title, std::string name, - ProgressServiceBackend& progress) = 0; - + virtual bool SynchronizeDirectory(Kernel::KernelCore& kernel, TitleIDVersion title, std::string name, ProgressServiceBackend& progress) = 0; // Removes all cached data associated with title id provided. - virtual bool Clear(u64 title_id) = 0; - + virtual bool Clear(Kernel::KernelCore& kernel, u64 title_id) = 0; // Sets the BCAT Passphrase to be used with the associated title ID. - virtual void SetPassphrase(u64 title_id, const Passphrase& passphrase) = 0; - + virtual void SetPassphrase(Kernel::KernelCore& kernel, u64 title_id, const Passphrase& passphrase) = 0; // Gets the launch parameter used by AM associated with the title ID and version provided. - virtual std::optional<std::vector<u8>> GetLaunchParameter(TitleIDVersion title) = 0; - + virtual std::optional<std::vector<u8>> GetLaunchParameter(Kernel::KernelCore& kernel, TitleIDVersion title) = 0; protected: DirectoryGetter dir_getter; }; @@ -103,18 +100,13 @@ public: explicit NullBcatBackend(DirectoryGetter getter); ~NullBcatBackend() override; - bool Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) override; - bool SynchronizeDirectory(TitleIDVersion title, std::string name, - ProgressServiceBackend& progress) override; - - bool Clear(u64 title_id) override; - - void SetPassphrase(u64 title_id, const Passphrase& passphrase) override; - - std::optional<std::vector<u8>> GetLaunchParameter(TitleIDVersion title) override; + bool Synchronize(Kernel::KernelCore& kernel, TitleIDVersion title, ProgressServiceBackend& progress) override; + bool SynchronizeDirectory(Kernel::KernelCore& kernel, TitleIDVersion title, std::string name, ProgressServiceBackend& progress) override; + bool Clear(Kernel::KernelCore& kernel, u64 title_id) override; + void SetPassphrase(Kernel::KernelCore& kernel, u64 title_id, const Passphrase& passphrase) override; + std::optional<std::vector<u8>> GetLaunchParameter(Kernel::KernelCore& kernel, TitleIDVersion title) override; }; -std::unique_ptr<BcatBackend> CreateBackendFromSettings(Core::System& system, - DirectoryGetter getter); +std::unique_ptr<BcatBackend> CreateBackendFromSettings(Core::System& system, DirectoryGetter getter); } // namespace Service::BCAT diff --git a/src/core/hle/service/bcat/bcat_service.cpp b/src/core/hle/service/bcat/bcat_service.cpp index 849bf8d0d9..210fd77094 100644 --- a/src/core/hle/service/bcat/bcat_service.cpp +++ b/src/core/hle/service/bcat/bcat_service.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -70,7 +70,7 @@ Result IBcatService::RequestSyncDeliveryCache( LOG_DEBUG(Service_BCAT, "called"); auto& progress_backend{GetProgressBackend(SyncType::Normal)}; - backend.Synchronize({system.GetApplicationProcessProgramID(), + backend.Synchronize(system.Kernel(), {system.GetApplicationProcessProgramID(), GetCurrentBuildID(system.GetApplicationProcessBuildID())}, GetProgressBackend(SyncType::Normal)); @@ -86,7 +86,7 @@ Result IBcatService::RequestSyncDeliveryCacheWithDirectoryName( LOG_DEBUG(Service_BCAT, "called, name={}", name); auto& progress_backend{GetProgressBackend(SyncType::Directory)}; - backend.SynchronizeDirectory({system.GetApplicationProcessProgramID(), + backend.SynchronizeDirectory(system.Kernel(), {system.GetApplicationProcessProgramID(), GetCurrentBuildID(system.GetApplicationProcessBuildID())}, name, progress_backend); @@ -107,7 +107,7 @@ Result IBcatService::SetPassphrase(u64 application_id, std::memcpy(passphrase.data(), passphrase_buffer.data(), (std::min)(passphrase.size(), passphrase_buffer.size())); - backend.SetPassphrase(application_id, passphrase); + backend.SetPassphrase(system.Kernel(), application_id, passphrase); R_SUCCEED(); } @@ -120,7 +120,7 @@ Result IBcatService::ClearDeliveryCacheStorage(u64 application_id) { LOG_DEBUG(Service_BCAT, "called, title_id={:016X}", application_id); R_UNLESS(application_id != 0, ResultInvalidArgument); - R_UNLESS(backend.Clear(application_id), FileSys::ResultPermissionDenied); + R_UNLESS(backend.Clear(system.Kernel(), application_id), FileSys::ResultPermissionDenied); R_SUCCEED(); } diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index 79578956b1..6885a7be7d 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -183,7 +183,7 @@ private: auto& readable_event = completion_event->GetReadableEvent(); IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(readable_event.Signal()); + rb.Push(readable_event.Signal(system.Kernel())); rb.PushCopyObjects(readable_event); } diff --git a/src/core/hle/service/glue/time/alarm_worker.cpp b/src/core/hle/service/glue/time/alarm_worker.cpp index 3ff071f4a0..770dc62f5c 100644 --- a/src/core/hle/service/glue/time/alarm_worker.cpp +++ b/src/core/hle/service/glue/time/alarm_worker.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -28,7 +31,7 @@ void AlarmWorker::Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> "Glue:AlarmWorker::AlarmTimer", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - m_timer_event->Signal(); + m_timer_event->Signal(m_system.Kernel()); return std::nullopt; }); @@ -57,7 +60,7 @@ void AlarmWorker::OnPowerStateChanged() { s64 closest_time{}; if (!GetClosestAlarmInfo(closest_alarm_info, closest_time)) { m_system.CoreTiming().UnscheduleEvent(m_timer_timing_event); - m_timer_event->Clear(); + m_timer_event->Clear(m_system.Kernel()); return; } @@ -67,7 +70,7 @@ void AlarmWorker::OnPowerStateChanged() { auto next_time{closest_alarm_info.alert_time - closest_time}; m_system.CoreTiming().UnscheduleEvent(m_timer_timing_event); - m_timer_event->Clear(); + m_timer_event->Clear(m_system.Kernel()); m_system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds(next_time), m_timer_timing_event); diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index c358cfbf28..3543e1938b 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp @@ -89,7 +89,7 @@ Result TimeZoneService::SetDeviceLocationName( std::scoped_lock m{m_list_mutex}; for (auto& operation_event : m_list_nodes) { - operation_event.m_event->Signal(); + operation_event.m_event->Signal(m_system.Kernel()); } R_SUCCEED(); } diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp index 1dab3e9dcb..5025efc717 100644 --- a/src/core/hle/service/glue/time/worker.cpp +++ b/src/core/hle/service/glue/time/worker.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +33,7 @@ TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady "Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - m_timer_steady_clock->Signal(); + m_timer_steady_clock->Signal(m_system.Kernel()); return std::nullopt; }); @@ -38,19 +41,19 @@ TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady "Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - m_timer_file_system->Signal(); + m_timer_file_system->Signal(m_system.Kernel()); return std::nullopt; }); } TimeWorker::~TimeWorker() { - m_local_clock_event->Signal(); - m_network_clock_event->Signal(); - m_ephemeral_clock_event->Signal(); + m_local_clock_event->Signal(m_system.Kernel()); + m_network_clock_event->Signal(m_system.Kernel()); + m_ephemeral_clock_event->Signal(m_system.Kernel()); std::this_thread::sleep_for(std::chrono::milliseconds(16)); m_thread.request_stop(); - m_event->Signal(); + m_event->Signal(m_system.Kernel()); m_thread.join(); m_ctx.CloseEvent(m_event); @@ -167,19 +170,19 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { return; case EventType::PowerStateChange: - m_alarm_worker.GetEvent().Clear(); + m_alarm_worker.GetEvent().Clear(m_system.Kernel()); if (m_pm_state_change_handler.m_priority <= 1) { m_alarm_worker.OnPowerStateChanged(); } break; case EventType::SignalAlarms: - m_alarm_worker.GetTimerEvent().Clear(); + m_alarm_worker.GetTimerEvent().Clear(m_system.Kernel()); m_time_m->CheckAndSignalAlarms(); break; case EventType::UpdateLocalSystemClock: { - m_local_clock_event->Clear(); + m_local_clock_event->Clear(m_system.Kernel()); Service::PSC::Time::SystemClockContext context{}; R_ASSERT(m_local_clock->GetSystemClockContext(&context)); @@ -190,7 +193,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { } case EventType::UpdateNetworkSystemClock: { - m_network_clock_event->Clear(); + m_network_clock_event->Clear(m_system.Kernel()); Service::PSC::Time::SystemClockContext context{}; R_ASSERT(m_network_clock->GetSystemClockContext(&context)); @@ -218,7 +221,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { } case EventType::UpdateEphemeralSystemClock: { - m_ephemeral_clock_event->Clear(); + m_ephemeral_clock_event->Clear(m_system.Kernel()); Service::PSC::Time::SystemClockContext context{}; auto res = m_ephemeral_clock->GetSystemClockContext(&context); @@ -247,20 +250,20 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { } case EventType::UpdateSteadyClock: - m_timer_steady_clock->Clear(); + m_timer_steady_clock->Clear(m_system.Kernel()); m_steady_clock_resource.UpdateTime(); m_time_m->SetStandardSteadyClockBaseTime(m_steady_clock_resource.GetTime()); break; case EventType::UpdateFileTimestamp: - m_timer_file_system->Clear(); + m_timer_file_system->Clear(m_system.Kernel()); m_file_timestamp_worker.SetFilesystemPosixTime(); break; case EventType::AutoCorrect: { - m_standard_user_auto_correct_clock_event->Clear(); + m_standard_user_auto_correct_clock_event->Clear(m_system.Kernel()); bool automatic_correction{}; R_ASSERT(m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled( diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index f29cf4e3d7..cd69829472 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -650,8 +650,7 @@ Result IHidServer::SetSupportedNpadStyleSet(Core::HID::NpadStyleSet supported_st LOG_DEBUG(Service_HID, "called, supported_style_set={}, applet_resource_user_id={}", supported_style_set, aruid.pid); - R_TRY( - GetResourceManager()->GetNpad()->SetSupportedNpadStyleSet(aruid.pid, supported_style_set)); + R_TRY(GetResourceManager()->GetNpad()->SetSupportedNpadStyleSet(system.Kernel(), aruid.pid, supported_style_set)); Core::HID::NpadStyleTag style_tag{supported_style_set}; const auto revision = GetResourceManager()->GetNpad()->GetRevision(aruid.pid); @@ -667,7 +666,7 @@ Result IHidServer::GetSupportedNpadStyleSet(Out<Core::HID::NpadStyleSet> out_sup ClientAppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", aruid.pid); - R_RETURN(GetResourceManager()->GetNpad()->GetSupportedNpadStyleSet(aruid.pid, + R_RETURN(GetResourceManager()->GetNpad()->GetSupportedNpadStyleSet(system.Kernel(), aruid.pid, *out_supported_style_set)); } @@ -677,7 +676,7 @@ Result IHidServer::SetSupportedNpadIdType( LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", aruid.pid); R_RETURN( - GetResourceManager()->GetNpad()->SetSupportedNpadIdType(aruid.pid, supported_npad_list)); + GetResourceManager()->GetNpad()->SetSupportedNpadIdType(system.Kernel(), aruid.pid, supported_npad_list)); } Result IHidServer::ActivateNpad(ClientAppletResourceUserId aruid) { @@ -702,14 +701,13 @@ Result IHidServer::AcquireNpadStyleSetUpdateEventHandle( LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", npad_id, aruid.pid, unknown); - R_RETURN(GetResourceManager()->GetNpad()->AcquireNpadStyleSetUpdateEventHandle( - aruid.pid, out_event, npad_id)); + R_RETURN(GetResourceManager()->GetNpad()->AcquireNpadStyleSetUpdateEventHandle(system.Kernel(), aruid.pid, out_event, npad_id)); } Result IHidServer::DisconnectNpad(Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); - R_RETURN(GetResourceManager()->GetNpad()->DisconnectNpad(aruid.pid, npad_id)); + R_RETURN(GetResourceManager()->GetNpad()->DisconnectNpad(system.Kernel(), aruid.pid, npad_id)); } Result IHidServer::GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern, @@ -779,7 +777,7 @@ Result IHidServer::SetNpadJoyAssignmentModeSingleByDefault(Core::HID::NpadIdType LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); Core::HID::NpadIdType new_npad_id{}; - GetResourceManager()->GetNpad()->SetNpadMode( + GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, new_npad_id, npad_id, NpadJoyDeviceType::Left, NpadJoyAssignmentMode::Single); R_SUCCEED(); } @@ -791,7 +789,7 @@ Result IHidServer::SetNpadJoyAssignmentModeSingle(Core::HID::NpadIdType npad_id, npad_id, aruid.pid, npad_joy_device_type); Core::HID::NpadIdType new_npad_id{}; - GetResourceManager()->GetNpad()->SetNpadMode( + GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, new_npad_id, npad_id, npad_joy_device_type, NpadJoyAssignmentMode::Single); R_SUCCEED(); } @@ -801,7 +799,7 @@ Result IHidServer::SetNpadJoyAssignmentModeDual(Core::HID::NpadIdType npad_id, LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); Core::HID::NpadIdType new_npad_id{}; - GetResourceManager()->GetNpad()->SetNpadMode(aruid.pid, new_npad_id, npad_id, {}, + GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, new_npad_id, npad_id, {}, NpadJoyAssignmentMode::Dual); R_SUCCEED(); } @@ -813,7 +811,7 @@ Result IHidServer::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, npad_id_1, npad_id_2, aruid.pid); R_RETURN( - GetResourceManager()->GetNpad()->MergeSingleJoyAsDualJoy(aruid.pid, npad_id_1, npad_id_2)); + GetResourceManager()->GetNpad()->MergeSingleJoyAsDualJoy(system.Kernel(), aruid.pid, npad_id_1, npad_id_2)); } Result IHidServer::StartLrAssignmentMode(ClientAppletResourceUserId aruid) { @@ -840,67 +838,40 @@ Result IHidServer::SetNpadHandheldActivationMode(ClientAppletResourceUserId arui ASSERT_MSG(false, "Activation mode should be always None, Single or Dual"); R_SUCCEED(); } - - R_RETURN( - GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(aruid.pid, activation_mode)); + R_RETURN(GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(system.Kernel(), aruid.pid, activation_mode)); } Result IHidServer::GetNpadHandheldActivationMode( Out<NpadHandheldActivationMode> out_activation_mode, ClientAppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", aruid.pid); - - R_RETURN(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode(aruid.pid, - *out_activation_mode)); + R_RETURN(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode(system.Kernel(), aruid.pid, *out_activation_mode)); } -Result IHidServer::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2, - ClientAppletResourceUserId aruid) { - LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", - npad_id_1, npad_id_2, aruid.pid); - - R_RETURN(GetResourceManager()->GetNpad()->SwapNpadAssignment(aruid.pid, npad_id_1, npad_id_2)) +Result IHidServer::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2, ClientAppletResourceUserId aruid) { + LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", npad_id_1, npad_id_2, aruid.pid); + R_RETURN(GetResourceManager()->GetNpad()->SwapNpadAssignment(system.Kernel(), aruid.pid, npad_id_1, npad_id_2)) } -Result IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(Out<bool> out_is_enabled, - Core::HID::NpadIdType npad_id, - ClientAppletResourceUserId aruid) { +Result IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(Out<bool> out_is_enabled, Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid) { LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); - R_UNLESS(IsNpadIdValid(npad_id), ResultInvalidNpadId); - R_RETURN(GetResourceManager()->GetNpad()->IsUnintendedHomeButtonInputProtectionEnabled( - *out_is_enabled, aruid.pid, npad_id)); + R_RETURN(GetResourceManager()->GetNpad()->IsUnintendedHomeButtonInputProtectionEnabled(*out_is_enabled, aruid.pid, npad_id)); } -Result IHidServer::EnableUnintendedHomeButtonInputProtection(bool is_enabled, - Core::HID::NpadIdType npad_id, - ClientAppletResourceUserId aruid) { - LOG_DEBUG(Service_HID, "called, is_enabled={}, npad_id={}, applet_resource_user_id={}", - is_enabled, npad_id, aruid.pid); - +Result IHidServer::EnableUnintendedHomeButtonInputProtection(bool is_enabled, Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid) { + LOG_DEBUG(Service_HID, "called, is_enabled={}, npad_id={}, applet_resource_user_id={}",is_enabled, npad_id, aruid.pid); R_UNLESS(IsNpadIdValid(npad_id), ResultInvalidNpadId); - R_RETURN(GetResourceManager()->GetNpad()->EnableUnintendedHomeButtonInputProtection( - aruid.pid, npad_id, is_enabled)); + R_RETURN(GetResourceManager()->GetNpad()->EnableUnintendedHomeButtonInputProtection(aruid.pid, npad_id, is_enabled)); } -Result IHidServer::SetNpadJoyAssignmentModeSingleWithDestination( - Out<bool> out_is_reassigned, Out<Core::HID::NpadIdType> out_new_npad_id, - Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid, - NpadJoyDeviceType npad_joy_device_type) { - LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", - npad_id, aruid.pid, npad_joy_device_type); - - *out_is_reassigned = GetResourceManager()->GetNpad()->SetNpadMode( - aruid.pid, *out_new_npad_id, npad_id, npad_joy_device_type, NpadJoyAssignmentMode::Single); - +Result IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(Out<bool> out_is_reassigned, Out<Core::HID::NpadIdType> out_new_npad_id, Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid, NpadJoyDeviceType npad_joy_device_type) { + LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", npad_id, aruid.pid, npad_joy_device_type); + *out_is_reassigned = GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, *out_new_npad_id, npad_id, npad_joy_device_type, NpadJoyAssignmentMode::Single); R_SUCCEED(); } -Result IHidServer::SetNpadAnalogStickUseCenterClamp(bool use_center_clamp, - ClientAppletResourceUserId aruid) { - LOG_INFO(Service_HID, "called, use_center_clamp={}, applet_resource_user_id={}", - use_center_clamp, aruid.pid); - +Result IHidServer::SetNpadAnalogStickUseCenterClamp(bool use_center_clamp, ClientAppletResourceUserId aruid) { + LOG_INFO(Service_HID, "called, use_center_clamp={}, applet_resource_user_id={}", use_center_clamp, aruid.pid); GetResourceManager()->GetNpad()->SetNpadAnalogStickUseCenterClamp(aruid.pid, use_center_clamp); R_SUCCEED(); } diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 1de5dd6f28..dbc8310c08 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -281,7 +281,7 @@ void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy(applet_resource_user_id); + GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy(system.Kernel(), applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -328,7 +328,7 @@ void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicyFull(applet_resource_user_id); + GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicyFull(system.Kernel(), applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -358,9 +358,8 @@ void IHidSystemServer::GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); Core::HID::NpadStyleSet supported_styleset{}; - const auto& npad = GetResourceManager()->GetNpad(); - const Result result = - npad->GetMaskedSupportedNpadStyleSet(applet_resource_user_id, supported_styleset); + const auto npad = GetResourceManager()->GetNpad(); + const Result result = npad->GetMaskedSupportedNpadStyleSet(system.Kernel(), applet_resource_user_id, supported_styleset); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(result); @@ -373,9 +372,8 @@ void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - const auto& npad = GetResourceManager()->GetNpad(); - const auto result = - npad->SetSupportedNpadStyleSet(applet_resource_user_id, Core::HID::NpadStyleSet::All); + const auto npad = GetResourceManager()->GetNpad(); + const auto result = npad->SetSupportedNpadStyleSet(system.Kernel(), applet_resource_user_id, Core::HID::NpadStyleSet::All); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp index 8db8f8538c..ce7591656a 100644 --- a/src/core/hle/service/hle_ipc.cpp +++ b/src/core/hle/service/hle_ipc.cpp @@ -275,17 +275,17 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer() { for (auto& object : outgoing_copy_objects) { Handle handle{}; if (object) { - R_TRY(handle_table.Add(&handle, object)); + R_TRY(handle_table.Add(kernel, &handle, object)); } cmd_buf[current_offset++] = handle; } for (auto& object : outgoing_move_objects) { Handle handle{}; if (object) { - R_TRY(handle_table.Add(&handle, object)); + R_TRY(handle_table.Add(kernel, &handle, object)); // Close our reference to the object, as it is being moved to the caller. - object->Close(); + object->Close(kernel); } cmd_buf[current_offset++] = handle; } @@ -503,11 +503,10 @@ bool HLERequestContext::CanWriteBuffer(std::size_t buffer_index) const { } void HLERequestContext::AddMoveInterface(SessionRequestHandlerPtr s) { - ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve( - Kernel::LimitableResource::SessionCountMax, 1)); + ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve(kernel, Kernel::LimitableResource::SessionCountMax, 1)); auto* session = Kernel::KSession::Create(kernel); - session->Initialize(nullptr, 0); + session->Initialize(kernel, nullptr, 0); Kernel::KSession::Register(kernel, session); auto& server = manager.lock()->GetServerManager(); diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h index ec8185a09e..eeb5bf3547 100644 --- a/src/core/hle/service/hle_ipc.h +++ b/src/core/hle/service/hle_ipc.h @@ -373,11 +373,10 @@ public: template <typename T> Kernel::KScopedAutoObject<T> GetObjectFromHandle(u32 handle) { - auto obj = client_handle_table->GetObjectForIpc(handle, thread); - if (obj.IsNotNull()) { - return obj->DynamicCast<T*>(); - } - return nullptr; + auto obj = client_handle_table->GetObjectForIpc(kernel, handle, thread); + if (obj.IsNotNull()) + return {kernel, obj->DynamicCast<T*>()}; + return {kernel, nullptr}; } [[nodiscard]] std::shared_ptr<SessionRequestManager> GetManager() const { diff --git a/src/core/hle/service/ipc_helpers.h b/src/core/hle/service/ipc_helpers.h index 8aee17db8d..c37b0c2e05 100644 --- a/src/core/hle/service/ipc_helpers.h +++ b/src/core/hle/service/ipc_helpers.h @@ -151,11 +151,10 @@ public: if (manager->IsDomain()) { context->AddDomainObject(std::move(iface)); } else { - ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve( - Kernel::LimitableResource::SessionCountMax, 1)); + ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve(kernel, Kernel::LimitableResource::SessionCountMax, 1)); auto* session = Kernel::KSession::Create(kernel); - session->Initialize(nullptr, 0); + session->Initialize(kernel, nullptr, 0); Kernel::KSession::Register(kernel, session); auto next_manager = std::make_shared<Service::SessionRequestManager>( diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index 1179e8b61d..626b643c00 100644 --- a/src/core/hle/service/jit/jit.cpp +++ b/src/core/hle/service/jit/jit.cpp @@ -30,12 +30,13 @@ static_assert(sizeof(Struct32) == 32, "Struct32 has wrong size"); class IJitEnvironment final : public ServiceFramework<IJitEnvironment> { public: - explicit IJitEnvironment(Core::System& system_, - Kernel::KScopedAutoObject<Kernel::KProcess> process_, - CodeMemory&& user_rx_, CodeMemory&& user_ro_) - : ServiceFramework{system_, "IJitEnvironment"}, process{std::move(process_)}, - user_rx{std::move(user_rx_)}, user_ro{std::move(user_ro_)}, - context{system_.ApplicationMemory()} { + explicit IJitEnvironment(Core::System& system_, Kernel::KProcess* process_, CodeMemory&& user_rx_, CodeMemory&& user_ro_) + : ServiceFramework{system_, "IJitEnvironment"} + , process{kernel, process_} + , user_rx{std::move(user_rx_)} + , user_ro{std::move(user_ro_)} + , context{system_.ApplicationMemory()} + { // clang-format off static const FunctionInfo functions[] = { @@ -58,6 +59,11 @@ public: configuration.sys_ro_memory = configuration.user_ro_memory; } + ~IJitEnvironment() { + user_rx.Finalize(system.Kernel()); + user_ro.Finalize(system.Kernel()); + } + Result GenerateCode(Out<s32> out_return_value, Out<CodeRange> out_range0, Out<CodeRange> out_range1, OutBuffer<BufferAttr_HipcMapAlias> out_buffer, u32 data_size, u64 command, CodeRange range0, CodeRange range1, @@ -281,14 +287,9 @@ private: } CodeMemory rx, ro; - - R_TRY(rx.Initialize(*process, *rx_mem, rx_size, Kernel::Svc::MemoryPermission::ReadExecute, - generate_random)); - R_TRY(ro.Initialize(*process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read, - generate_random)); - - *out_jit_environment = - std::make_shared<IJitEnvironment>(system, process.Get(), std::move(rx), std::move(ro)); + R_TRY(rx.Initialize(system.Kernel(), *process, *rx_mem, rx_size, Kernel::Svc::MemoryPermission::ReadExecute, generate_random)); + R_TRY(ro.Initialize(system.Kernel(), *process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read, generate_random)); + *out_jit_environment = std::make_shared<IJitEnvironment>(system, process.Get(), std::move(rx), std::move(ro)); R_SUCCEED(); } diff --git a/src/core/hle/service/jit/jit_code_memory.cpp b/src/core/hle/service/jit/jit_code_memory.cpp index 2b480488a8..3218512af4 100644 --- a/src/core/hle/service/jit/jit_code_memory.cpp +++ b/src/core/hle/service/jit/jit_code_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -5,12 +8,9 @@ namespace Service::JIT { -Result CodeMemory::Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, - size_t size, Kernel::Svc::MemoryPermission perm, - std::mt19937_64& generate_random) { +Result CodeMemory::Initialize(Kernel::KernelCore& kernel, Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random) { auto& page_table = process.GetPageTable(); - const u64 alias_code_start = - GetInteger(page_table.GetAliasCodeRegionStart()) / Kernel::PageSize; + const u64 alias_code_start = GetInteger(page_table.GetAliasCodeRegionStart()) / Kernel::PageSize; const u64 alias_code_size = page_table.GetAliasCodeRegionSize() / Kernel::PageSize; // NOTE: This will retry indefinitely until mapping the code memory succeeds. @@ -20,7 +20,7 @@ Result CodeMemory::Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& co (alias_code_start + (generate_random() % alias_code_size)) * Kernel::PageSize; // Try to map the address - R_TRY_CATCH(code_memory.MapToOwner(mapped_address, size, perm)) { + R_TRY_CATCH(code_memory.MapToOwner(kernel, mapped_address, size, perm)) { R_CATCH(Kernel::ResultInvalidMemoryRegion) { // If we could not map here, retry. continue; @@ -35,17 +35,17 @@ Result CodeMemory::Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& co m_perm = perm; // Open a new reference to the code memory. - m_code_memory->Open(); + m_code_memory->Open(kernel); // We succeeded. R_SUCCEED(); } } -void CodeMemory::Finalize() { +void CodeMemory::Finalize(Kernel::KernelCore& kernel) { if (m_code_memory) { - R_ASSERT(m_code_memory->UnmapFromOwner(m_address, m_size)); - m_code_memory->Close(); + R_ASSERT(m_code_memory->UnmapFromOwner(kernel, m_address, m_size)); + m_code_memory->Close(kernel); } m_code_memory = nullptr; diff --git a/src/core/hle/service/jit/jit_code_memory.h b/src/core/hle/service/jit/jit_code_memory.h index 6376d4c4eb..d741520aeb 100644 --- a/src/core/hle/service/jit/jit_code_memory.h +++ b/src/core/hle/service/jit/jit_code_memory.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,29 +10,16 @@ #include "core/hle/kernel/k_code_memory.h" +namespace Kernel { +class KernelCore; +} + namespace Service::JIT { class CodeMemory { public: - YUZU_NON_COPYABLE(CodeMemory); - - explicit CodeMemory() = default; - - CodeMemory(CodeMemory&& rhs) { - std::swap(m_code_memory, rhs.m_code_memory); - std::swap(m_size, rhs.m_size); - std::swap(m_address, rhs.m_address); - std::swap(m_perm, rhs.m_perm); - } - - ~CodeMemory() { - this->Finalize(); - } - -public: - Result Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, - Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random); - void Finalize(); + Result Initialize(Kernel::KernelCore& kernel, Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random); + void Finalize(Kernel::KernelCore& kernel); size_t GetSize() const { return m_size; @@ -39,7 +29,6 @@ public: return m_address; } -private: Kernel::KCodeMemory* m_code_memory{}; size_t m_size{}; u64 m_address{}; diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index f080f7ffa2..f7a5cb7049 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp @@ -1,3 +1,6 @@ +// 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 @@ -14,15 +17,15 @@ namespace Service::KernelHelpers { ServiceContext::ServiceContext(Core::System& system_, std::string name_) - : kernel(system_.Kernel()) { + : kernel(system_.Kernel()) +{ if (process = Kernel::GetCurrentProcessPointer(kernel); process != nullptr) { return; } // Create the process. process = Kernel::KProcess::Create(kernel); - ASSERT(R_SUCCEEDED(process->Initialize(Kernel::Svc::CreateProcessParameter{}, - kernel.GetSystemResourceLimit(), false))); + ASSERT(R_SUCCEEDED(process->Initialize(kernel, Kernel::Svc::CreateProcessParameter{}, kernel.GetSystemResourceLimit(), false))); // Register the process. Kernel::KProcess::Register(kernel, process); @@ -31,14 +34,14 @@ ServiceContext::ServiceContext(Core::System& system_, std::string name_) ServiceContext::~ServiceContext() { if (process_created) { - process->Close(); + process->Close(kernel); process = nullptr; } } Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { // Reserve a new event from the process resource limit - Kernel::KScopedResourceReservation event_reservation(process, + Kernel::KScopedResourceReservation event_reservation(kernel, process, Kernel::LimitableResource::EventCountMax); if (!event_reservation.Succeeded()) { LOG_CRITICAL(Service, "Resource limit reached!"); @@ -53,7 +56,7 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { } // Initialize the event. - event->Initialize(process); + event->Initialize(kernel, process); // Commit the thread reservation. event_reservation.Commit(); @@ -65,11 +68,10 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { } void ServiceContext::CloseEvent(Kernel::KEvent* event) { - if (!event) { - return; + if (event) { + event->GetReadableEvent().Close(kernel); + event->Close(kernel); } - event->GetReadableEvent().Close(); - event->Close(); } } // namespace Service::KernelHelpers diff --git a/src/core/hle/service/kernel_helpers.h b/src/core/hle/service/kernel_helpers.h index eca9aefb52..4e21c8857f 100644 --- a/src/core/hle/service/kernel_helpers.h +++ b/src/core/hle/service/kernel_helpers.h @@ -1,3 +1,6 @@ +// 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 @@ -26,7 +29,6 @@ public: void CloseEvent(Kernel::KEvent* event); -private: Kernel::KernelCore& kernel; Kernel::KProcess* process{}; bool process_created{false}; diff --git a/src/core/hle/service/ldn/user_local_communication_service.cpp b/src/core/hle/service/ldn/user_local_communication_service.cpp index 1e984a9782..572aea6314 100644 --- a/src/core/hle/service/ldn/user_local_communication_service.cpp +++ b/src/core/hle/service/ldn/user_local_communication_service.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -322,7 +322,7 @@ void IUserLocalCommunicationService::OnLDNPacketReceived(const Network::LDNPacke } void IUserLocalCommunicationService::OnEventFired() { - state_change_event->Signal(); + state_change_event->Signal(system.Kernel()); } } // namespace Service::LDN diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index faa2b1f584..2876c6f739 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -71,13 +71,13 @@ NfcDevice::~NfcDevice() { void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { if (type == Core::HID::ControllerTriggerType::Connected) { Initialize(); - availability_change_event->Signal(); + availability_change_event->Signal(system.Kernel()); return; } if (type == Core::HID::ControllerTriggerType::Disconnected) { Finalize(); - availability_change_event->Signal(); + availability_change_event->Signal(system.Kernel()); return; } @@ -138,8 +138,8 @@ bool NfcDevice::LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSeria }; device_state = DeviceState::TagFound; - deactivate_event->GetReadableEvent().Clear(); - activate_event->Signal(); + deactivate_event->GetReadableEvent().Clear(system.Kernel()); + activate_event->Signal(system.Kernel()); return true; } @@ -192,8 +192,8 @@ void NfcDevice::CloseNfcTag() { device_state = DeviceState::TagRemoved; encrypted_tag_data = {}; tag_data = {}; - activate_event->GetReadableEvent().Clear(); - deactivate_event->Signal(); + activate_event->GetReadableEvent().Clear(system.Kernel()); + deactivate_event->Signal(system.Kernel()); } Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const { diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 7bd06e2e0f..87e806d86b 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -275,7 +275,7 @@ private: } state.store(State::Processing); - evt_processing->Signal(); + evt_processing->Signal(system.Kernel()); worker = std::thread([this]() { using namespace std::chrono_literals; @@ -321,7 +321,7 @@ private: void Finish(Result rc) { worker_result.store(rc); state.store(State::Finished); - evt_scan_complete->Signal(); + evt_scan_complete->Signal(system.Kernel()); } KernelHelpers::ServiceContext svc_ctx; @@ -486,7 +486,7 @@ private: void UpdateState(RequestState new_state) { LOG_DEBUG(Service_NIFM, "(STUBBED) called"); state = new_state; - event1->Signal(); + event1->Signal(system.Kernel()); } KernelHelpers::ServiceContext service_context; diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index 4f465c5da7..5f85302713 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -429,7 +429,7 @@ private: void StartTask(HLERequestContext& ctx) { // No need to connect to the internet, just finish the task straight away. LOG_DEBUG(Service_NIM, "called"); - finished_event->Signal(); + finished_event->Signal(system.Kernel()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -451,7 +451,7 @@ private: void Cancel(HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); - finished_event->Clear(); + finished_event->Clear(system.Kernel()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } diff --git a/src/core/hle/service/ns/application_manager_interface.cpp b/src/core/hle/service/ns/application_manager_interface.cpp index 5490c09d03..485eac0afa 100644 --- a/src/core/hle/service/ns/application_manager_interface.cpp +++ b/src/core/hle/service/ns/application_manager_interface.cpp @@ -610,7 +610,7 @@ Result IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent( OutCopyHandle<Kernel::KReadableEvent> out_event) { LOG_WARNING(Service_NS, "(STUBBED) called"); - record_update_system_event.Signal(); + record_update_system_event.Signal(system.Kernel()); *out_event = record_update_system_event.GetHandle(); R_SUCCEED(); @@ -820,14 +820,14 @@ Result IApplicationManagerInterface::RequestDownloadApplicationControlDataInBack LOG_INFO(Service_NS, "called, control_source={} app={:016X}", control_source, application_id); - unknown_event.Signal(); + unknown_event.Signal(system.Kernel()); R_SUCCEED(); } Result IApplicationManagerInterface::Unknown4022( OutCopyHandle<Kernel::KReadableEvent> out_event) { LOG_WARNING(Service_NS, "(STUBBED) called"); - unknown_event.Signal(); + unknown_event.Signal(system.Kernel()); *out_event = unknown_event.GetHandle(); R_SUCCEED(); } diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.cpp b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp index 03f0a17865..f12d9b03d2 100644 --- a/src/core/hle/service/ns/read_only_application_control_data_interface.cpp +++ b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp @@ -87,7 +87,7 @@ public: RegisterHandlers(functions); completion_event = service_context.CreateEvent("IAsyncValue:Completion"); - completion_event->GetReadableEvent().Signal(); + completion_event->GetReadableEvent().Signal(system.Kernel()); } ~IAsyncValueForListApplicationTitle() override { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 3bfef0c29c..1238a21f85 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -138,8 +138,7 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { static_cast<u32>((vm.va_range_end - vm.va_range_split) >> vm.big_page_size_bits)}; vm.big_page_allocator.emplace(start_big_pages, end_big_pages); - gmmu = std::make_shared<Tegra::MemoryManager>(system, max_big_page_bits, vm.va_range_split, - vm.big_page_size_bits, VM::PAGE_SIZE_BITS); + gmmu = std::make_unique<Tegra::MemoryManager>(system, max_big_page_bits, vm.va_range_split, vm.big_page_size_bits, VM::PAGE_SIZE_BITS); system.GPU().InitAddressSpace(*gmmu); vm.initialised = true; @@ -416,7 +415,7 @@ NvResult nvhost_as_gpu::BindChannel(IoctlBindChannel& params) { LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); auto gpu_channel_device = module.GetDevice<nvhost_gpu>(params.fd); - gpu_channel_device->channel_state->memory_manager = gmmu; + gpu_channel_device->channel_state->memory_manager = gmmu.get(); return NvResult::Success; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 44892ee368..b8ae57e1b4 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -219,7 +219,7 @@ private: bool initialised{}; } vm; - std::shared_ptr<Tegra::MemoryManager> gmmu; + std::unique_ptr<Tegra::MemoryManager> gmmu; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index b2580f2bb9..6ef32b890f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -203,7 +203,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_a auto& event_ = events[slot]; if (event_.status.exchange(EventState::Signalling, std::memory_order_acq_rel) == EventState::Waiting) { - event_.kevent->Signal(); + event_.kevent->Signal(system.Kernel()); } event_.status.store(EventState::Signalled, std::memory_order_release); }); @@ -292,7 +292,7 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(IocCtrlEventClearParams& params) { } event.fails++; event.status.store(EventState::Cancelled, std::memory_order_release); - event.kevent->Clear(); + event.kevent->Clear(system.Kernel()); return NvResult::Success; } diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index 5bd53fb99e..c3eb2796e3 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -111,7 +111,7 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { core->override_max_buffer_count = buffer_count; core->SignalDequeueCondition(); - buffer_wait_event->Signal(); + buffer_wait_event->Signal(service_context.kernel); listener = core->consumer_listener; } @@ -576,7 +576,7 @@ void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) { slots[slot].fence = fence; core->SignalDequeueCondition(); - buffer_wait_event->Signal(); + buffer_wait_event->Signal(service_context.kernel); } Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { @@ -714,7 +714,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { core->connected_producer_listener = nullptr; core->connected_api = NativeWindowApi::NoConnectedApi; core->SignalDequeueCondition(); - buffer_wait_event->Signal(); + buffer_wait_event->Signal(service_context.kernel); listener = core->consumer_listener; } else { LOG_ERROR(Service_Nvnflinger, @@ -764,7 +764,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, } core->SignalDequeueCondition(); - buffer_wait_event->Signal(); + buffer_wait_event->Signal(service_context.kernel); return Status::NoError; } diff --git a/src/core/hle/service/olsc/native_handle_holder.cpp b/src/core/hle/service/olsc/native_handle_holder.cpp index d381714bc3..1e50195539 100644 --- a/src/core/hle/service/olsc/native_handle_holder.cpp +++ b/src/core/hle/service/olsc/native_handle_holder.cpp @@ -32,7 +32,7 @@ INativeHandleHolder::~INativeHandleHolder() { Result INativeHandleHolder::GetNativeHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) { LOG_WARNING(Service_OLSC, "(STUBBED) called"); if (event) { - event->Signal(); + event->Signal(system.Kernel()); *out_event = std::addressof(event->GetReadableEvent()); } else { *out_event = nullptr; diff --git a/src/core/hle/service/os/event.cpp b/src/core/hle/service/os/event.cpp index ec52c17fd8..8808c5b4f0 100644 --- a/src/core/hle/service/os/event.cpp +++ b/src/core/hle/service/os/event.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,25 +10,27 @@ namespace Service { -Event::Event(KernelHelpers::ServiceContext& ctx) { +Event::Event(KernelHelpers::ServiceContext& ctx_) + : ctx{ctx_} +{ m_event = ctx.CreateEvent("Event"); } Event::~Event() { - m_event->GetReadableEvent().Close(); - m_event->Close(); + m_event->GetReadableEvent().Close(ctx.kernel); + m_event->Close(ctx.kernel); } -void Event::Signal() { - m_event->Signal(); +void Event::Signal(Kernel::KernelCore& kernel) noexcept { + m_event->Signal(kernel); } -void Event::Clear() { - m_event->Clear(); +void Event::Clear(Kernel::KernelCore& kernel) noexcept { + m_event->Clear(kernel); } -Kernel::KReadableEvent* Event::GetHandle() { - return &m_event->GetReadableEvent(); +Kernel::KReadableEvent* Event::GetHandle() noexcept { + return std::addressof(m_event->GetReadableEvent()); } } // namespace Service diff --git a/src/core/hle/service/os/event.h b/src/core/hle/service/os/event.h index cdbc4635a6..bc23598b58 100644 --- a/src/core/hle/service/os/event.h +++ b/src/core/hle/service/os/event.h @@ -1,9 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once namespace Kernel { +class KernelCore; class KEvent; class KReadableEvent; } // namespace Kernel @@ -19,12 +23,12 @@ public: explicit Event(KernelHelpers::ServiceContext& ctx); ~Event(); - void Signal(); - void Clear(); - - Kernel::KReadableEvent* GetHandle(); + void Signal(Kernel::KernelCore& kernel) noexcept; + void Clear(Kernel::KernelCore& kernel) noexcept; + Kernel::KReadableEvent* GetHandle() noexcept; private: + KernelHelpers::ServiceContext& ctx; Kernel::KEvent* m_event; }; diff --git a/src/core/hle/service/os/mutex.cpp b/src/core/hle/service/os/mutex.cpp index 6009f48668..12b872b57f 100644 --- a/src/core/hle/service/os/mutex.cpp +++ b/src/core/hle/service/os/mutex.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,22 +13,22 @@ namespace Service { Mutex::Mutex(Core::System& system) : m_system(system) { m_event = Kernel::KEvent::Create(system.Kernel()); - m_event->Initialize(nullptr); + m_event->Initialize(system.Kernel(), nullptr); // Register the event. Kernel::KEvent::Register(system.Kernel(), m_event); - ASSERT(R_SUCCEEDED(m_event->Signal())); + ASSERT(R_SUCCEEDED(m_event->Signal(system.Kernel()))); } Mutex::~Mutex() { - m_event->GetReadableEvent().Close(); - m_event->Close(); + m_event->GetReadableEvent().Close(m_system.Kernel()); + m_event->Close(m_system.Kernel()); } void Mutex::lock() { // Infinitely retry until we successfully clear the event. - while (R_FAILED(m_event->GetReadableEvent().Reset())) { + while (R_FAILED(m_event->GetReadableEvent().Reset(m_system.Kernel()))) { s32 index; Kernel::KSynchronizationObject* obj = &m_event->GetReadableEvent(); @@ -40,7 +43,7 @@ void Mutex::lock() { void Mutex::unlock() { // Unlock. - ASSERT(R_SUCCEEDED(m_event->Signal())); + ASSERT(R_SUCCEEDED(m_event->Signal(m_system.Kernel()))); } } // namespace Service diff --git a/src/core/hle/service/os/process.cpp b/src/core/hle/service/os/process.cpp index 0dbadc315e..5e46de245d 100644 --- a/src/core/hle/service/os/process.cpp +++ b/src/core/hle/service/os/process.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,14 +13,6 @@ namespace Service { -Process::Process(Core::System& system) - : m_system(system), m_process(), m_main_thread_priority(), m_main_thread_stack_size(), - m_process_started() {} - -Process::~Process() { - this->Finalize(); -} - bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_load_result) { // First, ensure we are not holding another process. this->Finalize(); @@ -28,7 +23,7 @@ bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_lo // On exit, ensure we free the additional reference to the process. SCOPE_EXIT { - process->Close(); + process->Close(m_system.Kernel()); }; // Insert process modules into memory. @@ -52,7 +47,7 @@ bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_lo // Take ownership of the process object. m_process = process; - m_process->Open(); + m_process->Open(m_system.Kernel()); // We succeeded. return true; @@ -64,8 +59,7 @@ void Process::Finalize() { // Close the process. if (m_process) { - m_process->Close(); - + m_process->Close(m_system.Kernel()); // TODO: remove this, kernel already tracks this m_system.Kernel().RemoveProcess(m_process); } @@ -85,7 +79,7 @@ bool Process::Run() { // Start. if (m_process) { - m_process->Run(m_main_thread_priority, m_main_thread_stack_size); + m_process->Run(m_system.Kernel(), m_main_thread_priority, m_main_thread_stack_size); } // Mark as started. @@ -97,13 +91,13 @@ bool Process::Run() { void Process::Terminate() { if (m_process) { - m_process->Terminate(); + m_process->Terminate(m_system.Kernel()); } } void Process::ResetSignal() { if (m_process) { - m_process->Reset(); + m_process->Reset(m_system.Kernel()); } } @@ -144,8 +138,7 @@ u64 Process::GetProgramId() const { void Process::Suspend(bool suspended) { if (m_process) { - m_process->SetActivity(suspended ? Kernel::Svc::ProcessActivity::Paused - : Kernel::Svc::ProcessActivity::Runnable); + m_process->SetActivity(m_system.Kernel(), suspended ? Kernel::Svc::ProcessActivity::Paused : Kernel::Svc::ProcessActivity::Runnable); } } diff --git a/src/core/hle/service/os/process.h b/src/core/hle/service/os/process.h index 9109b7d0a5..ca10945f84 100644 --- a/src/core/hle/service/os/process.h +++ b/src/core/hle/service/os/process.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,8 +25,8 @@ namespace Service { class Process { public: - explicit Process(Core::System& system); - ~Process(); + inline explicit Process(Core::System& system) noexcept : m_system(system) {} + inline ~Process() { this->Finalize(); } bool Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_load_result); void Finalize(); @@ -50,8 +53,8 @@ public: private: Core::System& m_system; Kernel::KProcess* m_process{}; - s32 m_main_thread_priority{}; u64 m_main_thread_stack_size{}; + s32 m_main_thread_priority{}; bool m_process_started{}; }; diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index b52468e419..5f94984f4e 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -25,19 +28,15 @@ constexpr u64 NO_PROCESS_FOUND_PID{0}; using ProcessList = std::list<Kernel::KScopedAutoObject<Kernel::KProcess>>; template <typename F> -Kernel::KScopedAutoObject<Kernel::KProcess> SearchProcessList(ProcessList& process_list, - F&& predicate) { - const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); - - if (iter == process_list.end()) { - return nullptr; - } - - return iter->GetPointerUnsafe(); +Kernel::KScopedAutoObject<Kernel::KProcess> SearchProcessList(Kernel::KernelCore& kernel, ProcessList& process_list, F&& predicate) { + auto const it = std::find_if(process_list.begin(), process_list.end(), predicate); + if (it == process_list.end()) + return {kernel, nullptr}; + return {kernel, it->GetPointerUnsafe()}; } -void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) { - auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); }); +void GetApplicationPidGeneric(Kernel::KernelCore& kernel, HLERequestContext& ctx, ProcessList& process_list) { + auto process = SearchProcessList(kernel, process_list, [](auto& p) { return p->IsApplication(); }); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); @@ -105,7 +104,7 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); auto list = kernel.GetProcessList(); - auto process = SearchProcessList( + auto process = SearchProcessList(system.Kernel(), list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); if (process.IsNull()) { @@ -122,7 +121,7 @@ private: void GetApplicationProcessId(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(ctx, list); + GetApplicationPidGeneric(system.Kernel(), ctx, list); } void AtmosphereGetProcessInfo(HLERequestContext& ctx) { @@ -134,7 +133,7 @@ private: LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); auto list = kernel.GetProcessList(); - auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; }); + auto process = SearchProcessList(system.Kernel(), list, [pid](auto& p) { return p->GetProcessId() == pid; }); if (process.IsNull()) { IPC::ResponseBuilder rb{ctx, 2}; @@ -188,7 +187,7 @@ private: LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); auto list = kernel.GetProcessList(); - auto process = SearchProcessList( + auto process = SearchProcessList(system.Kernel(), list, [process_id](auto& p) { return p->GetProcessId() == process_id; }); if (process.IsNull()) { @@ -209,7 +208,7 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); auto list = system.Kernel().GetProcessList(); - auto process = SearchProcessList( + auto process = SearchProcessList(system.Kernel(), list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); if (process.IsNull()) { @@ -249,7 +248,7 @@ private: void GetApplicationProcessIdForShell(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(ctx, list); + GetApplicationPidGeneric(system.Kernel(), ctx, list); } }; diff --git a/src/core/hle/service/psc/ovln/receiver.cpp b/src/core/hle/service/psc/ovln/receiver.cpp index f7d3882a05..f43d705126 100644 --- a/src/core/hle/service/psc/ovln/receiver.cpp +++ b/src/core/hle/service/psc/ovln/receiver.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -100,7 +100,7 @@ Result IReceiver::ReceiveWithTick(Out<OverlayNotification> out_notification, } } if (!has_messages) { - receive_event->Clear(); + receive_event->Clear(system.Kernel()); } R_SUCCEED(); diff --git a/src/core/hle/service/psc/time/alarms.cpp b/src/core/hle/service/psc/time/alarms.cpp index 5e52c19f82..c2de95f653 100644 --- a/src/core/hle/service/psc/time/alarms.cpp +++ b/src/core/hle/service/psc/time/alarms.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,8 +10,10 @@ namespace Service::PSC::Time { Alarm::Alarm(Core::System& system, KernelHelpers::ServiceContext& ctx, AlarmType type) - : m_ctx{ctx}, m_event{ctx.CreateEvent("Psc:Alarm:Event")} { - m_event->Clear(); + : m_ctx{ctx} + , m_event{ctx.CreateEvent("Psc:Alarm:Event")} +{ + m_event->Clear(system.Kernel()); switch (type) { case WakeupAlarm: @@ -37,7 +42,7 @@ Alarms::~Alarms() { m_ctx.CloseEvent(m_event); } -Result Alarms::Enable(Alarm& alarm, s64 time) { +Result Alarms::Enable(Kernel::KernelCore& kernel, Alarm& alarm, s64 time) { R_UNLESS(m_steady_clock.IsInitialized(), ResultClockUninitialized); std::scoped_lock l{m_mutex}; @@ -49,21 +54,21 @@ Result Alarms::Enable(Alarm& alarm, s64 time) { time_ns = Common::AlignUp(time_ns, one_second_ns); alarm.SetAlertTime(time_ns); - Insert(alarm); - R_RETURN(UpdateClosestAndSignal()); + Insert(kernel, alarm); + R_RETURN(UpdateClosestAndSignal(kernel)); } -void Alarms::Disable(Alarm& alarm) { +void Alarms::Disable(Kernel::KernelCore& kernel, Alarm& alarm) { std::scoped_lock l{m_mutex}; if (!alarm.IsLinked()) { return; } - Erase(alarm); - UpdateClosestAndSignal(); + Erase(kernel, alarm); + UpdateClosestAndSignal(kernel); } -void Alarms::CheckAndSignal() { +void Alarms::CheckAndSignal(Kernel::KernelCore& kernel) { std::scoped_lock l{m_mutex}; if (m_alarms.empty()) { return; @@ -72,9 +77,9 @@ void Alarms::CheckAndSignal() { bool alarm_signalled{false}; for (auto& alarm : m_alarms) { if (m_steady_clock.GetRawTime() >= alarm.GetAlertTime()) { - alarm.Signal(); + alarm.Signal(kernel); alarm.Lock(); - Erase(alarm); + Erase(kernel, alarm); m_power_state_request_manager.UpdatePendingPowerStateRequestPriority( alarm.GetPriority()); @@ -87,7 +92,7 @@ void Alarms::CheckAndSignal() { } m_power_state_request_manager.SignalPowerStateRequestAvailability(); - UpdateClosestAndSignal(); + UpdateClosestAndSignal(kernel); } bool Alarms::GetClosestAlarm(Alarm** out_alarm) { @@ -97,7 +102,7 @@ bool Alarms::GetClosestAlarm(Alarm** out_alarm) { return alarm != nullptr; } -void Alarms::Insert(Alarm& alarm) { +void Alarms::Insert(Kernel::KernelCore& kernel, Alarm& alarm) { // Alarms are sorted by alert time, then priority auto it{m_alarms.begin()}; while (it != m_alarms.end()) { @@ -113,15 +118,15 @@ void Alarms::Insert(Alarm& alarm) { m_alarms.push_back(alarm); } -void Alarms::Erase(Alarm& alarm) { +void Alarms::Erase(Kernel::KernelCore& kernel, Alarm& alarm) { m_alarms.erase(m_alarms.iterator_to(alarm)); } -Result Alarms::UpdateClosestAndSignal() { +Result Alarms::UpdateClosestAndSignal(Kernel::KernelCore& kernel) { m_closest_alarm = m_alarms.empty() ? nullptr : std::addressof(m_alarms.front()); R_SUCCEED_IF(m_closest_alarm == nullptr); - m_event->Signal(); + m_event->Signal(kernel); R_SUCCEED(); } @@ -183,7 +188,7 @@ void ISteadyClockAlarm::Enable(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto time{rp.Pop<s64>()}; - auto res = m_alarms.Enable(m_alarm, time); + auto res = m_alarms.Enable(system.Kernel(), m_alarm, time); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res); @@ -192,7 +197,7 @@ void ISteadyClockAlarm::Enable(HLERequestContext& ctx) { void ISteadyClockAlarm::Disable(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called."); - m_alarms.Disable(m_alarm); + m_alarms.Disable(system.Kernel(), m_alarm); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/psc/time/alarms.h b/src/core/hle/service/psc/time/alarms.h index 597770028b..79b66c06ea 100644 --- a/src/core/hle/service/psc/time/alarms.h +++ b/src/core/hle/service/psc/time/alarms.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -48,8 +51,8 @@ struct Alarm : public Common::IntrusiveListBaseNode<Alarm> { return m_priority; } - void Signal() { - m_event->Signal(); + void Signal(Kernel::KernelCore& kernel) { + m_event->Signal(kernel); } Result Lock() { @@ -83,15 +86,15 @@ public: return m_steady_clock.GetRawTime(); } - Result Enable(Alarm& alarm, s64 time); - void Disable(Alarm& alarm); - void CheckAndSignal(); + Result Enable(Kernel::KernelCore& kernel, Alarm& alarm, s64 time); + void Disable(Kernel::KernelCore& kernel, Alarm& alarm); + void CheckAndSignal(Kernel::KernelCore& kernel); bool GetClosestAlarm(Alarm** out_alarm); private: - void Insert(Alarm& alarm); - void Erase(Alarm& alarm); - Result UpdateClosestAndSignal(); + void Insert(Kernel::KernelCore& kernel, Alarm& alarm); + void Erase(Kernel::KernelCore& kernel, Alarm& alarm); + Result UpdateClosestAndSignal(Kernel::KernelCore& kernel); Core::System& m_system; KernelHelpers::ServiceContext m_ctx; diff --git a/src/core/hle/service/psc/time/clocks/context_writers.cpp b/src/core/hle/service/psc/time/clocks/context_writers.cpp index a44486b438..4e54a07a37 100644 --- a/src/core/hle/service/psc/time/clocks/context_writers.cpp +++ b/src/core/hle/service/psc/time/clocks/context_writers.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -6,10 +9,10 @@ namespace Service::PSC::Time { -void ContextWriter::SignalAllNodes() { +void ContextWriter::SignalAllNodes(Kernel::KernelCore& kernel) { std::scoped_lock l{m_mutex}; for (auto& operation : m_operation_events) { - operation.m_event->Signal(); + operation.m_event->Signal(kernel); } } @@ -33,7 +36,7 @@ Result LocalSystemClockContextWriter::Write(const SystemClockContext& context) { m_shared_memory.SetLocalSystemContext(context); - SignalAllNodes(); + SignalAllNodes(m_system.Kernel()); R_SUCCEED(); } @@ -57,7 +60,7 @@ Result NetworkSystemClockContextWriter::Write(const SystemClockContext& context) m_shared_memory.SetNetworkSystemContext(context); - SignalAllNodes(); + SignalAllNodes(m_system.Kernel()); R_SUCCEED(); } @@ -75,7 +78,7 @@ Result EphemeralNetworkSystemClockContextWriter::Write(const SystemClockContext& m_in_use = true; } - SignalAllNodes(); + SignalAllNodes(m_system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/service/psc/time/clocks/context_writers.h b/src/core/hle/service/psc/time/clocks/context_writers.h index 6643fc9f2a..2adc7d2546 100644 --- a/src/core/hle/service/psc/time/clocks/context_writers.h +++ b/src/core/hle/service/psc/time/clocks/context_writers.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,6 +14,9 @@ #include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/shared_memory.h" +namespace Kernel { +class KernelCore; +} namespace Core { class System; } @@ -25,7 +31,7 @@ public: virtual ~ContextWriter() = default; virtual Result Write(const SystemClockContext& context) = 0; - void SignalAllNodes(); + void SignalAllNodes(Kernel::KernelCore& kernel); void Link(OperationEvent& operation_event); private: diff --git a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp index 31ed273966..7a51e51f3c 100644 --- a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp +++ b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -57,7 +60,7 @@ Result StandardUserSystemClockCore::GetTimePoint(SteadyClockTimePoint& out_time_ void StandardUserSystemClockCore::SetTimePointAndSignal(SteadyClockTimePoint& time_point) { m_time_point = time_point; - m_event->Signal(); + m_event->Signal(m_system.Kernel()); } } // namespace Service::PSC::Time diff --git a/src/core/hle/service/psc/time/power_state_request_manager.cpp b/src/core/hle/service/psc/time/power_state_request_manager.cpp index b28b513649..7a494f47cb 100644 --- a/src/core/hle/service/psc/time/power_state_request_manager.cpp +++ b/src/core/hle/service/psc/time/power_state_request_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -35,7 +35,7 @@ void PowerStateRequestManager::SignalPowerStateRequestAvailability() { } m_has_pending_request = false; m_available_request_priority = m_pending_request_priority; - m_event->Signal(); + m_event->Signal(m_system.Kernel()); } } @@ -45,7 +45,7 @@ bool PowerStateRequestManager::GetAndClearPowerStateRequest(u32& out_priority) { if (m_has_available_request) { out_priority = m_available_request_priority; m_has_available_request = false; - m_event->Clear(); + m_event->Clear(m_system.Kernel()); } return had_request; } diff --git a/src/core/hle/service/psc/time/service_manager.cpp b/src/core/hle/service/psc/time/service_manager.cpp index ed9fb32cdf..4646def3db 100644 --- a/src/core/hle/service/psc/time/service_manager.cpp +++ b/src/core/hle/service/psc/time/service_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -238,7 +241,7 @@ Result ServiceManager::GetClosestAlarmUpdatedEvent( Result ServiceManager::CheckAndSignalAlarms() { LOG_DEBUG(Service_Time, "called."); - m_alarms.CheckAndSignal(); + m_alarms.CheckAndSignal(m_system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp index 9a0adb2955..488731565d 100644 --- a/src/core/hle/service/psc/time/static.cpp +++ b/src/core/hle/service/psc/time/static.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -171,7 +174,7 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( R_TRY(m_time->m_standard_steady_clock.GetCurrentTimePoint(time_point)); m_user_system_clock.SetTimePointAndSignal(time_point); - m_user_system_clock.GetEvent().Signal(); + m_user_system_clock.GetEvent().Signal(system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp index 06396bbb4c..211f380171 100644 --- a/src/core/hle/service/ptm/psm.cpp +++ b/src/core/hle/service/ptm/psm.cpp @@ -43,19 +43,19 @@ public: void SignalChargerTypeChanged() { if (should_signal && should_signal_charger_type) { - state_change_event->Signal(); + state_change_event->Signal(system.Kernel()); } } void SignalPowerSupplyChanged() { if (should_signal && should_signal_power_supply) { - state_change_event->Signal(); + state_change_event->Signal(system.Kernel()); } } void SignalBatteryVoltageStateChanged() { if (should_signal && should_signal_battery_voltage) { - state_change_event->Signal(); + state_change_event->Signal(system.Kernel()); } } diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp index 895bcad864..879e51c65e 100644 --- a/src/core/hle/service/ro/ro.cpp +++ b/src/core/hle/service/ro/ro.cpp @@ -57,7 +57,7 @@ struct NrrInfo { struct ProcessContext { constexpr ProcessContext() = default; - void Initialize(Kernel::KProcess* process, u64 process_id) { + void Initialize(Kernel::KernelCore& kernel, Kernel::KProcess* process, u64 process_id) { ASSERT(!m_in_use); m_nro_in_use = {}; @@ -70,15 +70,15 @@ struct ProcessContext { m_in_use = true; if (m_process) { - m_process->Open(); + m_process->Open(kernel); } } - void Finalize() { + void Finalize(Kernel::KernelCore& kernel) { ASSERT(m_in_use); if (m_process) { - m_process->Close(); + m_process->Close(kernel); } m_nro_in_use = {}; @@ -307,7 +307,7 @@ class RoContext { public: explicit RoContext() = default; - Result RegisterProcess(size_t* out_context_id, Kernel::KProcess* process, u64 process_id) { + Result RegisterProcess(Kernel::KernelCore& kernel, size_t* out_context_id, Kernel::KProcess* process, u64 process_id) { // Validate process id. R_UNLESS(process->GetProcessId() == process_id, RO::ResultInvalidProcess); @@ -315,7 +315,7 @@ public: R_UNLESS(this->GetContextByProcessId(process_id) == nullptr, RO::ResultInvalidSession); // Allocate a context to manage the process handle. - *out_context_id = this->AllocateContext(process, process_id); + *out_context_id = this->AllocateContext(kernel, process, process_id); R_SUCCEED(); } @@ -327,8 +327,8 @@ public: R_SUCCEED(); } - void UnregisterProcess(size_t context_id) { - this->FreeContext(context_id); + void UnregisterProcess(Kernel::KernelCore& kernel, size_t context_id) { + this->FreeContext(kernel, context_id); } Result RegisterModuleInfo(size_t context_id, u64 nrr_address, u64 nrr_size, NrrKind nrr_kind, @@ -481,13 +481,13 @@ private: return nullptr; } - size_t AllocateContext(Kernel::KProcess* process, u64 process_id) { + size_t AllocateContext(Kernel::KernelCore& kernel, Kernel::KProcess* process, u64 process_id) { // Find a free process context. for (size_t i = 0; i < MaxSessions; i++) { ProcessContext* context = std::addressof(process_contexts[i]); if (context->IsFree()) { - context->Initialize(process, process_id); + context->Initialize(kernel, process, process_id); return i; } } @@ -496,9 +496,9 @@ private: UNREACHABLE(); } - void FreeContext(size_t context_id) { + void FreeContext(Kernel::KernelCore& kernel, size_t context_id) { if (ProcessContext* context = GetContextById(context_id); context != nullptr) { - context->Finalize(); + context->Finalize(kernel); } } }; @@ -525,7 +525,7 @@ public: } ~RoInterface() { - m_ro->UnregisterProcess(m_context_id); + m_ro->UnregisterProcess(system.Kernel(), m_context_id); } Result MapManualLoadModuleMemory(Out<u64> out_load_address, ClientProcessId client_pid, @@ -551,20 +551,16 @@ public: R_RETURN(m_ro->UnregisterModuleInfo(m_context_id, nrr_address)); } - Result RegisterProcessHandle(ClientProcessId client_pid, - InCopyHandle<Kernel::KProcess> process) { + Result RegisterProcessHandle(ClientProcessId client_pid, InCopyHandle<Kernel::KProcess> process) { // Register the process. - R_RETURN(m_ro->RegisterProcess(std::addressof(m_context_id), process.Get(), *client_pid)); + R_RETURN(m_ro->RegisterProcess(system.Kernel(), std::addressof(m_context_id), process.Get(), *client_pid)); } - Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size, - InCopyHandle<Kernel::KProcess> process) { + Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size, InCopyHandle<Kernel::KProcess> process) { // Validate the process. R_TRY(m_ro->ValidateProcess(m_context_id, *client_pid)); - // Register the module. - R_RETURN(m_ro->RegisterModuleInfo(m_context_id, nrr_address, nrr_size, m_nrr_kind, - m_nrr_kind == NrrKind::JitPlugin)); + R_RETURN(m_ro->RegisterModuleInfo(m_context_id, nrr_address, nrr_size, m_nrr_kind, m_nrr_kind == NrrKind::JitPlugin)); } private: diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index 3d898725e8..ee0dc83ee8 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -28,13 +31,15 @@ enum class UserDataTag { class Port : public MultiWaitHolder, public Common::IntrusiveListBaseNode<Port> { public: - explicit Port(Kernel::KServerPort* server_port, SessionRequestHandlerFactory&& handler_factory) - : MultiWaitHolder(server_port), m_handler_factory(std::move(handler_factory)) { + explicit Port(Kernel::KernelCore& kernel, Kernel::KServerPort* server_port, SessionRequestHandlerFactory&& handler_factory) + : MultiWaitHolder(server_port), m_handler_factory(std::move(handler_factory)) + , m_kernel{kernel} + { this->SetUserData(static_cast<uintptr_t>(UserDataTag::Port)); } ~Port() { - this->GetNativeHandle()->Close(); + this->GetNativeHandle()->Close(m_kernel); } SessionRequestHandlerPtr CreateHandler() { @@ -43,18 +48,20 @@ public: private: const SessionRequestHandlerFactory m_handler_factory; + Kernel::KernelCore& m_kernel; }; class Session : public MultiWaitHolder, public Common::IntrusiveListBaseNode<Session> { public: - explicit Session(Kernel::KServerSession* server_session, - std::shared_ptr<SessionRequestManager>&& manager) - : MultiWaitHolder(server_session), m_manager(std::move(manager)) { + explicit Session(Kernel::KernelCore& kernel, Kernel::KServerSession* server_session, std::shared_ptr<SessionRequestManager>&& manager) + : MultiWaitHolder(server_session), m_manager(std::move(manager)) + , m_kernel{kernel} + { this->SetUserData(static_cast<uintptr_t>(UserDataTag::Session)); } ~Session() { - this->GetNativeHandle()->Close(); + this->GetNativeHandle()->Close(m_kernel); } std::shared_ptr<SessionRequestManager>& GetManager() { @@ -68,12 +75,16 @@ public: private: std::shared_ptr<SessionRequestManager> m_manager; std::shared_ptr<HLERequestContext> m_context; + Kernel::KernelCore& m_kernel; }; -ServerManager::ServerManager(Core::System& system) : m_system{system}, m_selection_mutex{system} { +ServerManager::ServerManager(Core::System& system) + : m_system{system} + , m_selection_mutex{system} +{ // Initialize event. m_wakeup_event = Kernel::KEvent::Create(system.Kernel()); - m_wakeup_event->Initialize(nullptr); + m_wakeup_event->Initialize(m_system.Kernel(), nullptr); // Register event. Kernel::KEvent::Register(system.Kernel(), m_wakeup_event); @@ -86,7 +97,7 @@ ServerManager::ServerManager(Core::System& system) : m_system{system}, m_selecti ServerManager::~ServerManager() { // Signal stop. m_stop_source.request_stop(); - m_wakeup_event->Signal(); + m_wakeup_event->Signal(m_system.Kernel()); // Wait for processing to stop. m_stopped.Wait(); @@ -109,11 +120,11 @@ ServerManager::~ServerManager() { } // Close wakeup event. - m_wakeup_event->GetReadableEvent().Close(); - m_wakeup_event->Close(); + m_wakeup_event->GetReadableEvent().Close(m_system.Kernel()); + m_wakeup_event->Close(m_system.Kernel()); if (m_deferral_event) { - m_deferral_event->GetReadableEvent().Close(); + m_deferral_event->GetReadableEvent().Close(m_system.Kernel()); // Write event is owned by ServiceManager } } @@ -125,7 +136,7 @@ void ServerManager::RunServer(std::unique_ptr<ServerManager>&& server_manager) { Result ServerManager::RegisterSession(Kernel::KServerSession* server_session, std::shared_ptr<SessionRequestManager> manager) { // We are taking ownership of the server session, so don't open it. - auto* session = new Session(server_session, std::move(manager)); + auto* session = new Session(m_system.Kernel(), server_session, std::move(manager)); // Begin tracking the server session. { @@ -148,7 +159,7 @@ Result ServerManager::RegisterNamedService(const std::string& service_name, max_sessions, handler_factory)); // We are taking ownership of the server port, so don't open it. - auto* server = new Port(server_port, std::move(handler_factory)); + auto* server = new Port(m_system.Kernel(), server_port, std::move(handler_factory)); // Begin tracking the server port. { @@ -177,15 +188,15 @@ Result ServerManager::ManageNamedPort(const std::string& service_name, u32 max_sessions) { // Create a new port. auto* port = Kernel::KPort::Create(m_system.Kernel()); - port->Initialize(max_sessions, false, 0); + port->Initialize(m_system.Kernel(), max_sessions, false, 0); // Register the port. Kernel::KPort::Register(m_system.Kernel(), port); // Ensure that our reference to the port is closed if we fail to register it. SCOPE_EXIT { - port->GetClientPort().Close(); - port->GetServerPort().Close(); + port->GetClientPort().Close(m_system.Kernel()); + port->GetServerPort().Close(m_system.Kernel()); }; // Register the object name with the kernel. @@ -193,10 +204,10 @@ Result ServerManager::ManageNamedPort(const std::string& service_name, service_name.c_str())); // Open a new reference to the server port. - port->GetServerPort().Open(); + port->GetServerPort().Open(m_system.Kernel()); // Transfer ownership into a new port object. - auto* server = new Port(std::addressof(port->GetServerPort()), std::move(handler_factory)); + auto* server = new Port(m_system.Kernel(), std::addressof(port->GetServerPort()), std::move(handler_factory)); // Begin tracking the port. { @@ -217,7 +228,7 @@ Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) { ASSERT(m_deferral_event != nullptr); // Initialize the event. - m_deferral_event->Initialize(nullptr); + m_deferral_event->Initialize(m_system.Kernel(), nullptr); // Register the event. Kernel::KEvent::Register(m_system.Kernel(), m_deferral_event); @@ -258,7 +269,7 @@ void ServerManager::LinkToDeferredList(MultiWaitHolder* holder) { } // Signal the wakeup event. - m_wakeup_event->Signal(); + m_wakeup_event->Signal(m_system.Kernel()); } void ServerManager::LinkDeferred() { @@ -281,7 +292,7 @@ MultiWaitHolder* ServerManager::WaitSignaled() { auto* selected = m_multi_wait.WaitAny(m_system.Kernel()); if (selected == std::addressof(*m_wakeup_holder)) { // Clear and restart if we were woken up. - m_wakeup_event->Clear(); + m_wakeup_event->Clear(m_system.Kernel()); } else { // Unlink and handle the event. selected->UnlinkFromMultiWait(); @@ -323,7 +334,7 @@ Result ServerManager::LoopProcessImpl() { Result ServerManager::OnPortEvent(Port* server) { // Accept a new server session. auto* server_port = static_cast<Kernel::KServerPort*>(server->GetNativeHandle()); - Kernel::KServerSession* server_session = server_port->AcceptSession(); + Kernel::KServerSession* server_session = server_port->AcceptSession(m_system.Kernel()); ASSERT(server_session != nullptr); // Create the session manager and install the handler. @@ -345,7 +356,7 @@ Result ServerManager::OnSessionEvent(Session* session) { // Try to receive a message. auto* server_session = static_cast<Kernel::KServerSession*>(session->GetNativeHandle()); - res = server_session->ReceiveRequestHLE(&session->GetContext(), session->GetManager()); + res = server_session->ReceiveRequestHLE(m_system.Kernel(), &session->GetContext(), session->GetManager()); // If the session has been closed, we're done. if (res == Kernel::ResultSessionClosed) { @@ -382,7 +393,7 @@ Result ServerManager::CompleteSyncRequest(Session* session) { } // Send the reply. - res = server_session->SendReplyHLE(); + res = server_session->SendReplyHLE(m_system.Kernel()); // If the session has been closed, we're done. if (res == Kernel::ResultSessionClosed || service_res == IPC::ResultSessionClosed) { @@ -401,7 +412,7 @@ Result ServerManager::CompleteSyncRequest(Session* session) { Result ServerManager::OnDeferralEvent() { // Clear event before grabbing the list. - m_deferral_event->Clear(); + m_deferral_event->Clear(m_system.Kernel()); // Get and clear list. const auto deferrals = [&] { diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 5332fa3615..241533d53b 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -33,11 +33,11 @@ ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} { ServiceManager::~ServiceManager() { for (auto& [name, port] : service_ports) { - port->Close(); + port->Close(kernel); } if (deferral_event) { - deferral_event->Close(); + deferral_event->Close(kernel); } } @@ -64,7 +64,7 @@ Result ServiceManager::RegisterService(Kernel::KServerPort** out_server_port, st } auto* port = Kernel::KPort::Create(kernel); - port->Initialize(ServerSessionCountMax, false, 0); + port->Initialize(kernel, ServerSessionCountMax, false, 0); // Register the port. Kernel::KPort::Register(kernel, port); @@ -72,7 +72,7 @@ Result ServiceManager::RegisterService(Kernel::KServerPort** out_server_port, st service_ports.emplace(name, std::addressof(port->GetClientPort())); registered_services.emplace(name, handler); if (deferral_event) { - deferral_event->Signal(); + deferral_event->Signal(kernel); } // Set our output. @@ -195,7 +195,7 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques // Create a new session. Kernel::KClientSession* session{}; - if (const auto result = client_port->CreateSession(&session); result.IsError()) { + if (const auto result = client_port->CreateSession(kernel, &session); result.IsError()) { LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); return result; } diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp index 00c88f6de1..7d7ef38152 100644 --- a/src/core/hle/service/sm/sm_controller.cpp +++ b/src/core/hle/service/sm/sm_controller.cpp @@ -37,8 +37,7 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) { // once this is a proper process // Reserve a new session from the process resource limit. - Kernel::KScopedResourceReservation session_reservation( - Kernel::GetCurrentProcessPointer(kernel), Kernel::LimitableResource::SessionCountMax); + Kernel::KScopedResourceReservation session_reservation(system.Kernel(), Kernel::GetCurrentProcessPointer(kernel), Kernel::LimitableResource::SessionCountMax); ASSERT(session_reservation.Succeeded()); // Create the session. @@ -46,7 +45,7 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) { ASSERT(session != nullptr); // Initialize the session. - session->Initialize(nullptr, 0); + session->Initialize(kernel, nullptr, 0); // Commit the session reservation. session_reservation.Commit(); diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp index 801a135dd7..002c653b8c 100644 --- a/src/core/hle/service/vi/conductor.cpp +++ b/src/core/hle/service/vi/conductor.cpp @@ -70,7 +70,7 @@ void Conductor::UnlinkVsyncEvent(u64 display_id, Event* event) { void Conductor::ProcessVsync() { for (auto& [display_id, manager] : m_vsync_managers) { m_container.ComposeOnDisplay(&m_swap_interval, &m_compose_speed_scale, display_id); - manager.SignalVsync(); + manager.SignalVsync(m_system.Kernel()); } } diff --git a/src/core/hle/service/vi/vsync_manager.cpp b/src/core/hle/service/vi/vsync_manager.cpp index bdc4dfa966..59d0b82e0a 100644 --- a/src/core/hle/service/vi/vsync_manager.cpp +++ b/src/core/hle/service/vi/vsync_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -9,18 +12,10 @@ namespace Service::VI { VsyncManager::VsyncManager() = default; VsyncManager::~VsyncManager() = default; -void VsyncManager::SignalVsync() { +void VsyncManager::SignalVsync(Kernel::KernelCore& kernel) { for (auto* event : m_vsync_events) { - event->Signal(); + event->Signal(kernel); } } -void VsyncManager::LinkVsyncEvent(Event* event) { - m_vsync_events.insert(event); -} - -void VsyncManager::UnlinkVsyncEvent(Event* event) { - m_vsync_events.erase(event); -} - } // namespace Service::VI diff --git a/src/core/hle/service/vi/vsync_manager.h b/src/core/hle/service/vi/vsync_manager.h index 5d45bb5eec..9c04516749 100644 --- a/src/core/hle/service/vi/vsync_manager.h +++ b/src/core/hle/service/vi/vsync_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -5,6 +8,10 @@ #include <set> +namespace Kernel { +class KernelCore; +} + namespace Service { class Event; } @@ -18,9 +25,13 @@ public: explicit VsyncManager(); ~VsyncManager(); - void SignalVsync(); - void LinkVsyncEvent(Event* event); - void UnlinkVsyncEvent(Event* event); + void SignalVsync(Kernel::KernelCore& kernel); + void LinkVsyncEvent(Event* event) { + m_vsync_events.insert(event); + } + void UnlinkVsyncEvent(Event* event) { + m_vsync_events.erase(event); + } private: std::set<Event*> m_vsync_events; diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 74b2ff7018..3286606c5e 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -235,7 +235,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect ? ::Settings::values.rng_seed.GetValue() : Common::Random::Random64(0)) << 12) & 0xfff000; // Setup the process code layout - if (process.LoadFromMetadata(metadata, code_size, fastmem_base, aslr_offset).IsError()) { + if (process.LoadFromMetadata(system.Kernel(), metadata, code_size, fastmem_base, aslr_offset).IsError()) { return {ResultStatus::ErrorUnableToParseKernelMetadata, {}}; } diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index fdfbac0a20..62bcbc9579 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -93,11 +93,11 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process, ? ::Settings::values.rng_seed.GetValue() : Common::Random::Random64(0)) << 12) & 0xfff000; // Setup the process code layout - if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), codeset.memory.size(), 0, aslr_offset).IsError()) { + if (process.LoadFromMetadata(system.Kernel(), FileSys::ProgramMetadata::GetDefault(), codeset.memory.size(), 0, aslr_offset).IsError()) { return {ResultStatus::ErrorNotInitialized, {}}; } const VAddr base_address = GetInteger(process.GetEntryPoint()); - process.LoadModule(std::move(codeset), base_address); + process.LoadModule(system.Kernel(), std::move(codeset), base_address); LOG_DEBUG(Loader, "loaded module {} @ {:#X}", kip->GetName(), base_address); diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 21640b7330..4ba4bde0bb 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -280,7 +280,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, // Setup the process code layout if (process - .LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), image_size, fastmem_base, aslr_offset) + .LoadFromMetadata(system.Kernel(), FileSys::ProgramMetadata::GetDefault(), image_size, fastmem_base, aslr_offset) .IsError()) { return false; } @@ -296,7 +296,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, // Load codeset for current process codeset.memory = std::move(program_image); - process.LoadModule(std::move(codeset), process.GetEntryPoint()); + process.LoadModule(system.Kernel(), std::move(codeset), process.GetEntryPoint()); if (!argv_string.empty()) { constexpr u32 kEntryEndOfList = 0; constexpr u32 kEntryMainThreadHandle = 1; @@ -314,19 +314,14 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, {kEntryArgv, 0, {0, argv_addr}}, {kEntryEndOfList, 0, {0, 0}}, }; - process.GetMemory().WriteBlock(Common::ProcessAddress{config_addr}, entries, - sizeof(entries)); - process.GetMemory().WriteBlock(Common::ProcessAddress{argv_addr}, - argv_string.data(), argv_string.size()); - + process.GetMemory().WriteBlock(Common::ProcessAddress{config_addr}, entries, sizeof(entries)); + process.GetMemory().WriteBlock(Common::ProcessAddress{argv_addr}, argv_string.data(), argv_string.size()); constexpr size_t kMainThreadHandleValueOffset = offsetof(ConfigEntry, value); process.SetArgPointer(Kernel::KProcessAddress{config_addr}); if (exit_process_offset_in_image) { - process.SetArgReturnAddress( - Kernel::KProcessAddress{base + *exit_process_offset_in_image}); + process.SetArgReturnAddress(Kernel::KProcessAddress{base + *exit_process_offset_in_image}); } - process.SetMainThreadHandleAddr( - Kernel::KProcessAddress{config_addr + kMainThreadHandleValueOffset}); + process.SetMainThreadHandleAddr(Kernel::KProcessAddress{config_addr + kMainThreadHandleValueOffset}); } return true; diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 482c853542..a831f44a40 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -217,7 +217,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core:: } // Load codeset for current process - process.LoadModule(std::move(codeset), load_base); + process.LoadModule(system.Kernel(), std::move(codeset), load_base); return load_base + image_size; } diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index dcfd23644f..8e23a54a0d 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -91,17 +91,15 @@ u64 StandardVmCallbacks::HidKeysDown() { } void StandardVmCallbacks::PauseProcess() { - if (system.ApplicationProcess()->IsSuspended()) { - return; + if (!system.ApplicationProcess()->IsSuspended()) { + system.ApplicationProcess()->SetActivity(system.Kernel(), Kernel::Svc::ProcessActivity::Paused); } - system.ApplicationProcess()->SetActivity(Kernel::Svc::ProcessActivity::Paused); } void StandardVmCallbacks::ResumeProcess() { - if (!system.ApplicationProcess()->IsSuspended()) { - return; + if (system.ApplicationProcess()->IsSuspended()) { + system.ApplicationProcess()->SetActivity(system.Kernel(), Kernel::Svc::ProcessActivity::Runnable); } - system.ApplicationProcess()->SetActivity(Kernel::Svc::ProcessActivity::Runnable); } void StandardVmCallbacks::DebugLog(u8 id, u64 value) { |
