diff options
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs')
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs b/Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs new file mode 100644 index 00000000..a21531de --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs @@ -0,0 +1,93 @@ +using ChocolArm64; +using System.Threading; + +namespace Ryujinx.HLE.HOS.Kernel +{ + class KRecursiveLock + { + private Horizon System; + + public object LockObj { get; private set; } + + private int RecursionCount; + + public KRecursiveLock(Horizon System) + { + this.System = System; + + LockObj = new object(); + } + + public void Lock() + { + Monitor.Enter(LockObj); + + RecursionCount++; + } + + public void Unlock() + { + if (RecursionCount == 0) + { + return; + } + + bool DoContextSwitch = false; + + if (--RecursionCount == 0) + { + if (System.Scheduler.ThreadReselectionRequested) + { + System.Scheduler.SelectThreads(); + } + + Monitor.Exit(LockObj); + + if (System.Scheduler.MultiCoreScheduling) + { + lock (System.Scheduler.CoreContexts) + { + for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++) + { + KCoreContext CoreContext = System.Scheduler.CoreContexts[Core]; + + if (CoreContext.ContextSwitchNeeded) + { + AThread CurrentHleThread = CoreContext.CurrentThread?.Context; + + if (CurrentHleThread == null) + { + //Nothing is running, we can perform the context switch immediately. + CoreContext.ContextSwitch(); + } + else if (CurrentHleThread.IsCurrentThread()) + { + //Thread running on the current core, context switch will block. + DoContextSwitch = true; + } + else + { + //Thread running on another core, request a interrupt. + CurrentHleThread.RequestInterrupt(); + } + } + } + } + } + else + { + DoContextSwitch = true; + } + } + else + { + Monitor.Exit(LockObj); + } + + if (DoContextSwitch) + { + System.Scheduler.ContextSwitch(); + } + } + } +}
\ No newline at end of file |
