diff options
author | mpnico <mpnico@gmail.com> | 2021-09-11 22:08:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-11 22:08:25 +0200 |
commit | 117e32a6fffc30cdb895aa98483af7df353a8dd1 (patch) | |
tree | 3a6ad3b396bbf641663dada2419709837f7c8268 /Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | |
parent | b0e410a828fd37bf0d9021fc2f6b630e3944a861 (diff) |
Implement a "Pause Emulation" option & hotkey (#2428)
* Add a "Pause Emulation" option and hotkey
Closes Ryujinx#1604
* Refactoring how pause is handled
* Applied suggested changes from review
* Applied suggested fixes
* Pass correct suspend type to threads for suspend/resume
* Fix NRE after stoping emulation
* Removing SimulateWakeUpMessage call after resuming emulation
* Skip suspending non game process
* Pause the tickCounter in the ExecutionContext
* Refactoring tickCounter pause/resume as suggested
* Fix Config migration to add pause hotkey
* Fixed pausing only application threads
* Fix exiting emulator while paused
* Avoid pause/resume while already paused/resumed
* Cleanup unused code
* Avoid restarting audio if stopping emulation while in pause.
* Added suggested changes
* Fix ConfigurationState
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs')
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index 7224cca1..396a79ba 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -471,6 +471,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KernelContext.CriticalSection.Leave(); } + public void Suspend(ThreadSchedState type) + { + _forcePauseFlags |= type; + + CombineForcePauseFlags(); + } + + public void Resume(ThreadSchedState type) + { + ThreadSchedState oldForcePauseFlags = _forcePauseFlags; + + _forcePauseFlags &= ~type; + + if ((oldForcePauseFlags & ~type) == ThreadSchedState.None) + { + ThreadSchedState oldSchedFlags = SchedFlags; + + SchedFlags &= ThreadSchedState.LowMask; + + AdjustScheduling(oldSchedFlags); + } + } + public KernelResult SetActivity(bool pause) { KernelResult result = KernelResult.Success; @@ -495,9 +518,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading // Pause, the force pause flag should be clear (thread is NOT paused). if ((_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) == 0) { - _forcePauseFlags |= ThreadSchedState.ThreadPauseFlag; - - CombineForcePauseFlags(); + Suspend(ThreadSchedState.ThreadPauseFlag); } else { @@ -509,18 +530,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading // Unpause, the force pause flag should be set (thread is paused). if ((_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) != 0) { - ThreadSchedState oldForcePauseFlags = _forcePauseFlags; - - _forcePauseFlags &= ~ThreadSchedState.ThreadPauseFlag; - - if ((oldForcePauseFlags & ~ThreadSchedState.ThreadPauseFlag) == ThreadSchedState.None) - { - ThreadSchedState oldSchedFlags = SchedFlags; - - SchedFlags &= ThreadSchedState.LowMask; - - AdjustScheduling(oldSchedFlags); - } + Resume(ThreadSchedState.ThreadPauseFlag); } else { @@ -832,19 +842,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (!IsSchedulable) { - // Ensure our thread is running and we have an event. - StartHostThread(); - - // If the thread is not schedulable, we want to just run or pause - // it directly as we don't care about priority or the core it is - // running on in this case. - if (SchedFlags == ThreadSchedState.Running) - { - _schedulerWaitEvent.Set(); - } - else + if (!_forcedUnschedulable) { - _schedulerWaitEvent.Reset(); + // Ensure our thread is running and we have an event. + StartHostThread(); + + // If the thread is not schedulable, we want to just run or pause + // it directly as we don't care about priority or the core it is + // running on in this case. + if (SchedFlags == ThreadSchedState.Running) + { + _schedulerWaitEvent.Set(); + } + else + { + _schedulerWaitEvent.Reset(); + } } return; |