diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs index 8b339eabc..97f28bb70 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs @@ -15,7 +15,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private readonly Dictionary> _condVarThreads; private readonly Dictionary> _arbiterThreads; - private readonly ByDynamicPriority _byDynamicPriority; public KAddressArbiter(KernelContext context) { @@ -23,7 +22,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading _condVarThreads = []; _arbiterThreads = []; - _byDynamicPriority = new ByDynamicPriority(); } public Result ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle) @@ -142,14 +140,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (_condVarThreads.TryGetValue(condVarAddress, out List threads)) { - int i = 0; + int i = FindDynamicPriorityFifoInsertionIndex(threads, currentThread); + - if (threads.Count > 0) - { - i = threads.BinarySearch(currentThread, _byDynamicPriority); - if (i < 0) i = ~i; - } - threads.Insert(i, currentThread); } else @@ -332,14 +325,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (_arbiterThreads.TryGetValue(address, out List threads)) { - int i = 0; + int i = FindDynamicPriorityFifoInsertionIndex(threads, currentThread); + - if (threads.Count > 0) - { - i = threads.BinarySearch(currentThread, _byDynamicPriority); - if (i < 0) i = ~i; - } - threads.Insert(i, currentThread); } else @@ -424,14 +412,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (_arbiterThreads.TryGetValue(address, out List threads)) { - int i = 0; + int i = FindDynamicPriorityFifoInsertionIndex(threads, currentThread); + - if (threads.Count > 0) - { - i = threads.BinarySearch(currentThread, _byDynamicPriority); - if (i < 0) i = ~i; - } - threads.Insert(i, currentThread); } else @@ -627,12 +610,28 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading return validCount; } - private class ByDynamicPriority : IComparer + private static int FindDynamicPriorityFifoInsertionIndex(List threads, KThread currentThread) { - public int Compare(KThread x, KThread y) + int low = 0; + int high = threads.Count; + + // Lower numeric values represent higher priorities. Use upper-bound insertion + // to preserve FIFO order among waiters with the same dynamic priority. + while (low < high) { - return x!.DynamicPriority.CompareTo(y!.DynamicPriority); + int middle = low + ((high - low) >> 1); + + if (threads[middle].DynamicPriority <= currentThread.DynamicPriority) + { + low = middle + 1; + } + else + { + high = middle; + } } + + return low; } } }