diff options
Diffstat (limited to 'Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs')
| -rw-r--r-- | Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs | 435 |
1 files changed, 0 insertions, 435 deletions
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs deleted file mode 100644 index 12bc657a..00000000 --- a/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs +++ /dev/null @@ -1,435 +0,0 @@ -using ChocolArm64.State; -using Ryujinx.Core.Logging; -using Ryujinx.Core.OsHle.Handles; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; - -using static Ryujinx.Core.OsHle.ErrorCode; - -namespace Ryujinx.Core.OsHle.Kernel -{ - partial class SvcHandler - { - private const int MutexHasListenersMask = 0x40000000; - - private void SvcArbitrateLock(AThreadState ThreadState) - { - int OwnerThreadHandle = (int)ThreadState.X0; - long MutexAddress = (long)ThreadState.X1; - int WaitThreadHandle = (int)ThreadState.X2; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "OwnerThreadHandle = " + OwnerThreadHandle.ToString("x8") + ", " + - "MutexAddress = " + MutexAddress .ToString("x16") + ", " + - "WaitThreadHandle = " + WaitThreadHandle .ToString("x8")); - - if (IsPointingInsideKernel(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (IsWordAddressUnaligned(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAlignment); - - return; - } - - KThread OwnerThread = Process.HandleTable.GetData<KThread>(OwnerThreadHandle); - - if (OwnerThread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid owner thread handle 0x{OwnerThreadHandle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - KThread WaitThread = Process.HandleTable.GetData<KThread>(WaitThreadHandle); - - if (WaitThread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid requesting thread handle 0x{WaitThreadHandle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - - MutexLock(CurrThread, WaitThread, OwnerThreadHandle, WaitThreadHandle, MutexAddress); - - ThreadState.X0 = 0; - } - - private void SvcArbitrateUnlock(AThreadState ThreadState) - { - long MutexAddress = (long)ThreadState.X0; - - Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexAddress = " + MutexAddress.ToString("x16")); - - if (IsPointingInsideKernel(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (IsWordAddressUnaligned(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAlignment); - - return; - } - - MutexUnlock(Process.GetThread(ThreadState.Tpidr), MutexAddress); - - ThreadState.X0 = 0; - } - - private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState) - { - long MutexAddress = (long)ThreadState.X0; - long CondVarAddress = (long)ThreadState.X1; - int ThreadHandle = (int)ThreadState.X2; - ulong Timeout = ThreadState.X3; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "MutexAddress = " + MutexAddress .ToString("x16") + ", " + - "CondVarAddress = " + CondVarAddress.ToString("x16") + ", " + - "ThreadHandle = " + ThreadHandle .ToString("x8") + ", " + - "Timeout = " + Timeout .ToString("x16")); - - if (IsPointingInsideKernel(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (IsWordAddressUnaligned(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAlignment); - - return; - } - - KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle); - - if (Thread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - - MutexUnlock(CurrThread, MutexAddress); - - if (!CondVarWait(CurrThread, ThreadHandle, MutexAddress, CondVarAddress, Timeout)) - { - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout); - - return; - } - - ThreadState.X0 = 0; - } - - private void SvcSignalProcessWideKey(AThreadState ThreadState) - { - long CondVarAddress = (long)ThreadState.X0; - int Count = (int)ThreadState.X1; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "CondVarAddress = " + CondVarAddress.ToString("x16") + ", " + - "Count = " + Count .ToString("x8")); - - KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - - CondVarSignal(CurrThread, CondVarAddress, Count); - - ThreadState.X0 = 0; - } - - private void MutexLock( - KThread CurrThread, - KThread WaitThread, - int OwnerThreadHandle, - int WaitThreadHandle, - long MutexAddress) - { - lock (Process.ThreadSyncLock) - { - int MutexValue = Process.Memory.ReadInt32(MutexAddress); - - Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8")); - - if (MutexValue != (OwnerThreadHandle | MutexHasListenersMask)) - { - return; - } - - CurrThread.WaitHandle = WaitThreadHandle; - CurrThread.MutexAddress = MutexAddress; - - InsertWaitingMutexThread(OwnerThreadHandle, WaitThread); - } - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Entering wait state..."); - - Process.Scheduler.EnterWait(CurrThread); - } - - private void MutexUnlock(KThread CurrThread, long MutexAddress) - { - lock (Process.ThreadSyncLock) - { - //This is the new thread that will now own the mutex. - //If no threads are waiting for the lock, then it should be null. - KThread OwnerThread = PopThread(CurrThread.MutexWaiters, x => x.MutexAddress == MutexAddress); - - if (OwnerThread != null) - { - //Remove all waiting mutex from the old owner, - //and insert then on the new owner. - UpdateMutexOwner(CurrThread, OwnerThread, MutexAddress); - - CurrThread.UpdatePriority(); - - int HasListeners = OwnerThread.MutexWaiters.Count > 0 ? MutexHasListenersMask : 0; - - Process.Memory.WriteInt32(MutexAddress, HasListeners | OwnerThread.WaitHandle); - - OwnerThread.WaitHandle = 0; - OwnerThread.MutexAddress = 0; - OwnerThread.CondVarAddress = 0; - - OwnerThread.MutexOwner = null; - - OwnerThread.UpdatePriority(); - - Process.Scheduler.WakeUp(OwnerThread); - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Gave mutex to thread id " + OwnerThread.ThreadId + "!"); - } - else - { - Process.Memory.WriteInt32(MutexAddress, 0); - - Ns.Log.PrintDebug(LogClass.KernelSvc, "No threads waiting mutex!"); - } - } - } - - private bool CondVarWait( - KThread WaitThread, - int WaitThreadHandle, - long MutexAddress, - long CondVarAddress, - ulong Timeout) - { - WaitThread.WaitHandle = WaitThreadHandle; - WaitThread.MutexAddress = MutexAddress; - WaitThread.CondVarAddress = CondVarAddress; - - lock (Process.ThreadSyncLock) - { - WaitThread.CondVarSignaled = false; - - Process.ThreadArbiterList.Add(WaitThread); - } - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Entering wait state..."); - - if (Timeout != ulong.MaxValue) - { - Process.Scheduler.EnterWait(WaitThread, NsTimeConverter.GetTimeMs(Timeout)); - - lock (Process.ThreadSyncLock) - { - WaitThread.MutexOwner?.MutexWaiters.Remove(WaitThread); - - if (!WaitThread.CondVarSignaled || WaitThread.MutexOwner != null) - { - WaitThread.MutexOwner = null; - - Process.ThreadArbiterList.Remove(WaitThread); - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Timed out..."); - - return false; - } - } - } - else - { - Process.Scheduler.EnterWait(WaitThread); - } - - return true; - } - - private void CondVarSignal(KThread CurrThread, long CondVarAddress, int Count) - { - lock (Process.ThreadSyncLock) - { - while (Count == -1 || Count-- > 0) - { - KThread WaitThread = PopThread(Process.ThreadArbiterList, x => x.CondVarAddress == CondVarAddress); - - if (WaitThread == null) - { - Ns.Log.PrintDebug(LogClass.KernelSvc, "No more threads to wake up!"); - - break; - } - - WaitThread.CondVarSignaled = true; - - AcquireMutexValue(WaitThread.MutexAddress); - - int MutexValue = Process.Memory.ReadInt32(WaitThread.MutexAddress); - - Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8")); - - if (MutexValue == 0) - { - //Give the lock to this thread. - Process.Memory.WriteInt32(WaitThread.MutexAddress, WaitThread.WaitHandle); - - WaitThread.WaitHandle = 0; - WaitThread.MutexAddress = 0; - WaitThread.CondVarAddress = 0; - - WaitThread.MutexOwner?.UpdatePriority(); - - WaitThread.MutexOwner = null; - - Process.Scheduler.WakeUp(WaitThread); - } - else - { - //Wait until the lock is released. - MutexValue &= ~MutexHasListenersMask; - - InsertWaitingMutexThread(MutexValue, WaitThread); - - MutexValue |= MutexHasListenersMask; - - Process.Memory.WriteInt32(WaitThread.MutexAddress, MutexValue); - } - - ReleaseMutexValue(WaitThread.MutexAddress); - } - } - } - - private void UpdateMutexOwner(KThread CurrThread, KThread NewOwner, long MutexAddress) - { - //Go through all threads waiting for the mutex, - //and update the MutexOwner field to point to the new owner. - lock (Process.ThreadSyncLock) - { - for (int Index = 0; Index < CurrThread.MutexWaiters.Count; Index++) - { - KThread Thread = CurrThread.MutexWaiters[Index]; - - if (Thread.MutexAddress == MutexAddress) - { - CurrThread.MutexWaiters.RemoveAt(Index--); - - Thread.MutexOwner = NewOwner; - - InsertWaitingMutexThread(NewOwner, Thread); - } - } - } - } - - private void InsertWaitingMutexThread(int OwnerThreadHandle, KThread WaitThread) - { - KThread OwnerThread = Process.HandleTable.GetData<KThread>(OwnerThreadHandle); - - if (OwnerThread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{OwnerThreadHandle:x8}!"); - - return; - } - - InsertWaitingMutexThread(OwnerThread, WaitThread); - } - - private void InsertWaitingMutexThread(KThread OwnerThread, KThread WaitThread) - { - lock (Process.ThreadSyncLock) - { - WaitThread.MutexOwner = OwnerThread; - - if (!OwnerThread.MutexWaiters.Contains(WaitThread)) - { - OwnerThread.MutexWaiters.Add(WaitThread); - - OwnerThread.UpdatePriority(); - } - } - } - - private KThread PopThread(List<KThread> Threads, Func<KThread, bool> Predicate) - { - KThread Thread = Threads.OrderBy(x => x.ActualPriority).FirstOrDefault(Predicate); - - if (Thread != null) - { - Threads.Remove(Thread); - } - - return Thread; - } - - private void AcquireMutexValue(long MutexAddress) - { - while (!Process.Memory.AcquireAddress(MutexAddress)) - { - Thread.Yield(); - } - } - - private void ReleaseMutexValue(long MutexAddress) - { - Process.Memory.ReleaseAddress(MutexAddress); - } - - private bool IsPointingInsideKernel(long Address) - { - return ((ulong)Address + 0x1000000000) < 0xffffff000; - } - - private bool IsWordAddressUnaligned(long Address) - { - return (Address & 3) != 0; - } - } -}
\ No newline at end of file |
