Beispiel #1
0
        private (long, KThread) MutexUnlock(KThread currentThread, long mutexAddress)
        {
            KThread newOwnerThread = currentThread.RelinquishMutex(mutexAddress, out int count);

            int mutexValue = 0;

            if (newOwnerThread != null)
            {
                mutexValue = newOwnerThread.ThreadHandleForUserMutex;

                if (count >= 2)
                {
                    mutexValue |= HasListenersMask;
                }

                newOwnerThread.SignaledObj   = null;
                newOwnerThread.ObjSyncResult = 0;

                newOwnerThread.ReleaseAndResume();
            }

            long result = 0;

            if (!KernelTransfer.KernelToUserInt32(_system, mutexAddress, mutexValue))
            {
                result = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
            }

            return(result, newOwnerThread);
        }
Beispiel #2
0
        private (long, KThread) MutexUnlock(KThread CurrentThread, long MutexAddress)
        {
            KThread NewOwnerThread = CurrentThread.RelinquishMutex(MutexAddress, out int Count);

            int MutexValue = 0;

            if (NewOwnerThread != null)
            {
                MutexValue = NewOwnerThread.ThreadHandleForUserMutex;

                if (Count >= 2)
                {
                    MutexValue |= HasListenersMask;
                }

                NewOwnerThread.SignaledObj   = null;
                NewOwnerThread.ObjSyncResult = 0;

                NewOwnerThread.ReleaseAndResume();
            }

            long Result = 0;

            if (!KernelTransfer.KernelToUserInt32(System, MutexAddress, MutexValue))
            {
                Result = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
            }

            return(Result, NewOwnerThread);
        }
Beispiel #3
0
        public long ArbitrateLock(int OwnerHandle, long MutexAddress, int RequesterHandle)
        {
            KThread CurrentThread = System.Scheduler.GetCurrentThread();

            System.CriticalSection.Enter();

            CurrentThread.SignaledObj   = null;
            CurrentThread.ObjSyncResult = 0;

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

            if (!KernelTransfer.UserToKernelInt32(System, MutexAddress, out int MutexValue))
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));;
            }

            if (MutexValue != (OwnerHandle | HasListenersMask))
            {
                System.CriticalSection.Leave();

                return(0);
            }

            KThread MutexOwner = CurrentProcess.HandleTable.GetObject <KThread>(OwnerHandle);

            if (MutexOwner == null)
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle));
            }

            CurrentThread.MutexAddress             = MutexAddress;
            CurrentThread.ThreadHandleForUserMutex = RequesterHandle;

            MutexOwner.AddMutexWaiter(CurrentThread);

            CurrentThread.Reschedule(ThreadSchedState.Paused);

            System.CriticalSection.Leave();
            System.CriticalSection.Enter();

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

            System.CriticalSection.Leave();

            return((uint)CurrentThread.ObjSyncResult);
        }
Beispiel #4
0
        public long ArbitrateLock(int ownerHandle, long mutexAddress, int requesterHandle)
        {
            KThread currentThread = _system.Scheduler.GetCurrentThread();

            _system.CriticalSection.Enter();

            currentThread.SignaledObj   = null;
            currentThread.ObjSyncResult = 0;

            KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

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

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

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

                return(0);
            }

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

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

                return(MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle));
            }

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

            mutexOwner.AddMutexWaiter(currentThread);

            currentThread.Reschedule(ThreadSchedState.Paused);

            _system.CriticalSection.Leave();
            _system.CriticalSection.Enter();

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

            _system.CriticalSection.Leave();

            return((uint)currentThread.ObjSyncResult);
        }
