aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xREADME.md2
-rwxr-xr-xsrc/core/core.cpp10
-rwxr-xr-xsrc/core/hle/kernel/k_thread.h4
-rwxr-xr-xsrc/core/hle/kernel/kernel.cpp57
-rwxr-xr-xsrc/core/hle/kernel/kernel.h4
5 files changed, 44 insertions, 33 deletions
diff --git a/README.md b/README.md
index a895006e4..168a9a6e1 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
1yuzu emulator early access 1yuzu emulator early access
2============= 2=============
3 3
4This is the source code for early-access 4142. 4This is the source code for early-access 4143.
5 5
6## Legal Notice 6## Legal Notice
7 7
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 104c004ef..46a7941de 100755
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -242,7 +242,7 @@ struct System::Impl {
242 void Run() { 242 void Run() {
243 std::unique_lock<std::mutex> lk(suspend_guard); 243 std::unique_lock<std::mutex> lk(suspend_guard);
244 244
245 kernel.SuspendApplication(false); 245 kernel.SuspendEmulation(false);
246 core_timing.SyncPause(false); 246 core_timing.SyncPause(false);
247 is_paused.store(false, std::memory_order_relaxed); 247 is_paused.store(false, std::memory_order_relaxed);
248 } 248 }
@@ -251,7 +251,7 @@ struct System::Impl {
251 std::unique_lock<std::mutex> lk(suspend_guard); 251 std::unique_lock<std::mutex> lk(suspend_guard);
252 252
253 core_timing.SyncPause(true); 253 core_timing.SyncPause(true);
254 kernel.SuspendApplication(true); 254 kernel.SuspendEmulation(true);
255 is_paused.store(true, std::memory_order_relaxed); 255 is_paused.store(true, std::memory_order_relaxed);
256 } 256 }
257 257
@@ -261,7 +261,7 @@ struct System::Impl {
261 261
262 std::unique_lock<std::mutex> StallApplication() { 262 std::unique_lock<std::mutex> StallApplication() {
263 std::unique_lock<std::mutex> lk(suspend_guard); 263 std::unique_lock<std::mutex> lk(suspend_guard);
264 kernel.SuspendApplication(true); 264 kernel.SuspendEmulation(true);
265 core_timing.SyncPause(true); 265 core_timing.SyncPause(true);
266 return lk; 266 return lk;
267 } 267 }
@@ -269,7 +269,7 @@ struct System::Impl {
269 void UnstallApplication() { 269 void UnstallApplication() {
270 if (!IsPaused()) { 270 if (!IsPaused()) {
271 core_timing.SyncPause(false); 271 core_timing.SyncPause(false);
272 kernel.SuspendApplication(false); 272 kernel.SuspendEmulation(false);
273 } 273 }
274 } 274 }
275 275
@@ -459,7 +459,7 @@ struct System::Impl {
459 } 459 }
460 460
461 Network::CancelPendingSocketOperations(); 461 Network::CancelPendingSocketOperations();
462 kernel.SuspendApplication(true); 462 kernel.SuspendEmulation(true);
463 if (services) { 463 if (services) {
464 services->KillNVNFlinger(); 464 services->KillNVNFlinger();
465 } 465 }
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index c2a9e9831..7e069d91a 100755
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -66,6 +66,7 @@ enum class SuspendType : u32 {
66 Debug = 2, 66 Debug = 2,
67 Backtrace = 3, 67 Backtrace = 3,
68 Init = 4, 68 Init = 4,
69 System = 5,
69 70
70 Count, 71 Count,
71}; 72};
@@ -84,8 +85,9 @@ enum class ThreadState : u16 {
84 DebugSuspended = (1 << (2 + SuspendShift)), 85 DebugSuspended = (1 << (2 + SuspendShift)),
85 BacktraceSuspended = (1 << (3 + SuspendShift)), 86 BacktraceSuspended = (1 << (3 + SuspendShift)),
86 InitSuspended = (1 << (4 + SuspendShift)), 87 InitSuspended = (1 << (4 + SuspendShift)),
88 SystemSuspended = (1 << (5 + SuspendShift)),
87 89
88 SuspendFlagMask = ((1 << 5) - 1) << SuspendShift, 90 SuspendFlagMask = ((1 << 6) - 1) << SuspendShift,
89}; 91};
90DECLARE_ENUM_FLAG_OPERATORS(ThreadState); 92DECLARE_ENUM_FLAG_OPERATORS(ThreadState);
91 93
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index ec71fc5c0..c05722c87 100755
--- 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() {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index b3d76c41b..ce61c057e 100755
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -258,8 +258,8 @@ public:
258 /// Gets the shared memory object for HIDBus services. 258 /// Gets the shared memory object for HIDBus services.
259 const Kernel::KSharedMemory& GetHidBusSharedMem() const; 259 const Kernel::KSharedMemory& GetHidBusSharedMem() const;
260 260
261 /// Suspend/unsuspend application process. 261 /// Suspend/unsuspend emulated processes.
262 void SuspendApplication(bool suspend); 262 void SuspendEmulation(bool suspend);
263 263
264 /// Exceptional exit application process. 264 /// Exceptional exit application process.
265 void ExceptionalExitApplication(); 265 void ExceptionalExitApplication();