summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
authorGravatar Liam2024-02-14 16:57:20 -0500
committerGravatar Liam2024-02-14 17:03:50 -0500
commitaf42482565daf646d89a0a3cd8001a527ab76621 (patch)
tree3e28818b929f30d13cc190a9203697960bb6db7b /src/core/hle/kernel/kernel.cpp
parentMerge pull request #12996 from german77/settings-ipc (diff)
downloadyuzu-af42482565daf646d89a0a3cd8001a527ab76621.tar.gz
yuzu-af42482565daf646d89a0a3cd8001a527ab76621.tar.xz
yuzu-af42482565daf646d89a0a3cd8001a527ab76621.zip
kernel: add and enable system suspend type
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp57
1 files changed, 33 insertions, 24 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 34b25be66..4f4b02fac 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 {
1204 return *impl->hidbus_shared_mem; 1204 return *impl->hidbus_shared_mem;
1205} 1205}
1206 1206
1207void KernelCore::SuspendApplication(bool suspended) { 1207void KernelCore::SuspendEmulation(bool suspended) {
1208 const bool should_suspend{exception_exited || suspended}; 1208 const bool should_suspend{exception_exited || suspended};
1209 const auto activity = 1209 auto processes = GetProcessList();
1210 should_suspend ? Svc::ProcessActivity::Paused : Svc::ProcessActivity::Runnable;
1211 1210
1212 // Get the application process. 1211 for (auto& process : processes) {
1213 KScopedAutoObject<KProcess> process = ApplicationProcess(); 1212 KScopedLightLock ll{process->GetListLock()};
1214 if (process.IsNull()) { 1213
1215 return; 1214 for (auto& thread : process->GetThreadList()) {
1215 if (should_suspend) {
1216 thread.RequestSuspend(SuspendType::System);
1217 } else {
1218 thread.Resume(SuspendType::System);
1219 }
1220 }
1216 } 1221 }
1217 1222
1218 // Set the new activity. 1223 if (!should_suspend) {
1219 process->SetActivity(activity); 1224 return;
1225 }
1220 1226
1221 // Wait for process execution to stop. 1227 // Wait for process execution to stop.
1222 bool must_wait{should_suspend}; 1228 // KernelCore::SuspendEmulation must be called from locked context,
1223 1229 // or we could race another call, interfering with waiting.
1224 // KernelCore::SuspendApplication must be called from locked context, 1230 const auto TryWait = [&]() {
1225 // or we could race another call to SetActivity, interfering with waiting.
1226 while (must_wait) {
1227 KScopedSchedulerLock sl{*this}; 1231 KScopedSchedulerLock sl{*this};
1228 1232
1229 // Assume that all threads have finished running. 1233 for (auto& process : processes) {
1230 must_wait = false; 1234 for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
1231 1235 if (Scheduler(i).GetSchedulerCurrentThread()->GetOwnerProcess() ==
1232 for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) { 1236 process.GetPointerUnsafe()) {
1233 if (Scheduler(i).GetSchedulerCurrentThread()->GetOwnerProcess() == 1237 // A thread has not finished running yet.
1234 process.GetPointerUnsafe()) { 1238 // Continue waiting.
1235 // A thread has not finished running yet. 1239 return false;
1236 // Continue waiting. 1240 }
1237 must_wait = true;
1238 } 1241 }
1239 } 1242 }
1243
1244 return true;
1245 };
1246
1247 while (!TryWait()) {
1248 // ...
1240 } 1249 }
1241} 1250}
1242 1251
@@ -1260,7 +1269,7 @@ bool KernelCore::IsShuttingDown() const {
1260 1269
1261void KernelCore::ExceptionalExitApplication() { 1270void KernelCore::ExceptionalExitApplication() {
1262 exception_exited = true; 1271 exception_exited = true;
1263 SuspendApplication(true); 1272 SuspendEmulation(true);
1264} 1273}
1265 1274
1266void KernelCore::EnterSVCProfile() { 1275void KernelCore::EnterSVCProfile() {