public long ArbitrateLock( Process Process, AMemory Memory, int OwnerHandle, long MutexAddress, int RequesterHandle) { System.CriticalSectionLock.Lock(); KThread CurrentThread = System.Scheduler.GetCurrentThread(); CurrentThread.SignaledObj = null; CurrentThread.ObjSyncResult = 0; if (!UserToKernelInt32(Memory, MutexAddress, out int MutexValue)) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));; } if (MutexValue != (OwnerHandle | HasListenersMask)) { System.CriticalSectionLock.Unlock(); return(0); } KThread MutexOwner = Process.HandleTable.GetObject <KThread>(OwnerHandle); if (MutexOwner == null) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle)); } CurrentThread.MutexAddress = MutexAddress; CurrentThread.ThreadHandleForUserMutex = RequesterHandle; MutexOwner.AddMutexWaiter(CurrentThread); CurrentThread.Reschedule(ThreadSchedState.Paused); System.CriticalSectionLock.Unlock(); System.CriticalSectionLock.Lock(); if (CurrentThread.MutexOwner != null) { CurrentThread.MutexOwner.RemoveMutexWaiter(CurrentThread); } System.CriticalSectionLock.Unlock(); 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 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); }
private KThread TryAcquireMutex(Process Process, AMemory Memory, KThread Requester) { int Core = Requester.CurrentCore; long Address = Requester.MutexAddress; Memory.SetExclusive(Core, Address); int MutexValue = Memory.ReadInt32(Address); while (MutexValue != 0) { if (Memory.TestExclusive(Core, Address)) { if (MutexValue != 0) { //Update value to indicate there is a mutex waiter now. Memory.WriteInt32(Address, MutexValue | HasListenersMask); } else { //No thread owning the mutex, assign to requesting thread. Memory.WriteInt32(Address, Requester.ThreadHandleForUserMutex); } Memory.ClearExclusiveForStore(Core); break; } Memory.SetExclusive(Core, Address); MutexValue = Memory.ReadInt32(Address); } if (MutexValue == 0) { //We now own the mutex. Requester.SignaledObj = null; Requester.ObjSyncResult = 0; Requester.ReleaseAndResume(); return(null); } MutexValue &= ~HasListenersMask; KThread MutexOwner = Process.HandleTable.GetData <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); }