Beispiel #5
0
        private KernelResult GetProcessList(ulong address, int maxCount, out int count)
        {
            count = 0;

            if ((maxCount >> 28) != 0)
            {
                return(KernelResult.MaximumExceeded);
            }

            if (maxCount != 0)
            {
                KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

                ulong copySize = (ulong)maxCount * 8;

                if (address + copySize <= address)
                {
                    return(KernelResult.InvalidMemState);
                }

                if (currentProcess.MemoryManager.OutsideAddrSpace(address, copySize))
                {
                    return(KernelResult.InvalidMemState);
                }
            }

            int copyCount = 0;

            lock (_system.Processes)
            {
                foreach (KProcess process in _system.Processes.Values)
                {
                    if (copyCount < maxCount)
                    {
                        if (!KernelTransfer.KernelToUserInt64(_system, (long)address + copyCount * 8, process.Pid))
                        {
                            return(KernelResult.UserCopyFailed);
                        }
                    }

                    copyCount++;
                }
            }

            count = copyCount;

            return(KernelResult.Success);
        }
Beispiel #6
0
        private KernelResult GetProcessList(ulong Address, int MaxCount, out int Count)
        {
            Count = 0;

            if ((MaxCount >> 28) != 0)
            {
                return(KernelResult.MaximumExceeded);
            }

            if (MaxCount != 0)
            {
                KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

                ulong CopySize = (ulong)MaxCount * 8;

                if (Address + CopySize <= Address)
                {
                    return(KernelResult.InvalidMemState);
                }

                if (CurrentProcess.MemoryManager.OutsideAddrSpace(Address, CopySize))
                {
                    return(KernelResult.InvalidMemState);
                }
            }

            int CopyCount = 0;

            lock (System.Processes)
            {
                foreach (KProcess Process in System.Processes.Values)
                {
                    if (CopyCount < MaxCount)
                    {
                        if (!KernelTransfer.KernelToUserInt64(System, (long)Address + CopyCount * 8, Process.Pid))
                        {
                            return(KernelResult.UserCopyFailed);
                        }
                    }

                    CopyCount++;
                }
            }

            Count = CopyCount;

            return(KernelResult.Success);
        }
Beispiel #7
0
        public long SignalAndIncrementIfEqual(long Address, int Value, int Count)
        {
            System.CriticalSection.Enter();

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

            CurrentProcess.CpuMemory.SetExclusive(0, Address);

            if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

            while (CurrentValue == Value)
            {
                if (CurrentProcess.CpuMemory.TestExclusive(0, Address))
                {
                    CurrentProcess.CpuMemory.WriteInt32(Address, CurrentValue + 1);

                    CurrentProcess.CpuMemory.ClearExclusiveForStore(0);

                    break;
                }

                CurrentProcess.CpuMemory.SetExclusive(0, Address);

                CurrentValue = CurrentProcess.CpuMemory.ReadInt32(Address);
            }

            CurrentProcess.CpuMemory.ClearExclusive(0);

            if (CurrentValue != Value)
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState));
            }

            WakeArbiterThreads(Address, Count);

            System.CriticalSection.Leave();

            return(0);
        }
Beispiel #8
0
        public long SignalAndIncrementIfEqual(long address, int value, int count)
        {
            _system.CriticalSection.Enter();

            KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

            currentProcess.CpuMemory.SetExclusive(0, address);

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

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

            while (currentValue == value)
            {
                if (currentProcess.CpuMemory.TestExclusive(0, address))
                {
                    currentProcess.CpuMemory.WriteInt32(address, currentValue + 1);

                    currentProcess.CpuMemory.ClearExclusiveForStore(0);

                    break;
                }

                currentProcess.CpuMemory.SetExclusive(0, address);

                currentValue = currentProcess.CpuMemory.ReadInt32(address);
            }

            currentProcess.CpuMemory.ClearExclusive(0);

            if (currentValue != value)
            {
                _system.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState));
            }

            WakeArbiterThreads(address, count);

            _system.CriticalSection.Leave();

            return(0);
        }
Beispiel #9
0
        private KernelResult ManageNamedPort(long nameAddress, int maxSessions, out int handle)
        {
            handle = 0;

            if (!KernelTransfer.UserToKernelString(_system, nameAddress, 12, out string name))
            {
                return(KernelResult.UserCopyFailed);
            }

            if (maxSessions < 0 || name.Length > 11)
            {
                return(KernelResult.MaximumExceeded);
            }

            if (maxSessions == 0)
            {
                return(KClientPort.RemoveName(_system, name));
            }

            KPort port = new KPort(_system);

            KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

            KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out handle);

            if (result != KernelResult.Success)
            {
                return(result);
            }

            port.Initialize(maxSessions, false, 0);

            result = port.SetName(name);

            if (result != KernelResult.Success)
            {
                currentProcess.HandleTable.CloseHandle(handle);
            }

            return(result);
        }
