KPriorityQueue.cs 5.7 KB

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