private (KernelResult, KThread) MutexUnlock(KThread currentThread, ulong 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 = KernelResult.Success; newOwnerThread.ReleaseAndResume(); } KernelResult result = KernelResult.Success; if (!KernelTransfer.KernelToUserInt32(_context, mutexAddress, mutexValue)) { result = KernelResult.InvalidMemState; } return(result, newOwnerThread); }
private (int, KThread) MutexUnlock(KThread currentThread, ulong 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 = KernelResult.Success; newOwnerThread.ReleaseAndResume(); } return(mutexValue, newOwnerThread); }
private KThread TryAcquireMutex(KThread requester) { ulong address = requester.MutexAddress; KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); int mutexValue, newMutexValue; do { if (!KernelTransfer.UserToKernelInt32(_system, address, out mutexValue)) { // Invalid address. requester.SignaledObj = null; requester.ObjSyncResult = KernelResult.InvalidMemState; return(null); } if (mutexValue != 0) { // Update value to indicate there is a mutex waiter now. newMutexValue = mutexValue | HasListenersMask; } else { // No thread owning the mutex, assign to requesting thread. newMutexValue = requester.ThreadHandleForUserMutex; } }while (!currentProcess.CpuMemory.AtomicCompareExchangeInt32((long)address, mutexValue, newMutexValue)); if (mutexValue == 0) { // We now own the mutex. requester.SignaledObj = null; requester.ObjSyncResult = KernelResult.Success; 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 = KernelResult.InvalidHandle; requester.ReleaseAndResume(); } return(mutexOwner); }
private KThread TryAcquireMutex(KThread requester) { ulong address = requester.MutexAddress; KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); currentProcess.CpuMemory.SetExclusive(0, (long)address); if (!KernelTransfer.UserToKernelInt32(_system, address, out int mutexValue)) { //Invalid address. currentProcess.CpuMemory.ClearExclusive(0); requester.SignaledObj = null; requester.ObjSyncResult = KernelResult.InvalidMemState; return(null); } while (true) { if (currentProcess.CpuMemory.TestExclusive(0, (long)address)) { if (mutexValue != 0) { //Update value to indicate there is a mutex waiter now. currentProcess.CpuMemory.WriteInt32((long)address, mutexValue | HasListenersMask); } else { //No thread owning the mutex, assign to requesting thread. currentProcess.CpuMemory.WriteInt32((long)address, requester.ThreadHandleForUserMutex); } currentProcess.CpuMemory.ClearExclusiveForStore(0); break; } currentProcess.CpuMemory.SetExclusive(0, (long)address); mutexValue = currentProcess.CpuMemory.ReadInt32((long)address); } if (mutexValue == 0) { //We now own the mutex. requester.SignaledObj = null; requester.ObjSyncResult = KernelResult.Success; 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 = KernelResult.InvalidHandle; requester.ReleaseAndResume(); } return(mutexOwner); }