aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs22
-rw-r--r--Ryujinx.Core/OsHle/Handles/KThread.cs2
-rw-r--r--Ryujinx.Core/OsHle/Kernel/KernelErr.cs3
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcThread.cs85
4 files changed, 109 insertions, 3 deletions
diff --git a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
index a154b1c6..33f7fb14 100644
--- a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
+++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
@@ -196,6 +196,28 @@ namespace Ryujinx.Core.OsHle.Handles
Resume(Thread);
}
+ public bool TryRunning(KThread Thread)
+ {
+ if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
+ {
+ throw new InvalidOperationException();
+ }
+
+ lock (SchedLock)
+ {
+ if (WaitingToRun.HasThread(SchedThread) && AddActiveCore(Thread))
+ {
+ WaitingToRun.Remove(SchedThread);
+
+ RunThread(SchedThread);
+
+ return true;
+ }
+
+ return false;
+ }
+ }
+
public void Resume(KThread Thread)
{
if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
diff --git a/Ryujinx.Core/OsHle/Handles/KThread.cs b/Ryujinx.Core/OsHle/Handles/KThread.cs
index 1a044665..a430974c 100644
--- a/Ryujinx.Core/OsHle/Handles/KThread.cs
+++ b/Ryujinx.Core/OsHle/Handles/KThread.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.Core.OsHle.Handles
public int ActualPriority { get; private set; }
public int WantedPriority { get; private set; }
- public int IdealCore { get; private set; }
+ public int IdealCore { get; set; }
public int ActualCore { get; set; }
public int WaitHandle { get; set; }
diff --git a/Ryujinx.Core/OsHle/Kernel/KernelErr.cs b/Ryujinx.Core/OsHle/Kernel/KernelErr.cs
index 87f9cf3b..17c0044c 100644
--- a/Ryujinx.Core/OsHle/Kernel/KernelErr.cs
+++ b/Ryujinx.Core/OsHle/Kernel/KernelErr.cs
@@ -5,7 +5,10 @@ namespace Ryujinx.Core.OsHle.Kernel
public const int InvalidAlignment = 102;
public const int InvalidAddress = 106;
public const int InvalidMemRange = 110;
+ public const int InvalidPriority = 112;
+ public const int InvalidCoreId = 113;
public const int InvalidHandle = 114;
+ public const int InvalidCoreMask = 116;
public const int Timeout = 117;
public const int Canceled = 118;
public const int CountOutOfRange = 119;
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
index 71f3347a..94912f53 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
@@ -17,11 +17,28 @@ namespace Ryujinx.Core.OsHle.Kernel
int Priority = (int)ThreadState.X4;
int ProcessorId = (int)ThreadState.X5;
+ if ((uint)Priority > 0x3f)
+ {
+ Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid priority 0x{Priority:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPriority);
+
+ return;
+ }
+
if (ProcessorId == -2)
{
//TODO: Get this value from the NPDM file.
ProcessorId = 0;
}
+ else if ((uint)ProcessorId > 3)
+ {
+ Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core id 0x{ProcessorId:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidCoreId);
+
+ return;
+ }
int Handle = Process.MakeThread(
EntryPoint,
@@ -125,9 +142,73 @@ namespace Ryujinx.Core.OsHle.Kernel
private void SvcSetThreadCoreMask(AThreadState ThreadState)
{
- ThreadState.X0 = 0;
+ int Handle = (int)ThreadState.X0;
+ int IdealCore = (int)ThreadState.X1;
+ long CoreMask = (long)ThreadState.X2;
+
+ KThread Thread = GetThread(ThreadState.Tpidr, Handle);
+
+ if (IdealCore == -2)
+ {
+ //TODO: Get this value from the NPDM file.
+ IdealCore = 0;
+
+ CoreMask = 1 << IdealCore;
+ }
+ else if (IdealCore != -3)
+ {
+ if ((uint)IdealCore > 3)
+ {
+ Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core id 0x{IdealCore:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidCoreId);
+
+ return;
+ }
+
+ if ((CoreMask & (1 << IdealCore)) == 0)
+ {
+ Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core mask 0x{CoreMask:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidCoreMask);
- //TODO: Error codes.
+ return;
+ }
+ }
+
+ if (Thread == null)
+ {
+ Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+
+ return;
+ }
+
+ if (IdealCore == -3)
+ {
+ if ((CoreMask & (1 << Thread.IdealCore)) == 0)
+ {
+ Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core mask 0x{CoreMask:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidCoreMask);
+
+ return;
+ }
+ }
+ else
+ {
+ Thread.IdealCore = IdealCore;
+ }
+
+ Thread.CoreMask = (int)CoreMask;
+
+ KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
+
+ Process.Scheduler.Yield(CurrThread);
+ Process.Scheduler.TryRunning(Thread);
+
+ ThreadState.X0 = 0;
}
private void SvcGetCurrentProcessorNumber(AThreadState ThreadState)