using System.Collections.Generic; namespace Ryujinx.HLE.HOS.Kernel { class KSchedulingData { private LinkedList[][] ScheduledThreadsPerPrioPerCore; private LinkedList[][] SuggestedThreadsPerPrioPerCore; private long[] ScheduledPrioritiesPerCore; private long[] SuggestedPrioritiesPerCore; public KSchedulingData() { SuggestedThreadsPerPrioPerCore = new LinkedList[KScheduler.PrioritiesCount][]; ScheduledThreadsPerPrioPerCore = new LinkedList[KScheduler.PrioritiesCount][]; for (int Prio = 0; Prio < KScheduler.PrioritiesCount; Prio++) { SuggestedThreadsPerPrioPerCore[Prio] = new LinkedList[KScheduler.CpuCoresCount]; ScheduledThreadsPerPrioPerCore[Prio] = new LinkedList[KScheduler.CpuCoresCount]; for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++) { SuggestedThreadsPerPrioPerCore[Prio][Core] = new LinkedList(); ScheduledThreadsPerPrioPerCore[Prio][Core] = new LinkedList(); } } ScheduledPrioritiesPerCore = new long[KScheduler.CpuCoresCount]; SuggestedPrioritiesPerCore = new long[KScheduler.CpuCoresCount]; } public IEnumerable SuggestedThreads(int Core) { return Iterate(SuggestedThreadsPerPrioPerCore, SuggestedPrioritiesPerCore, Core); } public IEnumerable ScheduledThreads(int Core) { return Iterate(ScheduledThreadsPerPrioPerCore, ScheduledPrioritiesPerCore, Core); } private IEnumerable Iterate(LinkedList[][] ListPerPrioPerCore, long[] Prios, int Core) { long PrioMask = Prios[Core]; int Prio = CountTrailingZeros(PrioMask); PrioMask &= ~(1L << Prio); while (Prio < KScheduler.PrioritiesCount) { LinkedList List = ListPerPrioPerCore[Prio][Core]; LinkedListNode Node = List.First; while (Node != null) { yield return Node.Value; Node = Node.Next; } Prio = CountTrailingZeros(PrioMask); PrioMask &= ~(1L << Prio); } } private int CountTrailingZeros(long Value) { int Count = 0; while (((Value >> Count) & 0xf) == 0 && Count < 64) { Count += 4; } while (((Value >> Count) & 1) == 0 && Count < 64) { Count++; } return Count; } public void TransferToCore(int Prio, int DstCore, KThread Thread) { bool Schedulable = Thread.DynamicPriority < KScheduler.PrioritiesCount; int SrcCore = Thread.CurrentCore; Thread.CurrentCore = DstCore; if (SrcCore == DstCore || !Schedulable) { return; } if (SrcCore >= 0) { Unschedule(Prio, SrcCore, Thread); } if (DstCore >= 0) { Unsuggest(Prio, DstCore, Thread); Schedule(Prio, DstCore, Thread); } if (SrcCore >= 0) { Suggest(Prio, SrcCore, Thread); } } public void Suggest(int Prio, int Core, KThread Thread) { if (Prio >= KScheduler.PrioritiesCount) { return; } Thread.SiblingsPerCore[Core] = SuggestedQueue(Prio, Core).AddFirst(Thread); SuggestedPrioritiesPerCore[Core] |= 1L << Prio; } public void Unsuggest(int Prio, int Core, KThread Thread) { if (Prio >= KScheduler.PrioritiesCount) { return; } LinkedList Queue = SuggestedQueue(Prio, Core); Queue.Remove(Thread.SiblingsPerCore[Core]); if (Queue.First == null) { SuggestedPrioritiesPerCore[Core] &= ~(1L << Prio); } } public void Schedule(int Prio, int Core, KThread Thread) { if (Prio >= KScheduler.PrioritiesCount) { return; } Thread.SiblingsPerCore[Core] = ScheduledQueue(Prio, Core).AddLast(Thread); ScheduledPrioritiesPerCore[Core] |= 1L << Prio; } public void SchedulePrepend(int Prio, int Core, KThread Thread) { if (Prio >= KScheduler.PrioritiesCount) { return; } Thread.SiblingsPerCore[Core] = ScheduledQueue(Prio, Core).AddFirst(Thread); ScheduledPrioritiesPerCore[Core] |= 1L << Prio; } public void Reschedule(int Prio, int Core, KThread Thread) { LinkedList Queue = ScheduledQueue(Prio, Core); Queue.Remove(Thread.SiblingsPerCore[Core]); Thread.SiblingsPerCore[Core] = Queue.AddLast(Thread); } public void Unschedule(int Prio, int Core, KThread Thread) { if (Prio >= KScheduler.PrioritiesCount) { return; } LinkedList Queue = ScheduledQueue(Prio, Core); Queue.Remove(Thread.SiblingsPerCore[Core]); if (Queue.First == null) { ScheduledPrioritiesPerCore[Core] &= ~(1L << Prio); } } private LinkedList SuggestedQueue(int Prio, int Core) { return SuggestedThreadsPerPrioPerCore[Prio][Core]; } private LinkedList ScheduledQueue(int Prio, int Core) { return ScheduledThreadsPerPrioPerCore[Prio][Core]; } } }