diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-09-18 20:36:43 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-09-18 20:36:43 -0300 |
| commit | b8133c19971c7a2026af803003fafedbdb70488e (patch) | |
| tree | 84f4630e897ccd3f77b86051241a22a6cf45193d /Ryujinx.HLE/HOS/Kernel/KSynchronization.cs | |
| parent | 33e2810ef36fe0cf613aecd4c609f425aed02539 (diff) | |
Thread scheduler rewrite (#393)
* Started to rewrite the thread scheduler
* Add a single core-like scheduling mode, enabled by default
* Clear exclusive monitor on context switch
* Add SetThreadActivity, misc fixes
* Implement WaitForAddress and SignalToAddress svcs, misc fixes
* Misc fixes (on SetActivity and Arbiter), other tweaks
* Rebased
* Add missing null check
* Rename multicore key on config, fix UpdatePriorityInheritance
* Make scheduling data MLQs private
* nit: Ordering
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/KSynchronization.cs')
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KSynchronization.cs | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/KSynchronization.cs b/Ryujinx.HLE/HOS/Kernel/KSynchronization.cs new file mode 100644 index 00000000..57a6296c --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/KSynchronization.cs @@ -0,0 +1,135 @@ +using System.Collections.Generic; + +using static Ryujinx.HLE.HOS.ErrorCode; + +namespace Ryujinx.HLE.HOS.Kernel +{ + class KSynchronization + { + private Horizon System; + + public KSynchronization(Horizon System) + { + this.System = System; + } + + public long WaitFor(KSynchronizationObject[] SyncObjs, long Timeout, ref int HndIndex) + { + long Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout); + + System.CriticalSectionLock.Lock(); + + //Check if objects are already signaled before waiting. + for (int Index = 0; Index < SyncObjs.Length; Index++) + { + if (!SyncObjs[Index].IsSignaled()) + { + continue; + } + + HndIndex = Index; + + System.CriticalSectionLock.Unlock(); + + return 0; + } + + if (Timeout == 0) + { + System.CriticalSectionLock.Unlock(); + + return Result; + } + + KThread CurrentThread = System.Scheduler.GetCurrentThread(); + + if (CurrentThread.ShallBeTerminated || + CurrentThread.SchedFlags == ThreadSchedState.TerminationPending) + { + Result = MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating); + } + else if (CurrentThread.SyncCancelled) + { + CurrentThread.SyncCancelled = false; + + Result = MakeError(ErrorModule.Kernel, KernelErr.Cancelled); + } + else + { + LinkedListNode<KThread>[] SyncNodes = new LinkedListNode<KThread>[SyncObjs.Length]; + + for (int Index = 0; Index < SyncObjs.Length; Index++) + { + SyncNodes[Index] = SyncObjs[Index].AddWaitingThread(CurrentThread); + } + + CurrentThread.WaitingSync = true; + CurrentThread.SignaledObj = null; + CurrentThread.ObjSyncResult = (int)Result; + + CurrentThread.Reschedule(ThreadSchedState.Paused); + + if (Timeout > 0) + { + System.TimeManager.ScheduleFutureInvocation(CurrentThread, Timeout); + } + + System.CriticalSectionLock.Unlock(); + + CurrentThread.WaitingSync = false; + + if (Timeout > 0) + { + System.TimeManager.UnscheduleFutureInvocation(CurrentThread); + } + + System.CriticalSectionLock.Lock(); + + Result = (uint)CurrentThread.ObjSyncResult; + + HndIndex = -1; + + for (int Index = 0; Index < SyncObjs.Length; Index++) + { + SyncObjs[Index].RemoveWaitingThread(SyncNodes[Index]); + + if (SyncObjs[Index] == CurrentThread.SignaledObj) + { + HndIndex = Index; + } + } + } + + System.CriticalSectionLock.Unlock(); + + return Result; + } + + public void SignalObject(KSynchronizationObject SyncObj) + { + System.CriticalSectionLock.Lock(); + + if (SyncObj.IsSignaled()) + { + LinkedListNode<KThread> Node = SyncObj.WaitingThreads.First; + + while (Node != null) + { + KThread Thread = Node.Value; + + if ((Thread.SchedFlags & ThreadSchedState.LowNibbleMask) == ThreadSchedState.Paused) + { + Thread.SignaledObj = SyncObj; + Thread.ObjSyncResult = 0; + + Thread.Reschedule(ThreadSchedState.Running); + } + + Node = Node.Next; + } + } + + System.CriticalSectionLock.Unlock(); + } + } +}
\ No newline at end of file |
