Просмотр исходного кода

[HLE/Kernel] Fix SetThreadPriority, allow nano seconds values > int.MaxValue, fix on WaitProcessWideKeyAtomic (althrough looks like it still doesn't work properly

gdkchan 8 лет назад
Родитель
Сommit
33ae6e544b

+ 3 - 7
Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs

@@ -22,7 +22,7 @@ namespace Ryujinx.Core.OsHle.Kernel
             WaitingThreads = new List<(KThread, AutoResetEvent)>();
         }
 
-        public bool WaitForSignal(KThread Thread, long Timeout)
+        public bool WaitForSignal(KThread Thread, ulong Timeout)
         {
             bool Result = true;
 
@@ -37,23 +37,19 @@ namespace Ryujinx.Core.OsHle.Kernel
                         WaitingThreads.Add((Thread, WaitEvent));
                     }
 
-                    Process.Scheduler.Suspend(Thread.ProcessorId);
-
-                    if (Timeout < 0)
+                    if (Timeout == ulong.MaxValue)
                     {
                         Result = WaitEvent.WaitOne();
                     }
                     else
                     {
-                        Result = WaitEvent.WaitOne((int)(Timeout / 1000000));
+                        Result = WaitEvent.WaitOne(NsTimeConverter.GetTimeMs(Timeout));
 
                         lock (WaitingThreads)
                         {
                             WaitingThreads.Remove((Thread, WaitEvent));
                         }
                     }
-
-                    Process.Scheduler.Resume(Thread);
                 }
             }
 

+ 6 - 2
Ryujinx.Core/OsHle/Kernel/MutualExclusion.cs

@@ -12,6 +12,8 @@ namespace Ryujinx.Core.OsHle.Kernel
 
         private long MutexAddress;
 
+        private int OwnerThreadHandle;
+
         private List<(KThread Thread, AutoResetEvent WaitEvent)> WaitingThreads;
 
         public MutualExclusion(Process Process, long MutexAddress)
@@ -24,8 +26,6 @@ namespace Ryujinx.Core.OsHle.Kernel
 
         public void WaitForLock(KThread RequestingThread)
         {
-            int OwnerThreadHandle = Process.Memory.ReadInt32(MutexAddress) & ~MutexHasListenersMask;
-
             WaitForLock(RequestingThread, OwnerThreadHandle);
         }
 
@@ -80,10 +80,14 @@ namespace Ryujinx.Core.OsHle.Kernel
                     WaitingThreads.RemoveAt(HighestPrioIndex);
 
                     Process.Memory.WriteInt32(MutexAddress, HasListeners | Handle);
+
+                    OwnerThreadHandle = Handle;
                 }
                 else
                 {
                     Process.Memory.WriteInt32(MutexAddress, 0);
+
+                    OwnerThreadHandle = 0;
                 }
             }
         }

+ 19 - 0
Ryujinx.Core/OsHle/Kernel/NsTimeConverter.cs

@@ -0,0 +1,19 @@
+namespace Ryujinx.Core.OsHle.Kernel
+{
+    static class NsTimeConverter
+    {
+        public static int GetTimeMs(ulong Ns)
+        {
+            ulong Ms = Ns / 1_000_000;
+
+            if (Ms < int.MaxValue)
+            {
+                return (int)Ms;
+            }
+            else
+            {
+                return int.MaxValue;
+            }
+        }
+    }
+}

+ 5 - 5
Ryujinx.Core/OsHle/Kernel/SvcSystem.cs

@@ -83,9 +83,9 @@ namespace Ryujinx.Core.OsHle.Kernel
 
         private void SvcWaitSynchronization(AThreadState ThreadState)
         {
-            long HandlesPtr   = (long)ThreadState.X1;
-            int  HandlesCount =  (int)ThreadState.X2;
-            long Timeout      = (long)ThreadState.X3;
+            long  HandlesPtr   = (long)ThreadState.X1;
+            int   HandlesCount =  (int)ThreadState.X2;
+            ulong Timeout      =       ThreadState.X3;
 
             KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
 
@@ -115,9 +115,9 @@ namespace Ryujinx.Core.OsHle.Kernel
 
             ulong Result = 0;
 
-            if (Timeout != -1)
+            if (Timeout != ulong.MaxValue)
             {
-                HandleIndex = WaitHandle.WaitAny(Handles, (int)(Timeout / 1000000));
+                HandleIndex = WaitHandle.WaitAny(Handles, NsTimeConverter.GetTimeMs(Timeout));
 
                 if (HandleIndex == WaitHandle.WaitTimeout)
                 {

+ 6 - 6
Ryujinx.Core/OsHle/Kernel/SvcThread.cs

@@ -64,11 +64,11 @@ namespace Ryujinx.Core.OsHle.Kernel
 
         private void SvcSleepThread(AThreadState ThreadState)
         {
-            ulong NanoSecs = ThreadState.X0;
+            ulong Ns = ThreadState.X0;
 
             KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
 
-            if (NanoSecs == 0)
+            if (Ns == 0)
             {
                 Process.Scheduler.Yield(CurrThread);
             }
@@ -76,7 +76,7 @@ namespace Ryujinx.Core.OsHle.Kernel
             {
                 Process.Scheduler.Suspend(CurrThread.ProcessorId);
 
-                Thread.Sleep((int)(NanoSecs / 1000000));
+                Thread.Sleep(NsTimeConverter.GetTimeMs(Ns));
 
                 Process.Scheduler.Resume(CurrThread);
             }
@@ -103,14 +103,14 @@ namespace Ryujinx.Core.OsHle.Kernel
 
         private void SvcSetThreadPriority(AThreadState ThreadState)
         {
-            int Prio   = (int)ThreadState.X0;
-            int Handle = (int)ThreadState.X1;
+            int Handle   = (int)ThreadState.X0;
+            int Priority = (int)ThreadState.X1;
 
             KThread CurrThread = Process.HandleTable.GetData<KThread>(Handle);
 
             if (CurrThread != null)
             {
-                CurrThread.Priority = Prio;
+                CurrThread.Priority = Priority;
 
                 ThreadState.X0 = 0;
             }

+ 8 - 4
Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs

@@ -55,10 +55,10 @@ namespace Ryujinx.Core.OsHle.Kernel
 
         private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState)
         {
-            long MutexAddress   = (long)ThreadState.X0;
-            long CondVarAddress = (long)ThreadState.X1;
-            int  ThreadHandle   =  (int)ThreadState.X2;
-            long Timeout        = (long)ThreadState.X3;
+            long  MutexAddress   = (long)ThreadState.X0;
+            long  CondVarAddress = (long)ThreadState.X1;
+            int   ThreadHandle   =  (int)ThreadState.X2;
+            ulong Timeout        =       ThreadState.X3;
 
             KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
 
@@ -69,6 +69,8 @@ namespace Ryujinx.Core.OsHle.Kernel
                 ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
             }
 
+            Process.Scheduler.Suspend(Thread.ProcessorId);
+
             MutualExclusion Mutex = GetMutex(MutexAddress);
 
             Mutex.Unlock();
@@ -82,6 +84,8 @@ namespace Ryujinx.Core.OsHle.Kernel
 
             Mutex.WaitForLock(Thread);
 
+            Process.Scheduler.Resume(Thread);
+
             ThreadState.X0 = 0;
         }