KSchedulingData.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. using System.Collections.Generic;
  2. namespace Ryujinx.HLE.HOS.Kernel
  3. {
  4. class KSchedulingData
  5. {
  6. private LinkedList<KThread>[][] ScheduledThreadsPerPrioPerCore;
  7. private LinkedList<KThread>[][] SuggestedThreadsPerPrioPerCore;
  8. private long[] ScheduledPrioritiesPerCore;
  9. private long[] SuggestedPrioritiesPerCore;
  10. public KSchedulingData()
  11. {
  12. SuggestedThreadsPerPrioPerCore = new LinkedList<KThread>[KScheduler.PrioritiesCount][];
  13. ScheduledThreadsPerPrioPerCore = new LinkedList<KThread>[KScheduler.PrioritiesCount][];
  14. for (int Prio = 0; Prio < KScheduler.PrioritiesCount; Prio++)
  15. {
  16. SuggestedThreadsPerPrioPerCore[Prio] = new LinkedList<KThread>[KScheduler.CpuCoresCount];
  17. ScheduledThreadsPerPrioPerCore[Prio] = new LinkedList<KThread>[KScheduler.CpuCoresCount];
  18. for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
  19. {
  20. SuggestedThreadsPerPrioPerCore[Prio][Core] = new LinkedList<KThread>();
  21. ScheduledThreadsPerPrioPerCore[Prio][Core] = new LinkedList<KThread>();
  22. }
  23. }
  24. ScheduledPrioritiesPerCore = new long[KScheduler.CpuCoresCount];
  25. SuggestedPrioritiesPerCore = new long[KScheduler.CpuCoresCount];
  26. }
  27. public IEnumerable<KThread> SuggestedThreads(int Core)
  28. {
  29. return Iterate(SuggestedThreadsPerPrioPerCore, SuggestedPrioritiesPerCore, Core);
  30. }
  31. public IEnumerable<KThread> ScheduledThreads(int Core)
  32. {
  33. return Iterate(ScheduledThreadsPerPrioPerCore, ScheduledPrioritiesPerCore, Core);
  34. }
  35. private IEnumerable<KThread> Iterate(LinkedList<KThread>[][] ListPerPrioPerCore, long[] Prios, int Core)
  36. {
  37. long PrioMask = Prios[Core];
  38. int Prio = CountTrailingZeros(PrioMask);
  39. PrioMask &= ~(1L << Prio);
  40. while (Prio < KScheduler.PrioritiesCount)
  41. {
  42. LinkedList<KThread> List = ListPerPrioPerCore[Prio][Core];
  43. LinkedListNode<KThread> Node = List.First;
  44. while (Node != null)
  45. {
  46. yield return Node.Value;
  47. Node = Node.Next;
  48. }
  49. Prio = CountTrailingZeros(PrioMask);
  50. PrioMask &= ~(1L << Prio);
  51. }
  52. }
  53. private int CountTrailingZeros(long Value)
  54. {
  55. int Count = 0;
  56. while (((Value >> Count) & 0xf) == 0 && Count < 64)
  57. {
  58. Count += 4;
  59. }
  60. while (((Value >> Count) & 1) == 0 && Count < 64)
  61. {
  62. Count++;
  63. }
  64. return Count;
  65. }
  66. public void TransferToCore(int Prio, int DstCore, KThread Thread)
  67. {
  68. bool Schedulable = Thread.DynamicPriority < KScheduler.PrioritiesCount;
  69. int SrcCore = Thread.CurrentCore;
  70. Thread.CurrentCore = DstCore;
  71. if (SrcCore == DstCore || !Schedulable)
  72. {
  73. return;
  74. }
  75. if (SrcCore >= 0)
  76. {
  77. Unschedule(Prio, SrcCore, Thread);
  78. }
  79. if (DstCore >= 0)
  80. {
  81. Unsuggest(Prio, DstCore, Thread);
  82. Schedule(Prio, DstCore, Thread);
  83. }
  84. if (SrcCore >= 0)
  85. {
  86. Suggest(Prio, SrcCore, Thread);
  87. }
  88. }
  89. public void Suggest(int Prio, int Core, KThread Thread)
  90. {
  91. if (Prio >= KScheduler.PrioritiesCount)
  92. {
  93. return;
  94. }
  95. Thread.SiblingsPerCore[Core] = SuggestedQueue(Prio, Core).AddFirst(Thread);
  96. SuggestedPrioritiesPerCore[Core] |= 1L << Prio;
  97. }
  98. public void Unsuggest(int Prio, int Core, KThread Thread)
  99. {
  100. if (Prio >= KScheduler.PrioritiesCount)
  101. {
  102. return;
  103. }
  104. LinkedList<KThread> Queue = SuggestedQueue(Prio, Core);
  105. Queue.Remove(Thread.SiblingsPerCore[Core]);
  106. if (Queue.First == null)
  107. {
  108. SuggestedPrioritiesPerCore[Core] &= ~(1L << Prio);
  109. }
  110. }
  111. public void Schedule(int Prio, int Core, KThread Thread)
  112. {
  113. if (Prio >= KScheduler.PrioritiesCount)
  114. {
  115. return;
  116. }
  117. Thread.SiblingsPerCore[Core] = ScheduledQueue(Prio, Core).AddLast(Thread);
  118. ScheduledPrioritiesPerCore[Core] |= 1L << Prio;
  119. }
  120. public void SchedulePrepend(int Prio, int Core, KThread Thread)
  121. {
  122. if (Prio >= KScheduler.PrioritiesCount)
  123. {
  124. return;
  125. }
  126. Thread.SiblingsPerCore[Core] = ScheduledQueue(Prio, Core).AddFirst(Thread);
  127. ScheduledPrioritiesPerCore[Core] |= 1L << Prio;
  128. }
  129. public void Reschedule(int Prio, int Core, KThread Thread)
  130. {
  131. LinkedList<KThread> Queue = ScheduledQueue(Prio, Core);
  132. Queue.Remove(Thread.SiblingsPerCore[Core]);
  133. Thread.SiblingsPerCore[Core] = Queue.AddLast(Thread);
  134. }
  135. public void Unschedule(int Prio, int Core, KThread Thread)
  136. {
  137. if (Prio >= KScheduler.PrioritiesCount)
  138. {
  139. return;
  140. }
  141. LinkedList<KThread> Queue = ScheduledQueue(Prio, Core);
  142. Queue.Remove(Thread.SiblingsPerCore[Core]);
  143. if (Queue.First == null)
  144. {
  145. ScheduledPrioritiesPerCore[Core] &= ~(1L << Prio);
  146. }
  147. }
  148. private LinkedList<KThread> SuggestedQueue(int Prio, int Core)
  149. {
  150. return SuggestedThreadsPerPrioPerCore[Prio][Core];
  151. }
  152. private LinkedList<KThread> ScheduledQueue(int Prio, int Core)
  153. {
  154. return ScheduledThreadsPerPrioPerCore[Prio][Core];
  155. }
  156. }
  157. }