Beispiel #1
0
        private void InsertWaitingMutexThreadUnsafe(KThread OwnerThread, KThread WaitThread)
        {
            WaitThread.MutexOwner = OwnerThread;

            if (!OwnerThread.MutexWaiters.Contains(WaitThread))
            {
                OwnerThread.MutexWaiters.Add(WaitThread);

                OwnerThread.UpdatePriority();
            }
        }
Beispiel #2
0
        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);
                }
            }
        }
Beispiel #3
0
        private void InsertWaitingMutexThread(KThread OwnerThread, KThread WaitThread)
        {
            lock (Process.ThreadSyncLock)
            {
                WaitThread.MutexOwner = OwnerThread;

                if (!OwnerThread.MutexWaiters.Contains(WaitThread))
                {
                    OwnerThread.MutexWaiters.Add(WaitThread);

                    OwnerThread.UpdatePriority();
                }
            }
        }
Beispiel #4
0
        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();
        }
Beispiel #5
0
        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!");
                }
            }
        }
Beispiel #6
0
        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!");
                }
            }
        }
Beispiel #7
0
        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;
                }
            }
        }