Beispiel #10
0
        private KernelResult ManageNamedPort(long NameAddress, int MaxSessions, out int Handle)
        {
            Handle = 0;

            if (!KernelTransfer.UserToKernelString(System, NameAddress, 12, out string Name))
            {
                return(KernelResult.UserCopyFailed);
            }

            if (MaxSessions < 0 || Name.Length > 11)
            {
                return(KernelResult.MaximumExceeded);
            }

            if (MaxSessions == 0)
            {
                return(KClientPort.RemoveName(System, Name));
            }

            KPort Port = new KPort(System);

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

            KernelResult Result = CurrentProcess.HandleTable.GenerateHandle(Port.ServerPort, out Handle);

            if (Result != KernelResult.Success)
            {
                return(Result);
            }

            Port.Initialize(MaxSessions, false, 0);

            Result = Port.SetName(Name);

            if (Result != KernelResult.Success)
            {
                CurrentProcess.HandleTable.CloseHandle(Handle);
            }

            return(Result);
        }
Beispiel #11
0
        public long SignalAndModifyIfEqual(long Address, int Value, int Count)
        {
            System.CriticalSection.Enter();

            int Offset;

            //The value is decremented if the number of threads waiting is less
            //or equal to the Count of threads to be signaled, or Count is zero
            //or negative. It is incremented if there are no threads waiting.
            int WaitingCount = 0;

            foreach (KThread Thread in ArbiterThreads.Where(x => x.MutexAddress == Address))
            {
                if (++WaitingCount > Count)
                {
                    break;
                }
            }

            if (WaitingCount > 0)
            {
                Offset = WaitingCount <= Count || Count <= 0 ? -1 : 0;
            }
            else
            {
                Offset = 1;
            }

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

            CurrentProcess.CpuMemory.SetExclusive(0, Address);

            if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

            while (CurrentValue == Value)
            {
                if (CurrentProcess.CpuMemory.TestExclusive(0, Address))
                {
                    CurrentProcess.CpuMemory.WriteInt32(Address, CurrentValue + Offset);

                    CurrentProcess.CpuMemory.ClearExclusiveForStore(0);

                    break;
                }

                CurrentProcess.CpuMemory.SetExclusive(0, Address);

                CurrentValue = CurrentProcess.CpuMemory.ReadInt32(Address);
            }

            CurrentProcess.CpuMemory.ClearExclusive(0);

            if (CurrentValue != Value)
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState));
            }

            WakeArbiterThreads(Address, Count);

            System.CriticalSection.Leave();

            return(0);
        }
Beispiel #12
0
        public long WaitForAddressIfLessThan(long 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(MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating));
            }

            CurrentThread.SignaledObj   = null;
            CurrentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

            //If ShouldDecrement is true, do atomic decrement of the value at Address.
            CurrentProcess.CpuMemory.SetExclusive(0, Address);

            if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

            if (ShouldDecrement)
            {
                while (CurrentValue < Value)
                {
                    if (CurrentProcess.CpuMemory.TestExclusive(0, Address))
                    {
                        CurrentProcess.CpuMemory.WriteInt32(Address, CurrentValue - 1);

                        CurrentProcess.CpuMemory.ClearExclusiveForStore(0);

                        break;
                    }

                    CurrentProcess.CpuMemory.SetExclusive(0, Address);

                    CurrentValue = CurrentProcess.CpuMemory.ReadInt32(Address);
                }
            }

            CurrentProcess.CpuMemory.ClearExclusive(0);

            if (CurrentValue < Value)
            {
                if (Timeout == 0)
                {
                    System.CriticalSection.Leave();

                    return(MakeError(ErrorModule.Kernel, KernelErr.Timeout));
                }

                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(CurrentThread.ObjSyncResult);
            }

            System.CriticalSection.Leave();

            return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState));
        }
