aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs')
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs52
1 files changed, 30 insertions, 22 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
index 0c51b7b9..b9de7d9c 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
@@ -1,8 +1,6 @@
using Ryujinx.Common;
using Ryujinx.HLE.HOS.Kernel.Process;
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Numerics;
using System.Threading;
@@ -17,6 +15,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private static readonly int[] PreemptionPriorities = new int[] { 59, 59, 59, 63 };
+ private static readonly int[] _srcCoresHighestPrioThreads = new int[CpuCoresCount];
+
private readonly KernelContext _context;
private readonly int _coreId;
@@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
for (int core = 0; core < CpuCoresCount; core++)
{
- KThread thread = context.PriorityQueue.ScheduledThreads(core).FirstOrDefault();
+ KThread thread = context.PriorityQueue.ScheduledThreadsFirstOrDefault(core);
if (thread != null &&
thread.Owner != null &&
@@ -115,12 +115,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
// If the core is not idle (there's already a thread running on it),
// then we don't need to attempt load balancing.
- if (context.PriorityQueue.ScheduledThreads(core).Any())
+ if (context.PriorityQueue.HasScheduledThreads(core))
{
continue;
}
- int[] srcCoresHighestPrioThreads = new int[CpuCoresCount];
+ Array.Fill(_srcCoresHighestPrioThreads, 0);
int srcCoresHighestPrioThreadsCount = 0;
@@ -136,7 +136,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
break;
}
- srcCoresHighestPrioThreads[srcCoresHighestPrioThreadsCount++] = suggested.ActiveCore;
+ _srcCoresHighestPrioThreads[srcCoresHighestPrioThreadsCount++] = suggested.ActiveCore;
}
// Not yet selected candidate found.
@@ -158,9 +158,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
// (the first one that doesn't make the source core idle if moved).
for (int index = 0; index < srcCoresHighestPrioThreadsCount; index++)
{
- int srcCore = srcCoresHighestPrioThreads[index];
+ int srcCore = _srcCoresHighestPrioThreads[index];
- KThread src = context.PriorityQueue.ScheduledThreads(srcCore).ElementAtOrDefault(1);
+ KThread src = context.PriorityQueue.ScheduledThreadsElementAtOrDefault(srcCore, 1);
if (src != null)
{
@@ -422,9 +422,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private static void RotateScheduledQueue(KernelContext context, int core, int prio)
{
- IEnumerable<KThread> scheduledThreads = context.PriorityQueue.ScheduledThreads(core);
-
- KThread selectedThread = scheduledThreads.FirstOrDefault(x => x.DynamicPriority == prio);
+ KThread selectedThread = context.PriorityQueue.ScheduledThreadsWithDynamicPriorityFirstOrDefault(core, prio);
KThread nextThread = null;
// Yield priority queue.
@@ -433,14 +431,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
nextThread = context.PriorityQueue.Reschedule(prio, core, selectedThread);
}
- IEnumerable<KThread> SuitableCandidates()
+ static KThread FirstSuitableCandidateOrDefault(KernelContext context, int core, KThread selectedThread, KThread nextThread, Predicate< KThread> predicate)
{
foreach (KThread suggested in context.PriorityQueue.SuggestedThreads(core))
{
int suggestedCore = suggested.ActiveCore;
if (suggestedCore >= 0)
{
- KThread selectedSuggestedCore = context.PriorityQueue.ScheduledThreads(suggestedCore).FirstOrDefault();
+ KThread selectedSuggestedCore = context.PriorityQueue.ScheduledThreadsFirstOrDefault(suggestedCore);
if (selectedSuggestedCore == suggested || (selectedSuggestedCore != null && selectedSuggestedCore.DynamicPriority < 2))
{
@@ -453,14 +451,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
nextThread == null ||
nextThread.LastScheduledTime >= suggested.LastScheduledTime)
{
- yield return suggested;
+ if (predicate(suggested))
+ {
+ return suggested;
+ }
}
}
+
+ return null;
}
// Select candidate threads that could run on this core.
// Only take into account threads that are not yet selected.
- KThread dst = SuitableCandidates().FirstOrDefault(x => x.DynamicPriority == prio);
+ KThread dst = FirstSuitableCandidateOrDefault(context, core, selectedThread, nextThread, x => x.DynamicPriority == prio);
if (dst != null)
{
@@ -469,11 +472,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
// If the priority of the currently selected thread is lower or same as the preemption priority,
// then try to migrate a thread with lower priority.
- KThread bestCandidate = context.PriorityQueue.ScheduledThreads(core).FirstOrDefault();
+ KThread bestCandidate = context.PriorityQueue.ScheduledThreadsFirstOrDefault(core);
if (bestCandidate != null && bestCandidate.DynamicPriority >= prio)
{
- dst = SuitableCandidates().FirstOrDefault(x => x.DynamicPriority < bestCandidate.DynamicPriority);
+ dst = FirstSuitableCandidateOrDefault(context, core, selectedThread, nextThread, x => x.DynamicPriority < bestCandidate.DynamicPriority);
if (dst != null)
{
@@ -534,7 +537,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
// Move current thread to the end of the queue.
KThread nextThread = context.PriorityQueue.Reschedule(prio, core, currentThread);
- IEnumerable<KThread> SuitableCandidates()
+ static KThread FirstSuitableCandidateOrDefault(KernelContext context, int core, KThread nextThread, int lessThanOrEqualPriority)
{
foreach (KThread suggested in context.PriorityQueue.SuggestedThreads(core))
{
@@ -554,12 +557,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
if (suggested.LastScheduledTime <= nextThread.LastScheduledTime ||
suggested.DynamicPriority < nextThread.DynamicPriority)
{
- yield return suggested;
+ if (suggested.DynamicPriority <= lessThanOrEqualPriority)
+ {
+ return suggested;
+ }
}
}
+
+ return null;
}
- KThread dst = SuitableCandidates().FirstOrDefault(x => x.DynamicPriority <= prio);
+ KThread dst = FirstSuitableCandidateOrDefault(context, core, nextThread, prio);
if (dst != null)
{
@@ -596,7 +604,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
context.PriorityQueue.TransferToCore(currentThread.DynamicPriority, -1, currentThread);
- if (!context.PriorityQueue.ScheduledThreads(core).Any())
+ if (!context.PriorityQueue.HasScheduledThreads(core))
{
KThread selectedThread = null;
@@ -609,7 +617,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
continue;
}
- KThread firstCandidate = context.PriorityQueue.ScheduledThreads(suggestedCore).FirstOrDefault();
+ KThread firstCandidate = context.PriorityQueue.ScheduledThreadsFirstOrDefault(suggestedCore);
if (firstCandidate == suggested)
{