KSchedulingData.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. using System.Collections.Generic;
  2. namespace Ryujinx.HLE.HOS.Kernel.Threading
  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. }