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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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)); }
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)); }
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); }
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); }