private void InsertWaitingMutexThreadUnsafe(KThread OwnerThread, KThread WaitThread) { WaitThread.MutexOwner = OwnerThread; if (!OwnerThread.MutexWaiters.Contains(WaitThread)) { OwnerThread.MutexWaiters.Add(WaitThread); OwnerThread.UpdatePriority(); } }
private bool MutexUnlock(KThread CurrThread, long MutexAddress) { if (CurrThread == null) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex 0x{MutexAddress:x16}!"); return(false); } lock (CurrThread) { //This is the new thread that will not own the mutex. //If no threads are waiting for the lock, then it should be null. KThread OwnerThread = CurrThread.NextMutexThread; while (OwnerThread != null && OwnerThread.MutexAddress != MutexAddress) { OwnerThread = OwnerThread.NextMutexThread; } UpdateMutexOwner(CurrThread, OwnerThread, MutexAddress); CurrThread.NextMutexThread = null; CurrThread.UpdatePriority(); if (OwnerThread != null) { int HasListeners = OwnerThread.NextMutexThread != null ? 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); return(true); } else { Process.Memory.WriteInt32(MutexAddress, 0); return(false); } } }
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 void InsertWaitingMutexThread(int OwnerThreadHandle, KThread WaitThread) { KThread OwnerThread = Process.HandleTable.GetData <KThread>(OwnerThreadHandle); if (OwnerThread == null) { Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{OwnerThreadHandle:x8}!"); return; } WaitThread.MutexOwner = OwnerThread; lock (OwnerThread) { KThread CurrThread = OwnerThread; while (CurrThread.NextMutexThread != null) { if (CurrThread == WaitThread) { return; } if (CurrThread.NextMutexThread.ActualPriority < WaitThread.ActualPriority) { break; } CurrThread = CurrThread.NextMutexThread; } if (CurrThread != WaitThread) { if (WaitThread.NextCondVarThread != null) { throw new InvalidOperationException(); } WaitThread.NextMutexThread = CurrThread.NextMutexThread; CurrThread.NextMutexThread = WaitThread; } } OwnerThread.UpdatePriority(); }
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, int Count) = PopMutexThreadUnsafe(CurrThread, MutexAddress); if (OwnerThread == CurrThread) { throw new InvalidOperationException(); } if (OwnerThread != null) { //Remove all waiting mutex from the old owner, //and insert then on the new owner. UpdateMutexOwnerUnsafe(CurrThread, OwnerThread, MutexAddress); CurrThread.UpdatePriority(); int HasListeners = Count >= 2 ? MutexHasListenersMask : 0; Memory.WriteInt32ToSharedAddr(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 { Memory.WriteInt32ToSharedAddr(MutexAddress, 0); Ns.Log.PrintDebug(LogClass.KernelSvc, "No threads waiting mutex!"); } } }
private void MutexUnlock(KThread CurrThread, long MutexAddress) { lock (Process.ThreadSyncLock) { //This is the new thread that will not 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 void CondVarSignal(long CondVarAddress, int Count) { lock (CondVarLock) { KThread PrevThread = null; KThread CurrThread = Process.ThreadArbiterList; while (CurrThread != null && (Count == -1 || Count > 0)) { if (CurrThread.CondVarAddress == CondVarAddress) { if (PrevThread != null) { PrevThread.NextCondVarThread = CurrThread.NextCondVarThread; } else { Process.ThreadArbiterList = CurrThread.NextCondVarThread; } CurrThread.NextCondVarThread = null; AcquireMutexValue(CurrThread.MutexAddress); int MutexValue = Process.Memory.ReadInt32(CurrThread.MutexAddress); MutexValue &= ~MutexHasListenersMask; if (MutexValue == 0) { //Give the lock to this thread. Process.Memory.WriteInt32(CurrThread.MutexAddress, CurrThread.WaitHandle); CurrThread.WaitHandle = 0; CurrThread.MutexAddress = 0; CurrThread.CondVarAddress = 0; CurrThread.MutexOwner = null; CurrThread.UpdatePriority(); Process.Scheduler.WakeUp(CurrThread); } else { //Wait until the lock is released. InsertWaitingMutexThread(MutexValue, CurrThread); MutexValue |= MutexHasListenersMask; Process.Memory.WriteInt32(CurrThread.MutexAddress, MutexValue); } ReleaseMutexValue(CurrThread.MutexAddress); Count--; } PrevThread = CurrThread; CurrThread = CurrThread.NextCondVarThread; } } }