aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-09-18 20:36:43 -0300
committerGitHub <noreply@github.com>2018-09-18 20:36:43 -0300
commitb8133c19971c7a2026af803003fafedbdb70488e (patch)
tree84f4630e897ccd3f77b86051241a22a6cf45193d /Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
parent33e2810ef36fe0cf613aecd4c609f425aed02539 (diff)
Thread scheduler rewrite (#393)
* Started to rewrite the thread scheduler * Add a single core-like scheduling mode, enabled by default * Clear exclusive monitor on context switch * Add SetThreadActivity, misc fixes * Implement WaitForAddress and SignalToAddress svcs, misc fixes * Misc fixes (on SetActivity and Arbiter), other tweaks * Rebased * Add missing null check * Rename multicore key on config, fix UpdatePriorityInheritance * Make scheduling data MLQs private * nit: Ordering
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/SvcSystem.cs')
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcSystem.cs155
1 files changed, 36 insertions, 119 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
index d10eb117..60ccf7f7 100644
--- a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
@@ -68,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Kernel
if (Event != null)
{
- Event.WaitEvent.Reset();
+ Event.Reset();
ThreadState.X0 = 0;
}
@@ -80,115 +80,6 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
- private void SvcWaitSynchronization(AThreadState ThreadState)
- {
- long HandlesPtr = (long)ThreadState.X1;
- int HandlesCount = (int)ThreadState.X2;
- ulong Timeout = ThreadState.X3;
-
- Device.Log.PrintDebug(LogClass.KernelSvc,
- "HandlesPtr = 0x" + HandlesPtr .ToString("x16") + ", " +
- "HandlesCount = 0x" + HandlesCount.ToString("x8") + ", " +
- "Timeout = 0x" + Timeout .ToString("x16"));
-
- if ((uint)HandlesCount > 0x40)
- {
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange);
-
- return;
- }
-
- KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
- WaitHandle[] Handles = new WaitHandle[HandlesCount + 1];
-
- for (int Index = 0; Index < HandlesCount; Index++)
- {
- int Handle = Memory.ReadInt32(HandlesPtr + Index * 4);
-
- KSynchronizationObject SyncObj = Process.HandleTable.GetData<KSynchronizationObject>(Handle);
-
- if (SyncObj == null)
- {
- Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- Handles[Index] = SyncObj.WaitEvent;
- }
-
- using (AutoResetEvent WaitEvent = new AutoResetEvent(false))
- {
- if (!SyncWaits.TryAdd(CurrThread, WaitEvent))
- {
- throw new InvalidOperationException();
- }
-
- Handles[HandlesCount] = WaitEvent;
-
- Process.Scheduler.Suspend(CurrThread);
-
- int HandleIndex;
-
- ulong Result = 0;
-
- if (Timeout != ulong.MaxValue)
- {
- HandleIndex = WaitHandle.WaitAny(Handles, NsTimeConverter.GetTimeMs(Timeout));
- }
- else
- {
- HandleIndex = WaitHandle.WaitAny(Handles);
- }
-
- if (HandleIndex == WaitHandle.WaitTimeout)
- {
- Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
- }
- else if (HandleIndex == HandlesCount)
- {
- Result = MakeError(ErrorModule.Kernel, KernelErr.Canceled);
- }
-
- SyncWaits.TryRemove(CurrThread, out _);
-
- Process.Scheduler.Resume(CurrThread);
-
- ThreadState.X0 = Result;
-
- if (Result == 0)
- {
- ThreadState.X1 = (ulong)HandleIndex;
- }
- }
- }
-
- private void SvcCancelSynchronization(AThreadState ThreadState)
- {
- int ThreadHandle = (int)ThreadState.X0;
-
- KThread Thread = GetThread(ThreadState.Tpidr, ThreadHandle);
-
- if (Thread == null)
- {
- Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- if (SyncWaits.TryRemove(Thread, out AutoResetEvent WaitEvent))
- {
- WaitEvent.Set();
- }
-
- ThreadState.X0 = 0;
- }
-
private void SvcGetSystemTick(AThreadState ThreadState)
{
ThreadState.X0 = ThreadState.CntpctEl0;
@@ -203,7 +94,7 @@ namespace Ryujinx.HLE.HOS.Kernel
//TODO: Validate that app has perms to access the service, and that the service
//actually exists, return error codes otherwise.
- KSession Session = new KSession(ServiceFactory.MakeService(Name), Name);
+ KSession Session = new KSession(ServiceFactory.MakeService(System, Name), Name);
ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session);
@@ -225,27 +116,38 @@ namespace Ryujinx.HLE.HOS.Kernel
(int)ThreadState.X2);
}
- private void SendSyncRequest(AThreadState ThreadState, long CmdPtr, long Size, int Handle)
+ private void SendSyncRequest(AThreadState ThreadState, long MessagePtr, long Size, int Handle)
{
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
- byte[] CmdData = Memory.ReadBytes(CmdPtr, Size);
+ byte[] MessageData = Memory.ReadBytes(MessagePtr, Size);
KSession Session = Process.HandleTable.GetData<KSession>(Handle);
if (Session != null)
{
- Process.Scheduler.Suspend(CurrThread);
+ //Process.Scheduler.Suspend(CurrThread);
+
+ System.CriticalSectionLock.Lock();
- IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
+ KThread CurrentThread = System.Scheduler.GetCurrentThread();
- long Result = IpcHandler.IpcCall(Device, Process, Memory, Session, Cmd, CmdPtr);
+ CurrentThread.SignaledObj = null;
+ CurrentThread.ObjSyncResult = 0;
- Thread.Yield();
+ CurrentThread.Reschedule(ThreadSchedState.Paused);
- Process.Scheduler.Resume(CurrThread);
+ IpcMessage Message = new IpcMessage(MessageData, MessagePtr);
- ThreadState.X0 = (ulong)Result;
+ ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
+ CurrentThread,
+ Session,
+ Message,
+ MessagePtr));
+
+ System.CriticalSectionLock.Unlock();
+
+ ThreadState.X0 = (ulong)CurrentThread.ObjSyncResult;
}
else
{
@@ -255,6 +157,21 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
+ private void ProcessIpcRequest(object State)
+ {
+ HleIpcMessage IpcMessage = (HleIpcMessage)State;
+
+ IpcMessage.Thread.ObjSyncResult = (int)IpcHandler.IpcCall(
+ Device,
+ Process,
+ Memory,
+ IpcMessage.Session,
+ IpcMessage.Message,
+ IpcMessage.MessagePtr);
+
+ IpcMessage.Thread.Reschedule(ThreadSchedState.Running);
+ }
+
private void SvcBreak(AThreadState ThreadState)
{
long Reason = (long)ThreadState.X0;