From af42482565daf646d89a0a3cd8001a527ab76621 Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 14 Feb 2024 16:57:20 -0500 Subject: [PATCH] kernel: add and enable system suspend type --- src/core/core.cpp | 10 +++--- src/core/hle/kernel/k_thread.h | 4 ++- src/core/hle/kernel/kernel.cpp | 57 ++++++++++++++++++++-------------- src/core/hle/kernel/kernel.h | 4 +-- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 435ef67934..bd5f11d535 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -242,7 +242,7 @@ struct System::Impl { void Run() { std::unique_lock lk(suspend_guard); - kernel.SuspendApplication(false); + kernel.SuspendEmulation(false); core_timing.SyncPause(false); is_paused.store(false, std::memory_order_relaxed); } @@ -251,7 +251,7 @@ struct System::Impl { std::unique_lock lk(suspend_guard); core_timing.SyncPause(true); - kernel.SuspendApplication(true); + kernel.SuspendEmulation(true); is_paused.store(true, std::memory_order_relaxed); } @@ -261,7 +261,7 @@ struct System::Impl { std::unique_lock StallApplication() { std::unique_lock lk(suspend_guard); - kernel.SuspendApplication(true); + kernel.SuspendEmulation(true); core_timing.SyncPause(true); return lk; } @@ -269,7 +269,7 @@ struct System::Impl { void UnstallApplication() { if (!IsPaused()) { core_timing.SyncPause(false); - kernel.SuspendApplication(false); + kernel.SuspendEmulation(false); } } @@ -459,7 +459,7 @@ struct System::Impl { } Network::CancelPendingSocketOperations(); - kernel.SuspendApplication(true); + kernel.SuspendEmulation(true); if (services) { services->KillNVNFlinger(); } diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index f13e232b24..e928cfebc9 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -66,6 +66,7 @@ enum class SuspendType : u32 { Debug = 2, Backtrace = 3, Init = 4, + System = 5, Count, }; @@ -84,8 +85,9 @@ enum class ThreadState : u16 { DebugSuspended = (1 << (2 + SuspendShift)), BacktraceSuspended = (1 << (3 + SuspendShift)), InitSuspended = (1 << (4 + SuspendShift)), + SystemSuspended = (1 << (5 + SuspendShift)), - SuspendFlagMask = ((1 << 5) - 1) << SuspendShift, + SuspendFlagMask = ((1 << 6) - 1) << SuspendShift, }; DECLARE_ENUM_FLAG_OPERATORS(ThreadState); diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 34b25be665..4f4b02fac7 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -1204,39 +1204,48 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const { return *impl->hidbus_shared_mem; } -void KernelCore::SuspendApplication(bool suspended) { +void KernelCore::SuspendEmulation(bool suspended) { const bool should_suspend{exception_exited || suspended}; - const auto activity = - should_suspend ? Svc::ProcessActivity::Paused : Svc::ProcessActivity::Runnable; + auto processes = GetProcessList(); - // Get the application process. - KScopedAutoObject process = ApplicationProcess(); - if (process.IsNull()) { + for (auto& process : processes) { + KScopedLightLock ll{process->GetListLock()}; + + for (auto& thread : process->GetThreadList()) { + if (should_suspend) { + thread.RequestSuspend(SuspendType::System); + } else { + thread.Resume(SuspendType::System); + } + } + } + + if (!should_suspend) { return; } - // Set the new activity. - process->SetActivity(activity); - // Wait for process execution to stop. - bool must_wait{should_suspend}; - - // KernelCore::SuspendApplication must be called from locked context, - // or we could race another call to SetActivity, interfering with waiting. - while (must_wait) { + // KernelCore::SuspendEmulation must be called from locked context, + // or we could race another call, interfering with waiting. + const auto TryWait = [&]() { KScopedSchedulerLock sl{*this}; - // Assume that all threads have finished running. - must_wait = false; - - for (auto i = 0; i < static_cast(Core::Hardware::NUM_CPU_CORES); ++i) { - if (Scheduler(i).GetSchedulerCurrentThread()->GetOwnerProcess() == - process.GetPointerUnsafe()) { - // A thread has not finished running yet. - // Continue waiting. - must_wait = true; + for (auto& process : processes) { + for (auto i = 0; i < static_cast(Core::Hardware::NUM_CPU_CORES); ++i) { + if (Scheduler(i).GetSchedulerCurrentThread()->GetOwnerProcess() == + process.GetPointerUnsafe()) { + // A thread has not finished running yet. + // Continue waiting. + return false; + } } } + + return true; + }; + + while (!TryWait()) { + // ... } } @@ -1260,7 +1269,7 @@ bool KernelCore::IsShuttingDown() const { void KernelCore::ExceptionalExitApplication() { exception_exited = true; - SuspendApplication(true); + SuspendEmulation(true); } void KernelCore::EnterSVCProfile() { diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 8ea5bed1c6..57182c0c8d 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -258,8 +258,8 @@ public: /// Gets the shared memory object for HIDBus services. const Kernel::KSharedMemory& GetHidBusSharedMem() const; - /// Suspend/unsuspend application process. - void SuspendApplication(bool suspend); + /// Suspend/unsuspend emulated processes. + void SuspendEmulation(bool suspend); /// Exceptional exit application process. void ExceptionalExitApplication();