Example #1
0
        public void SignalObject(KSynchronizationObject syncObj)
        {
            _system.CriticalSection.Enter();

            if (syncObj.IsSignaled())
            {
                LinkedListNode <KThread> node = syncObj.WaitingThreads.First;

                while (node != null)
                {
                    KThread thread = node.Value;

                    if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
                    {
                        thread.SignaledObj   = syncObj;
                        thread.ObjSyncResult = KernelResult.Success;

                        thread.Reschedule(ThreadSchedState.Running);
                    }

                    node = node.Next;
                }
            }

            _system.CriticalSection.Leave();
        }
Example #2
0
        public static void Wait(KernelContext context, LinkedList <KThread> threadList, object mutex, long timeout)
        {
            KThread currentThread = context.Scheduler.GetCurrentThread();

            context.CriticalSection.Enter();

            Monitor.Exit(mutex);

            currentThread.Withholder = threadList;

            currentThread.Reschedule(ThreadSchedState.Paused);

            currentThread.WithholderNode = threadList.AddLast(currentThread);

            if (currentThread.ShallBeTerminated ||
                currentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                threadList.Remove(currentThread.WithholderNode);

                currentThread.Reschedule(ThreadSchedState.Running);

                currentThread.Withholder = null;

                context.CriticalSection.Leave();
            }
            else
            {
                if (timeout > 0)
                {
                    context.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
                }

                context.CriticalSection.Leave();

                if (timeout > 0)
                {
                    context.TimeManager.UnscheduleFutureInvocation(currentThread);
                }
            }

            Monitor.Enter(mutex);
        }
Example #3
0
        public KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle)
        {
            KThread currentThread = KernelStatic.GetCurrentThread();

            _context.CriticalSection.Enter();

            currentThread.SignaledObj   = null;
            currentThread.ObjSyncResult = KernelResult.Success;

            KProcess currentProcess = KernelStatic.GetCurrentProcess();

            if (!KernelTransfer.UserToKernelInt32(_context, mutexAddress, out int mutexValue))
            {
                _context.CriticalSection.Leave();

                return(KernelResult.InvalidMemState);
            }

            if (mutexValue != (ownerHandle | HasListenersMask))
            {
                _context.CriticalSection.Leave();

                return(0);
            }

            KThread mutexOwner = currentProcess.HandleTable.GetObject <KThread>(ownerHandle);

            if (mutexOwner == null)
            {
                _context.CriticalSection.Leave();

                return(KernelResult.InvalidHandle);
            }

            currentThread.MutexAddress             = mutexAddress;
            currentThread.ThreadHandleForUserMutex = requesterHandle;

            mutexOwner.AddMutexWaiter(currentThread);

            currentThread.Reschedule(ThreadSchedState.Paused);

            _context.CriticalSection.Leave();
            _context.CriticalSection.Enter();

            if (currentThread.MutexOwner != null)
            {
                currentThread.MutexOwner.RemoveMutexWaiter(currentThread);
            }

            _context.CriticalSection.Leave();

            return(currentThread.ObjSyncResult);
        }
Example #4
0
        public static void NotifyAll(KernelContext context, LinkedList <KThread> threadList)
        {
            context.CriticalSection.Enter();

            LinkedListNode <KThread> node = threadList.First;

            for (; node != null; node = threadList.First)
            {
                KThread thread = node.Value;

                threadList.Remove(thread.WithholderNode);

                thread.Withholder = null;

                thread.Reschedule(ThreadSchedState.Running);
            }

            context.CriticalSection.Leave();
        }
Example #5
0
        public KernelResult WaitProcessWideKeyAtomic(
            ulong mutexAddress,
            ulong condVarAddress,
            int threadHandle,
            long timeout)
        {
            _context.CriticalSection.Enter();

            KThread currentThread = KernelStatic.GetCurrentThread();

            currentThread.SignaledObj   = null;
            currentThread.ObjSyncResult = KernelResult.TimedOut;

            if (currentThread.ShallBeTerminated ||
                currentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                _context.CriticalSection.Leave();

                return(KernelResult.ThreadTerminating);
            }

            (KernelResult result, _) = MutexUnlock(currentThread, mutexAddress);

            if (result != KernelResult.Success)
            {
                _context.CriticalSection.Leave();

                return(result);
            }

            currentThread.MutexAddress             = mutexAddress;
            currentThread.ThreadHandleForUserMutex = threadHandle;
            currentThread.CondVarAddress           = condVarAddress;

            _condVarThreads.Add(currentThread);

            if (timeout != 0)
            {
                currentThread.Reschedule(ThreadSchedState.Paused);

                if (timeout > 0)
                {
                    _context.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
                }
            }

            _context.CriticalSection.Leave();

            if (timeout > 0)
            {
                _context.TimeManager.UnscheduleFutureInvocation(currentThread);
            }

            _context.CriticalSection.Enter();

            if (currentThread.MutexOwner != null)
            {
                currentThread.MutexOwner.RemoveMutexWaiter(currentThread);
            }

            _condVarThreads.Remove(currentThread);

            _context.CriticalSection.Leave();

            return(currentThread.ObjSyncResult);
        }
