aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Core
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-05-13 00:22:42 -0300
committergdkchan <gab.dark.100@gmail.com>2018-05-13 00:22:42 -0300
commit4546d1b9be1052bbf82858d97795b33355bf64da (patch)
treea88286d145d8da522a81b3a265c538e7795b7f8d /Ryujinx.Core
parent3603497a137d14f2d65c5450133f2486a9f9620c (diff)
Initial work to support changing thread core on the scheduler, also some cond var priority fixes
Diffstat (limited to 'Ryujinx.Core')
-rw-r--r--Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs226
-rw-r--r--Ryujinx.Core/OsHle/Handles/KThread.cs151
-rw-r--r--Ryujinx.Core/OsHle/Handles/SchedulerThread.cs48
-rw-r--r--Ryujinx.Core/OsHle/Handles/ThreadQueue.cs158
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcHandler.cs4
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcSystem.cs4
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcThread.cs4
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs26
-rw-r--r--Ryujinx.Core/OsHle/Process.cs8
9 files changed, 436 insertions, 193 deletions
diff --git a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
index 1c35b23c..a154b1c6 100644
--- a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
+++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
@@ -1,130 +1,16 @@
using Ryujinx.Core.Logging;
using System;
using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Threading;
namespace Ryujinx.Core.OsHle.Handles
{
class KProcessScheduler : IDisposable
{
- private const int LowestPriority = 0x40;
-
- private class SchedulerThread : IDisposable
- {
- public KThread Thread { get; private set; }
-
- public bool IsActive { get; set; }
-
- public AutoResetEvent WaitSync { get; private set; }
- public ManualResetEvent WaitActivity { get; private set; }
- public AutoResetEvent WaitSched { get; private set; }
-
- public SchedulerThread(KThread Thread)
- {
- this.Thread = Thread;
-
- IsActive = true;
-
- WaitSync = new AutoResetEvent(false);
-
- WaitActivity = new ManualResetEvent(true);
-
- WaitSched = new AutoResetEvent(false);
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool Disposing)
- {
- if (Disposing)
- {
- WaitSync.Dispose();
-
- WaitActivity.Dispose();
-
- WaitSched.Dispose();
- }
- }
- }
-
- private class ThreadQueue
- {
- private List<SchedulerThread> Threads;
-
- public ThreadQueue()
- {
- Threads = new List<SchedulerThread>();
- }
-
- public void Push(SchedulerThread Thread)
- {
- lock (Threads)
- {
- Threads.Add(Thread);
- }
- }
-
- public SchedulerThread Pop(int MinPriority = LowestPriority)
- {
- lock (Threads)
- {
- SchedulerThread SchedThread;
-
- int HighestPriority = MinPriority;
-
- int HighestPrioIndex = -1;
-
- for (int Index = 0; Index < Threads.Count; Index++)
- {
- SchedThread = Threads[Index];
-
- if (HighestPriority > SchedThread.Thread.ActualPriority)
- {
- HighestPriority = SchedThread.Thread.ActualPriority;
-
- HighestPrioIndex = Index;
- }
- }
-
- if (HighestPrioIndex == -1)
- {
- return null;
- }
-
- SchedThread = Threads[HighestPrioIndex];
-
- Threads.RemoveAt(HighestPrioIndex);
-
- return SchedThread;
- }
- }
-
- public bool HasThread(SchedulerThread SchedThread)
- {
- lock (Threads)
- {
- return Threads.Contains(SchedThread);
- }
- }
-
- public bool Remove(SchedulerThread SchedThread)
- {
- lock (Threads)
- {
- return Threads.Remove(SchedThread);
- }
- }
- }
-
private ConcurrentDictionary<KThread, SchedulerThread> AllThreads;
- private ThreadQueue[] WaitingToRun;
+ private ThreadQueue WaitingToRun;
- private HashSet<int> ActiveProcessors;
+ private int ActiveCores;
private object SchedLock;
@@ -136,14 +22,7 @@ namespace Ryujinx.Core.OsHle.Handles
AllThreads = new ConcurrentDictionary<KThread, SchedulerThread>();
- WaitingToRun = new ThreadQueue[4];
-
- for (int Index = 0; Index < 4; Index++)
- {
- WaitingToRun[Index] = new ThreadQueue();
- }
-
- ActiveProcessors = new HashSet<int>();
+ WaitingToRun = new ThreadQueue();
SchedLock = new object();
}
@@ -159,7 +38,7 @@ namespace Ryujinx.Core.OsHle.Handles
return;
}
- if (ActiveProcessors.Add(Thread.ProcessorId))
+ if (AddActiveCore(Thread))
{
Thread.Thread.Execute();
@@ -167,7 +46,7 @@ namespace Ryujinx.Core.OsHle.Handles
}
else
{
- WaitingToRun[Thread.ProcessorId].Push(SchedThread);
+ WaitingToRun.Push(SchedThread);
PrintDbgThreadInfo(Thread, "waiting to run.");
}
@@ -182,18 +61,18 @@ namespace Ryujinx.Core.OsHle.Handles
{
if (AllThreads.TryRemove(Thread, out SchedulerThread SchedThread))
{
- WaitingToRun[Thread.ProcessorId].Remove(SchedThread);
+ WaitingToRun.Remove(SchedThread);
SchedThread.Dispose();
}
- SchedulerThread NewThread = WaitingToRun[Thread.ProcessorId].Pop();
+ SchedulerThread NewThread = WaitingToRun.Pop(Thread.ActualCore);
if (NewThread == null)
{
- Log.PrintDebug(LogClass.KernelScheduler, $"Nothing to run on core {Thread.ProcessorId}!");
+ Log.PrintDebug(LogClass.KernelScheduler, $"Nothing to run on core {Thread.ActualCore}!");
- ActiveProcessors.Remove(Thread.ProcessorId);
+ RemoveActiveCore(Thread.ActualCore);
return;
}
@@ -228,7 +107,7 @@ namespace Ryujinx.Core.OsHle.Handles
throw new InvalidOperationException();
}
- Suspend(Thread.ProcessorId);
+ Suspend(Thread);
SchedThread.WaitSync.WaitOne();
@@ -242,7 +121,7 @@ namespace Ryujinx.Core.OsHle.Handles
throw new InvalidOperationException();
}
- Suspend(Thread.ProcessorId);
+ Suspend(Thread);
bool Result = SchedThread.WaitSync.WaitOne(Timeout);
@@ -261,11 +140,13 @@ namespace Ryujinx.Core.OsHle.Handles
SchedThread.WaitSync.Set();
}
- public void Suspend(int ProcessorId)
+ public void Suspend(KThread Thread)
{
lock (SchedLock)
{
- SchedulerThread SchedThread = WaitingToRun[ProcessorId].Pop();
+ PrintDbgThreadInfo(Thread, "suspended.");
+
+ SchedulerThread SchedThread = WaitingToRun.Pop(Thread.ActualCore);
if (SchedThread != null)
{
@@ -273,9 +154,9 @@ namespace Ryujinx.Core.OsHle.Handles
}
else
{
- Log.PrintDebug(LogClass.KernelScheduler, $"Nothing to run on core {ProcessorId}!");
+ Log.PrintDebug(LogClass.KernelScheduler, $"Nothing to run on core {Thread.ActualCore}!");
- ActiveProcessors.Remove(ProcessorId);
+ RemoveActiveCore(Thread.ActualCore);
}
}
}
@@ -288,7 +169,9 @@ namespace Ryujinx.Core.OsHle.Handles
{
lock (SchedLock)
{
- SchedulerThread SchedThread = WaitingToRun[Thread.ProcessorId].Pop(Thread.ActualPriority);
+ SchedulerThread SchedThread = WaitingToRun.Pop(
+ Thread.ActualCore,
+ Thread.ActualPriority);
if (SchedThread == null)
{
@@ -307,7 +190,7 @@ namespace Ryujinx.Core.OsHle.Handles
{
//Just stop running the thread if it's not active,
//and run whatever is waiting to run with the higuest priority.
- Suspend(Thread.ProcessorId);
+ Suspend(Thread);
}
Resume(Thread);
@@ -333,14 +216,14 @@ namespace Ryujinx.Core.OsHle.Handles
lock (SchedLock)
{
- if (ActiveProcessors.Add(Thread.ProcessorId))
+ if (AddActiveCore(Thread))
{
PrintDbgThreadInfo(Thread, "resuming execution...");
return;
}
- WaitingToRun[Thread.ProcessorId].Push(SchedThread);
+ WaitingToRun.Push(SchedThread);
PrintDbgThreadInfo(Thread, "entering wait state...");
}
@@ -354,6 +237,8 @@ namespace Ryujinx.Core.OsHle.Handles
{
if (!SchedThread.Thread.Thread.Execute())
{
+ PrintDbgThreadInfo(SchedThread.Thread, "waked.");
+
SchedThread.WaitSched.Set();
}
else
@@ -362,6 +247,14 @@ namespace Ryujinx.Core.OsHle.Handles
}
}
+ public void Resort(KThread Thread)
+ {
+ if (AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
+ {
+ WaitingToRun.Resort(SchedThread);
+ }
+ }
+
private bool IsActive(KThread Thread)
{
if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
@@ -372,11 +265,62 @@ namespace Ryujinx.Core.OsHle.Handles
return SchedThread.IsActive;
}
+ private bool AddActiveCore(KThread Thread)
+ {
+ lock (SchedLock)
+ {
+ //First, try running it on Ideal Core.
+ int CoreMask = 1 << Thread.IdealCore;
+
+ if ((ActiveCores & CoreMask) == 0)
+ {
+ ActiveCores |= CoreMask;
+
+ Thread.ActualCore = Thread.IdealCore;
+
+ return true;
+ }
+
+ //If that fails, then try running on any core allowed by Core Mask.
+ CoreMask = Thread.CoreMask & ~ActiveCores;
+
+ if (CoreMask != 0)
+ {
+ CoreMask &= -CoreMask;
+
+ ActiveCores |= CoreMask;
+
+ for (int Bit = 0; Bit < 32; Bit++)
+ {
+ if (((CoreMask >> Bit) & 1) != 0)
+ {
+ Thread.ActualCore = Bit;
+
+ return true;
+ }
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ return false;
+ }
+ }
+
+ private void RemoveActiveCore(int Core)
+ {
+ lock (SchedLock)
+ {
+ ActiveCores &= ~(1 << Core);
+ }
+ }
+
private void PrintDbgThreadInfo(KThread Thread, string Message)
{
Log.PrintDebug(LogClass.KernelScheduler, "(" +
"ThreadId = " + Thread.ThreadId + ", " +
- "ProcessorId = " + Thread.ProcessorId + ", " +
+ "ActualCore = " + Thread.ActualCore + ", " +
+ "IdealCore = " + Thread.IdealCore + ", " +
"ActualPriority = " + Thread.ActualPriority + ", " +
"WantedPriority = " + Thread.WantedPriority + ") " + Message);
}
diff --git a/Ryujinx.Core/OsHle/Handles/KThread.cs b/Ryujinx.Core/OsHle/Handles/KThread.cs
index 2084c2ba..1a044665 100644
--- a/Ryujinx.Core/OsHle/Handles/KThread.cs
+++ b/Ryujinx.Core/OsHle/Handles/KThread.cs
@@ -7,9 +7,13 @@ namespace Ryujinx.Core.OsHle.Handles
{
public AThread Thread { get; private set; }
+ public int CoreMask { get; set; }
+
public long MutexAddress { get; set; }
public long CondVarAddress { get; set; }
+ private Process Process;
+
public KThread NextMutexThread { get; set; }
public KThread NextCondVarThread { get; set; }
@@ -18,16 +22,24 @@ namespace Ryujinx.Core.OsHle.Handles
public int ActualPriority { get; private set; }
public int WantedPriority { get; private set; }
- public int ProcessorId { get; private set; }
+ public int IdealCore { get; private set; }
+ public int ActualCore { get; set; }
public int WaitHandle { get; set; }
public int ThreadId => Thread.ThreadId;
- public KThread(AThread Thread, int ProcessorId, int Priority)
+ public KThread(
+ AThread Thread,
+ Process Process,
+ int IdealCore,
+ int Priority)
{
- this.Thread = Thread;
- this.ProcessorId = ProcessorId;
+ this.Thread = Thread;
+ this.Process = Process;
+ this.IdealCore = IdealCore;
+
+ CoreMask = 1 << IdealCore;
ActualPriority = WantedPriority = Priority;
}
@@ -54,59 +66,138 @@ namespace Ryujinx.Core.OsHle.Handles
{
ActualPriority = CurrPriority;
- UpdateWaitList();
+ UpdateWaitLists();
MutexOwner?.UpdatePriority();
}
}
- private void UpdateWaitList()
+ private void UpdateWaitLists()
+ {
+ UpdateMutexList();
+ UpdateCondVarList();
+
+ Process.Scheduler.Resort(this);
+ }
+
+ private void UpdateMutexList()
{
KThread OwnerThread = MutexOwner;
- if (OwnerThread != null)
+ if (OwnerThread == null)
{
- //The MutexOwner field should only be non null when the thread is
- //waiting for the lock, and the lock belongs to another thread.
- if (OwnerThread == this)
+ return;
+ }
+
+ //The MutexOwner field should only be non-null when the thread is
+ //waiting for the lock, and the lock belongs to another thread.
+ if (OwnerThread == this)
+ {
+ throw new InvalidOperationException();
+ }
+
+ lock (OwnerThread)
+ {
+ //Remove itself from the list.
+ KThread CurrThread = OwnerThread;
+
+ while (CurrThread.NextMutexThread != null)
{
- throw new InvalidOperationException();
+ if (CurrThread.NextMutexThread == this)
+ {
+ CurrThread.NextMutexThread = NextMutexThread;
+
+ break;
+ }
+
+ CurrThread = CurrThread.NextMutexThread;
}
- lock (OwnerThread)
- {
- //Remove itself from the list.
- KThread CurrThread = OwnerThread;
+ //Re-add taking new priority into account.
+ CurrThread = OwnerThread;
- while (CurrThread.NextMutexThread != null)
+ while (CurrThread.NextMutexThread != null)
+ {
+ if (CurrThread.NextMutexThread.ActualPriority > ActualPriority)
{
- if (CurrThread.NextMutexThread == this)
- {
- CurrThread.NextMutexThread = NextMutexThread;
+ break;
+ }
- break;
- }
+ CurrThread = CurrThread.NextMutexThread;
+ }
- CurrThread = CurrThread.NextMutexThread;
- }
+ NextMutexThread = CurrThread.NextMutexThread;
- //Re-add taking new priority into account.
- CurrThread = OwnerThread;
+ CurrThread.NextMutexThread = this;
+ }
+ }
- while (CurrThread.NextMutexThread != null)
+ private void UpdateCondVarList()
+ {
+ lock (Process.ThreadArbiterListLock)
+ {
+ if (Process.ThreadArbiterListHead == null)
+ {
+ return;
+ }
+
+ //Remove itself from the list.
+ bool Found;
+
+ KThread CurrThread = Process.ThreadArbiterListHead;
+
+ if (Found = (Process.ThreadArbiterListHead == this))
+ {
+ Process.ThreadArbiterListHead = Process.ThreadArbiterListHead.NextCondVarThread;
+ }
+ else
+ {
+ while (CurrThread.NextCondVarThread != null)
{
- if (CurrThread.NextMutexThread.ActualPriority < ActualPriority)
+ if (CurrThread.NextCondVarThread == this)
{
+ CurrThread.NextCondVarThread = NextCondVarThread;
+
+ Found = true;
+
break;
}
- CurrThread = CurrThread.NextMutexThread;
+ CurrThread = CurrThread.NextCondVarThread;
}
+ }
- NextMutexThread = CurrThread.NextMutexThread;
+ if (!Found)
+ {
+ return;
+ }
+
+ //Re-add taking new priority into account.
+ if (Process.ThreadArbiterListHead == null ||
+ Process.ThreadArbiterListHead.ActualPriority > ActualPriority)
+ {
+ NextCondVarThread = Process.ThreadArbiterListHead;
+
+ Process.ThreadArbiterListHead = this;
- CurrThread.NextMutexThread = this;
+ return;
}
+
+ CurrThread = Process.ThreadArbiterListHead;
+
+ while (CurrThread.NextCondVarThread != null)
+ {
+ if (CurrThread.NextCondVarThread.ActualPriority > ActualPriority)
+ {
+ break;
+ }
+
+ CurrThread = CurrThread.NextCondVarThread;
+ }
+
+ NextCondVarThread = CurrThread.NextCondVarThread;
+
+ CurrThread.NextCondVarThread = this;
}
}
}
diff --git a/Ryujinx.Core/OsHle/Handles/SchedulerThread.cs b/Ryujinx.Core/OsHle/Handles/SchedulerThread.cs
new file mode 100644
index 00000000..4a8b4c09
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Handles/SchedulerThread.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Threading;
+
+namespace Ryujinx.Core.OsHle.Handles
+{
+ class SchedulerThread : IDisposable
+ {
+ public KThread Thread { get; private set; }
+
+ public SchedulerThread Next { get; set; }
+
+ public bool IsActive { get; set; }
+
+ public AutoResetEvent WaitSync { get; private set; }
+ public ManualResetEvent WaitActivity { get; private set; }
+ public AutoResetEvent WaitSched { get; private set; }
+
+ public SchedulerThread(KThread Thread)
+ {
+ this.Thread = Thread;
+
+ IsActive = true;
+
+ WaitSync = new AutoResetEvent(false);
+
+ WaitActivity = new ManualResetEvent(true);
+
+ WaitSched = new AutoResetEvent(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool Disposing)
+ {
+ if (Disposing)
+ {
+ WaitSync.Dispose();
+
+ WaitActivity.Dispose();
+
+ WaitSched.Dispose();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/ThreadQueue.cs b/Ryujinx.Core/OsHle/Handles/ThreadQueue.cs
new file mode 100644
index 00000000..41fbd81e
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Handles/ThreadQueue.cs
@@ -0,0 +1,158 @@
+namespace Ryujinx.Core.OsHle.Handles
+{
+ class ThreadQueue
+ {
+ private const int LowestPriority = 0x40;
+
+ private SchedulerThread Head;
+
+ private object ListLock;
+
+ public ThreadQueue()
+ {
+ ListLock = new object();
+ }
+
+ public void Push(SchedulerThread Wait)
+ {
+ lock (ListLock)
+ {
+ //Ensure that we're not creating circular references
+ //by adding a thread that is already on the list.
+ if (HasThread(Wait))
+ {
+ return;
+ }
+
+ if (Head == null || Head.Thread.ActualPriority > Wait.Thread.ActualPriority)
+ {
+ Wait.Next = Head;
+
+ Head = Wait;
+
+ return;
+ }
+
+ SchedulerThread Curr = Head;
+
+ while (Curr.Next != null)
+ {
+ if (Curr.Next.Thread.ActualPriority > Wait.Thread.ActualPriority)
+ {
+ break;
+ }
+
+ Curr = Curr.Next;
+ }
+
+ Wait.Next = Curr.Next;
+ Curr.Next = Wait;
+ }
+ }
+
+ public SchedulerThread Pop(int Core, int MinPriority = LowestPriority)
+ {
+ lock (ListLock)
+ {
+ int CoreMask = 1 << Core;
+
+ SchedulerThread Prev = null;
+ SchedulerThread Curr = Head;
+
+ while (Curr != null)
+ {
+ KThread Thread = Curr.Thread;
+
+ if (Thread.ActualPriority <= MinPriority && (Thread.CoreMask & CoreMask) != 0)
+ {
+ if (Prev != null)
+ {
+ Prev.Next = Curr.Next;
+ }
+ else
+ {
+ Head = Head.Next;
+ }
+
+ break;
+ }
+
+ Prev = Curr;
+ Curr = Curr.Next;
+ }
+
+ return Curr;
+ }
+ }
+
+ public bool Remove(SchedulerThread Thread)
+ {
+ lock (ListLock)
+ {
+ if (Head == null)
+ {
+ return false;
+ }
+ else if (Head == Thread)
+ {
+ Head = Head.Next;
+
+ return true;
+ }
+
+ SchedulerThread Prev = Head;
+ SchedulerThread Curr = Head.Next;
+
+ while (Curr != null)
+ {
+ if (Curr == Thread)
+ {
+ Prev.Next = Curr.Next;
+
+ return true;
+ }
+
+ Prev = Curr;
+ Curr = Curr.Next;
+ }
+
+ return false;
+ }
+ }
+
+ public bool Resort(SchedulerThread Thread)
+ {
+ lock (ListLock)
+ {
+ if (Remove(Thread))
+ {
+ Push(Thread);
+
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ public bool HasThread(SchedulerThread Thread)
+ {
+ lock (ListLock)
+ {
+ SchedulerThread Curr = Head;
+
+ while (Curr != null)
+ {
+ if (Curr == Thread)
+ {
+ return true;
+ }
+
+ Curr = Curr.Next;
+ }
+
+ return false;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
index be394c4b..bbbd0fb0 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
@@ -22,8 +22,6 @@ namespace Ryujinx.Core.OsHle.Kernel
private ConcurrentDictionary<KThread, AutoResetEvent> SyncWaits;
- private object CondVarLock;
-
private HashSet<(HSharedMem, long)> MappedSharedMems;
private ulong CurrentHeapSize;
@@ -80,8 +78,6 @@ namespace Ryujinx.Core.OsHle.Kernel
SyncWaits = new ConcurrentDictionary<KThread, AutoResetEvent>();
- CondVarLock = new object();
-
MappedSharedMems = new HashSet<(HSharedMem, long)>();
}
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
index e5b080a8..24317bdf 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
@@ -131,7 +131,7 @@ namespace Ryujinx.Core.OsHle.Kernel
Handles[HandlesCount] = WaitEvent;
- Process.Scheduler.Suspend(CurrThread.ProcessorId);
+ Process.Scheduler.Suspend(CurrThread);
int HandleIndex;
@@ -237,7 +237,7 @@ namespace Ryujinx.Core.OsHle.Kernel
if (Session != null)
{
- Process.Scheduler.Suspend(CurrThread.ProcessorId);
+ Process.Scheduler.Suspend(CurrThread);
IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
index ee45c02c..71f3347a 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
@@ -75,7 +75,7 @@ namespace Ryujinx.Core.OsHle.Kernel
}
else
{
- Process.Scheduler.Suspend(CurrThread.ProcessorId);
+ Process.Scheduler.Suspend(CurrThread);
Thread.Sleep(NsTimeConverter.GetTimeMs(Ns));
@@ -132,7 +132,7 @@ namespace Ryujinx.Core.OsHle.Kernel
private void SvcGetCurrentProcessorNumber(AThreadState ThreadState)
{
- ThreadState.X0 = (ulong)Process.GetThread(ThreadState.Tpidr).ProcessorId;
+ ThreadState.X0 = (ulong)Process.GetThread(ThreadState.Tpidr).ActualCore;
}
private void SvcGetThreadId(AThreadState ThreadState)
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs
index 57608cda..0ca2a5f9 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs
@@ -260,17 +260,23 @@ namespace Ryujinx.Core.OsHle.Kernel
WaitThread.MutexAddress = MutexAddress;
WaitThread.CondVarAddress = CondVarAddress;
- lock (CondVarLock)
+ lock (Process.ThreadArbiterListLock)
{
- KThread CurrThread = Process.ThreadArbiterList;
+ KThread CurrThread = Process.ThreadArbiterListHead;
- if (CurrThread != null)
+ if (CurrThread == null || CurrThread.ActualPriority > WaitThread.ActualPriority)
+ {
+ WaitThread.NextCondVarThread = Process.ThreadArbiterListHead;
+
+ Process.ThreadArbiterListHead = WaitThread;
+ }
+ else
{
bool DoInsert = CurrThread != WaitThread;
while (CurrThread.NextCondVarThread != null)
{
- if (CurrThread.NextCondVarThread.ActualPriority < WaitThread.ActualPriority)
+ if (CurrThread.NextCondVarThread.ActualPriority > WaitThread.ActualPriority)
{
break;
}
@@ -293,10 +299,6 @@ namespace Ryujinx.Core.OsHle.Kernel
CurrThread.NextCondVarThread = WaitThread;
}
}
- else
- {
- Process.ThreadArbiterList = WaitThread;
- }
}
Ns.Log.PrintDebug(LogClass.KernelSvc, "Entering wait state...");
@@ -315,10 +317,10 @@ namespace Ryujinx.Core.OsHle.Kernel
private void CondVarSignal(long CondVarAddress, int Count)
{
- lock (CondVarLock)
+ lock (Process.ThreadArbiterListLock)
{
KThread PrevThread = null;
- KThread CurrThread = Process.ThreadArbiterList;
+ KThread CurrThread = Process.ThreadArbiterListHead;
while (CurrThread != null && (Count == -1 || Count > 0))
{
@@ -330,7 +332,7 @@ namespace Ryujinx.Core.OsHle.Kernel
}
else
{
- Process.ThreadArbiterList = CurrThread.NextCondVarThread;
+ Process.ThreadArbiterListHead = CurrThread.NextCondVarThread;
}
CurrThread.NextCondVarThread = null;
@@ -401,7 +403,7 @@ namespace Ryujinx.Core.OsHle.Kernel
return;
}
- if (CurrThread.NextMutexThread.ActualPriority < WaitThread.ActualPriority)
+ if (CurrThread.NextMutexThread.ActualPriority > WaitThread.ActualPriority)
{
break;
}
diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs
index 3ccbc016..8520b9ad 100644
--- a/Ryujinx.Core/OsHle/Process.cs
+++ b/Ryujinx.Core/OsHle/Process.cs
@@ -38,7 +38,9 @@ namespace Ryujinx.Core.OsHle
public KProcessScheduler Scheduler { get; private set; }
- public KThread ThreadArbiterList { get; set; }
+ public KThread ThreadArbiterListHead { get; set; }
+
+ public object ThreadArbiterListLock { get; private set; }
public KProcessHandleTable HandleTable { get; private set; }
@@ -70,6 +72,8 @@ namespace Ryujinx.Core.OsHle
Memory = new AMemory();
+ ThreadArbiterListLock = new object();
+
HandleTable = new KProcessHandleTable();
AppletState = new AppletStateMgr();
@@ -196,7 +200,7 @@ namespace Ryujinx.Core.OsHle
AThread CpuThread = new AThread(GetTranslator(), Memory, EntryPoint);
- KThread Thread = new KThread(CpuThread, ProcessorId, Priority);
+ KThread Thread = new KThread(CpuThread, this, ProcessorId, Priority);
int Handle = HandleTable.OpenHandle(Thread);