Beispiel #13
0
        public long WaitForAddressIfEqual(long Address, int Value, long Timeout)
        {
            KThread CurrentThread = System.Scheduler.GetCurrentThread();

            System.CriticalSection.Enter();

            if (CurrentThread.ShallBeTerminated ||
                CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating));
            }

            CurrentThread.SignaledObj   = null;
            CurrentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);

            if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

            if (CurrentValue == Value)
            {
                if (Timeout == 0)
                {
                    System.CriticalSection.Leave();

                    return(MakeError(ErrorModule.Kernel, KernelErr.Timeout));
                }

                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(CurrentThread.ObjSyncResult);
            }

            System.CriticalSection.Leave();

            return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState));
        }
Beispiel #14
0
        private KThread TryAcquireMutex(KThread Requester)
        {
            long Address = Requester.MutexAddress;

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

            CurrentProcess.CpuMemory.SetExclusive(0, Address);

            if (!KernelTransfer.UserToKernelInt32(System, Address, out int MutexValue))
            {
                //Invalid address.
                CurrentProcess.CpuMemory.ClearExclusive(0);

                Requester.SignaledObj   = null;
                Requester.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);

                return(null);
            }

            while (true)
            {
                if (CurrentProcess.CpuMemory.TestExclusive(0, Address))
                {
                    if (MutexValue != 0)
                    {
                        //Update value to indicate there is a mutex waiter now.
                        CurrentProcess.CpuMemory.WriteInt32(Address, MutexValue | HasListenersMask);
                    }
                    else
                    {
                        //No thread owning the mutex, assign to requesting thread.
                        CurrentProcess.CpuMemory.WriteInt32(Address, Requester.ThreadHandleForUserMutex);
                    }

                    CurrentProcess.CpuMemory.ClearExclusiveForStore(0);

                    break;
                }

                CurrentProcess.CpuMemory.SetExclusive(0, Address);

                MutexValue = CurrentProcess.CpuMemory.ReadInt32(Address);
            }

            if (MutexValue == 0)
            {
                //We now own the mutex.
                Requester.SignaledObj   = null;
                Requester.ObjSyncResult = 0;

                Requester.ReleaseAndResume();

                return(null);
            }

            MutexValue &= ~HasListenersMask;

            KThread MutexOwner = CurrentProcess.HandleTable.GetObject <KThread>(MutexValue);

            if (MutexOwner != null)
            {
                //Mutex already belongs to another thread, wait for it.
                MutexOwner.AddMutexWaiter(Requester);
            }
            else
            {
                //Invalid mutex owner.
                Requester.SignaledObj   = null;
                Requester.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);

                Requester.ReleaseAndResume();
            }

            return(MutexOwner);
        }
Beispiel #15
0
        public long SignalAndModifyIfEqual(long address, int value, int count)
        {
            _system.CriticalSection.Enter();

            int offset;

            //The value is decremented if the number of threads waiting is less
            //or equal to the Count of threads to be signaled, or Count is zero
            //or negative. It is incremented if there are no threads waiting.
            int waitingCount = 0;

            foreach (KThread thread in ArbiterThreads.Where(x => x.MutexAddress == address))
            {
                if (++waitingCount > count)
                {
                    break;
                }
            }

            if (waitingCount > 0)
            {
                offset = waitingCount <= count || count <= 0 ? -1 : 0;
            }
            else
            {
                offset = 1;
            }

            KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

            currentProcess.CpuMemory.SetExclusive(0, address);

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

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

            while (currentValue == value)
            {
                if (currentProcess.CpuMemory.TestExclusive(0, address))
                {
                    currentProcess.CpuMemory.WriteInt32(address, currentValue + offset);

                    currentProcess.CpuMemory.ClearExclusiveForStore(0);

                    break;
                }

                currentProcess.CpuMemory.SetExclusive(0, address);

                currentValue = currentProcess.CpuMemory.ReadInt32(address);
            }

            currentProcess.CpuMemory.ClearExclusive(0);

            if (currentValue != value)
            {
                _system.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState));
            }

            WakeArbiterThreads(address, count);

            _system.CriticalSection.Leave();

            return(0);
        }