Example #6
0
        public KernelResult WaitFor(KSynchronizationObject[] syncObjs, long timeout, out int handleIndex)
        {
            handleIndex = 0;

            KernelResult result = KernelResult.TimedOut;

            _system.CriticalSection.Enter();

            //Check if objects are already signaled before waiting.
            for (int index = 0; index < syncObjs.Length; index++)
            {
                if (!syncObjs[index].IsSignaled())
                {
                    continue;
                }

                handleIndex = index;

                _system.CriticalSection.Leave();

                return(0);
            }

            if (timeout == 0)
            {
                _system.CriticalSection.Leave();

                return(result);
            }

            KThread currentThread = _system.Scheduler.GetCurrentThread();

            if (currentThread.ShallBeTerminated ||
                currentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                result = KernelResult.ThreadTerminating;
            }
            else if (currentThread.SyncCancelled)
            {
                currentThread.SyncCancelled = false;

                result = KernelResult.Cancelled;
            }
            else
            {
                LinkedListNode <KThread>[] syncNodes = new LinkedListNode <KThread> [syncObjs.Length];

                for (int index = 0; index < syncObjs.Length; index++)
                {
                    syncNodes[index] = syncObjs[index].AddWaitingThread(currentThread);
                }

                currentThread.WaitingSync   = true;
                currentThread.SignaledObj   = null;
                currentThread.ObjSyncResult = result;

                currentThread.Reschedule(ThreadSchedState.Paused);

                if (timeout > 0)
                {
                    _system.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
                }

                _system.CriticalSection.Leave();

                currentThread.WaitingSync = false;

                if (timeout > 0)
                {
                    _system.TimeManager.UnscheduleFutureInvocation(currentThread);
                }

                _system.CriticalSection.Enter();

                result = currentThread.ObjSyncResult;

                handleIndex = -1;

                for (int index = 0; index < syncObjs.Length; index++)
                {
                    syncObjs[index].RemoveWaitingThread(syncNodes[index]);

                    if (syncObjs[index] == currentThread.SignaledObj)
                    {
                        handleIndex = index;
                    }
                }
            }

            _system.CriticalSection.Leave();

            return(result);
        }
Example #7
0
        public KernelResult WaitForAddressIfLessThan(
            ulong address,
            int value,
            bool shouldDecrement,
            long timeout)
        {
            KThread currentThread = _system.Scheduler.GetCurrentThread();

            _system.CriticalSection.Enter();

            if (currentThread.ShallBeTerminated ||
                currentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                _system.CriticalSection.Leave();

                return(KernelResult.ThreadTerminating);
            }

            currentThread.SignaledObj   = null;
            currentThread.ObjSyncResult = KernelResult.TimedOut;

            KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

            if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue))
            {
                _system.CriticalSection.Leave();

                return(KernelResult.InvalidMemState);
            }

            if (shouldDecrement)
            {
                currentValue = currentProcess.CpuMemory.AtomicDecrementInt32((long)address) + 1;
            }

            if (currentValue < value)
            {
                if (timeout == 0)
                {
                    _system.CriticalSection.Leave();

                    return(KernelResult.TimedOut);
                }

                currentThread.MutexAddress         = address;
                currentThread.WaitingInArbitration = true;

                InsertSortedByPriority(ArbiterThreads, currentThread);

                currentThread.Reschedule(ThreadSchedState.Paused);

                if (timeout > 0)
                {
                    _system.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
                }

                _system.CriticalSection.Leave();

                if (timeout > 0)
                {
                    _system.TimeManager.UnscheduleFutureInvocation(currentThread);
                }

                _system.CriticalSection.Enter();

                if (currentThread.WaitingInArbitration)
                {
                    ArbiterThreads.Remove(currentThread);

                    currentThread.WaitingInArbitration = false;
                }

                _system.CriticalSection.Leave();

                return((KernelResult)currentThread.ObjSyncResult);
            }

            _system.CriticalSection.Leave();

            return(KernelResult.InvalidState);
        }