diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-09-18 20:36:43 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-09-18 20:36:43 -0300 |
| commit | b8133c19971c7a2026af803003fafedbdb70488e (patch) | |
| tree | 84f4630e897ccd3f77b86051241a22a6cf45193d /Ryujinx.HLE/HOS/Kernel/SvcSystem.cs | |
| parent | 33e2810ef36fe0cf613aecd4c609f425aed02539 (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.cs | 155 |
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; |
