diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-04-19 16:18:30 -0300 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-04-19 16:18:30 -0300 |
| commit | 03002f6537e3208e6951bc9092e958985e200c7d (patch) | |
| tree | e3e4eea4eba155d82168915ad7c3a507e3a20f59 /Ryujinx.Core | |
| parent | 33ae6e544bd477da629e3f4ab4925f457ecfbbb7 (diff) | |
Add SvcSetThreadActivity, tweak SignalProcessWideKey, add fmul32i shader instructions and other small fixes
Diffstat (limited to 'Ryujinx.Core')
| -rw-r--r-- | Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs | 83 | ||||
| -rw-r--r-- | Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs | 21 | ||||
| -rw-r--r-- | Ryujinx.Core/OsHle/Kernel/SvcHandler.cs | 3 | ||||
| -rw-r--r-- | Ryujinx.Core/OsHle/Kernel/SvcThread.cs | 23 |
4 files changed, 112 insertions, 18 deletions
diff --git a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs index 1300d218..2f694600 100644 --- a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs +++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs @@ -15,11 +15,15 @@ namespace Ryujinx.Core.OsHle.Handles public AutoResetEvent WaitEvent { get; private set; } + public bool Active { get; set; } + public SchedulerThread(KThread Thread) { this.Thread = Thread; WaitEvent = new AutoResetEvent(false); + + Active = true; } public void Dispose() @@ -98,7 +102,10 @@ namespace Ryujinx.Core.OsHle.Handles public bool Remove(SchedulerThread SchedThread) { - return Threads.Remove(SchedThread); + lock (Threads) + { + return Threads.Remove(SchedThread); + } } } @@ -180,6 +187,55 @@ namespace Ryujinx.Core.OsHle.Handles } } + public void SetThreadActivity(KThread Thread, bool Active) + { + if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread)) + { + throw new InvalidOperationException(); + } + + lock (SchedLock) + { + bool OldState = SchedThread.Active; + + SchedThread.Active = Active; + + if (!OldState && Active) + { + if (ActiveProcessors.Add(Thread.ProcessorId)) + { + RunThread(SchedThread); + } + else + { + WaitingToRun[Thread.ProcessorId].Push(SchedThread); + + PrintDbgThreadInfo(Thread, "entering wait state..."); + } + } + else if (OldState && !Active) + { + if (Thread.Thread.IsCurrentThread()) + { + Suspend(Thread.ProcessorId); + + PrintDbgThreadInfo(Thread, "entering inactive wait state..."); + } + else + { + WaitingToRun[Thread.ProcessorId].Remove(SchedThread); + } + } + } + + if (!Active && Thread.Thread.IsCurrentThread()) + { + SchedThread.WaitEvent.WaitOne(); + + PrintDbgThreadInfo(Thread, "resuming execution..."); + } + } + public void Suspend(int ProcessorId) { lock (SchedLock) @@ -222,9 +278,7 @@ namespace Ryujinx.Core.OsHle.Handles public void Resume(KThread Thread) { - SchedulerThread SchedThread; - - if (!AllThreads.TryGetValue(Thread, out SchedThread)) + if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread)) { throw new InvalidOperationException(); } @@ -236,18 +290,25 @@ namespace Ryujinx.Core.OsHle.Handles { KThread Thread = SchedThread.Thread; - lock (SchedLock) + if (SchedThread.Active) { - if (ActiveProcessors.Add(Thread.ProcessorId)) + lock (SchedLock) { - PrintDbgThreadInfo(Thread, "resuming execution..."); + if (ActiveProcessors.Add(Thread.ProcessorId)) + { + PrintDbgThreadInfo(Thread, "resuming execution..."); - return; - } + return; + } - PrintDbgThreadInfo(Thread, "entering wait state..."); + WaitingToRun[Thread.ProcessorId].Push(SchedThread); - WaitingToRun[Thread.ProcessorId].Push(SchedThread); + PrintDbgThreadInfo(Thread, "entering wait state..."); + } + } + else + { + PrintDbgThreadInfo(Thread, "entering inactive wait state..."); } SchedThread.WaitEvent.WaitOne(); diff --git a/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs b/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs index 91ed9158..f7657376 100644 --- a/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs +++ b/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs @@ -57,7 +57,7 @@ namespace Ryujinx.Core.OsHle.Kernel Count = Process.Memory.ReadInt32(CondVarAddress); - if (Count > 0) + if (Result && Count > 0) { Process.Memory.WriteInt32(CondVarAddress, Count - 1); } @@ -73,10 +73,10 @@ namespace Ryujinx.Core.OsHle.Kernel { if (Count < 0) { - Process.Memory.WriteInt32(CondVarAddress, WaitingThreads.Count); - foreach ((_, AutoResetEvent WaitEvent) in WaitingThreads) { + IncrementCondVarValue(); + WaitEvent.Set(); } @@ -84,8 +84,6 @@ namespace Ryujinx.Core.OsHle.Kernel } else { - Process.Memory.WriteInt32(CondVarAddress, Count); - while (WaitingThreads.Count > 0 && Count-- > 0) { int HighestPriority = WaitingThreads[0].Thread.Priority; @@ -101,6 +99,8 @@ namespace Ryujinx.Core.OsHle.Kernel } } + IncrementCondVarValue(); + WaitingThreads[HighestPrioIndex].WaitEvent.Set(); WaitingThreads.RemoveAt(HighestPrioIndex); @@ -111,6 +111,17 @@ namespace Ryujinx.Core.OsHle.Kernel Process.Scheduler.Yield(Thread); } + private void IncrementCondVarValue() + { + AcquireCondVarValue(); + + int Count = Process.Memory.ReadInt32(CondVarAddress); + + Process.Memory.WriteInt32(CondVarAddress, Count + 1); + + ReleaseCondVarValue(); + } + private void AcquireCondVarValue() { if (!OwnsCondVarValue) diff --git a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs index fa772988..16ef8697 100644 --- a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs +++ b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs @@ -63,7 +63,8 @@ namespace Ryujinx.Core.OsHle.Kernel { 0x25, SvcGetThreadId }, { 0x26, SvcBreak }, { 0x27, SvcOutputDebugString }, - { 0x29, SvcGetInfo } + { 0x29, SvcGetInfo }, + { 0x32, SvcSetThreadActivity } }; this.Ns = Ns; diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs index 2534c9d9..06147b28 100644 --- a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs +++ b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs @@ -147,7 +147,28 @@ namespace Ryujinx.Core.OsHle.Kernel } else { - Logging.Warn(LogClass.KernelSvc, $"Tried to GetThreadId on invalid thread handle 0x{Handle:x8}!"); + Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); + } + } + + private void SvcSetThreadActivity(AThreadState ThreadState) + { + int Handle = (int)ThreadState.X0; + bool Active = (int)ThreadState.X1 != 0; + + KThread CurrThread = Process.HandleTable.GetData<KThread>(Handle); + + if (CurrThread != null) + { + Process.Scheduler.SetThreadActivity(CurrThread, Active); + + ThreadState.X0 = 0; + } + else + { + Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); } |
