public virtual int sceKernelUnlockMutex(int uid, int count) { SceKernelMutexInfo info = mutexMap[uid]; if (info == null) { Console.WriteLine("sceKernelUnlockMutex unknown uid"); return(ERROR_KERNEL_MUTEX_NOT_FOUND); } if (info.lockedCount == 0) { // log only as debug to avoid warning spams on some games Console.WriteLine("sceKernelUnlockMutex not locked"); return(ERROR_KERNEL_MUTEX_UNLOCKED); } if ((info.lockedCount - count) < 0) { Console.WriteLine("sceKernelUnlockMutex underflow"); return(ERROR_KERNEL_MUTEX_UNLOCK_UNDERFLOW); } info.lockedCount -= count; if (info.lockedCount == 0) { info.threadid = -1; onMutexModified(info); } return(0); }
public virtual int sceKernelCancelMutex(int uid, int newcount, TPointer32 numWaitThreadAddr) { SceKernelMutexInfo info = mutexMap[uid]; if (info == null) { Console.WriteLine("sceKernelCancelMutex unknown UID " + uid.ToString("x")); return(ERROR_KERNEL_MUTEX_NOT_FOUND); } if (info.lockedCount == 0) { Console.WriteLine("sceKernelCancelMutex UID " + uid.ToString("x") + " not locked"); return(-1); } if (newcount < 0) { newcount = info.initCount; } if (newcount > 1 && (info.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0) { Console.WriteLine(string.Format("sceKernelCancelMutex uid={0:D}, newcount={1:D} - illegal count", uid, newcount)); return(SceKernelErrors.ERROR_KERNEL_ILLEGAL_COUNT); } // Write previous numWaitThreads count. numWaitThreadAddr.setValue(info.NumWaitingThreads); info.threadWaitingList.removeAllWaitingThreads(); // Set new count. info.lockedCount = newcount; onMutexCancelled(uid); return(0); }
/// <summary> /// Don't call this unless thread.waitType == PSP_WAIT_MUTEX </summary> /// <returns> true if the thread was waiting on a valid mutex </returns> private bool removeWaitingThread(SceKernelThreadInfo thread) { SceKernelMutexInfo info = mutexMap[thread.wait.Mutex_id]; if (info == null) { return(false); } info.threadWaitingList.removeWaitingThread(thread); return(true); }
public virtual int sceKernelCreateMutex(PspString name, int attr, int count, int option_addr) { if (count < 0 || (count > 1 && (attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0)) { return(SceKernelErrors.ERROR_KERNEL_ILLEGAL_COUNT); } SceKernelMutexInfo info = new SceKernelMutexInfo(name.String, count, attr); mutexMap[info.uid] = info; return(info.uid); }
public virtual int sceKernelReferMutexStatus(int uid, TPointer addr) { SceKernelMutexInfo info = mutexMap[uid]; if (info == null) { Console.WriteLine("sceKernelReferMutexStatus unknown UID " + uid.ToString("x")); return(ERROR_KERNEL_MUTEX_NOT_FOUND); } info.write(addr); return(0); }
public virtual int sceKernelDeleteMutex(int uid) { SceKernelMutexInfo info = mutexMap.Remove(uid); if (info == null) { Console.WriteLine("sceKernelDeleteMutex unknown UID " + uid.ToString("x")); return(ERROR_KERNEL_MUTEX_NOT_FOUND); } onMutexDeleted(uid); return(0); }
public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait) { // Check if the thread has to continue its wait state or if the mutex // has been unlocked during the callback execution. SceKernelMutexInfo info = outerInstance.mutexMap[wait.Mutex_id]; if (info == null) { thread.cpuContext._v0 = ERROR_KERNEL_MUTEX_NOT_FOUND; return(false); } // Check the mutex. if (outerInstance.tryLockMutex(info, wait.Mutex_count, thread)) { info.threadWaitingList.removeWaitingThread(thread); thread.cpuContext._v0 = 0; return(false); } return(true); }
private bool tryLockMutex(SceKernelMutexInfo info, int count, SceKernelThreadInfo thread) { if (info.lockedCount == 0) { // If the mutex is not locked, allow this thread to lock it. info.threadid = thread.uid; info.lockedCount += count; return(true); } else if (info.threadid == thread.uid) { // If the mutex is already locked, but it's trying to be locked by the same thread // that acquired it initially, check if recursive locking is allowed. // If not, return an error. if (((info.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == PSP_MUTEX_ATTR_ALLOW_RECURSIVE)) { info.lockedCount += count; return(true); } } return(false); }
private void onMutexModified(SceKernelMutexInfo info) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; SceKernelThreadInfo checkedThread = null; while (true) { SceKernelThreadInfo thread = info.threadWaitingList.getNextWaitingThread(checkedThread); if (thread == null) { break; } if (tryLockMutex(info, thread.wait.Mutex_count, thread)) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("onMutexModified waking thread {0}", thread)); } info.threadWaitingList.removeWaitingThread(thread); thread.cpuContext._v0 = 0; threadMan.hleChangeThreadState(thread, PSP_THREAD_READY); reschedule = true; } else { checkedThread = thread; } } // Reschedule only if threads waked up. if (reschedule) { Modules.ThreadManForUserModule.hleRescheduleCurrentThread(); } }
private int hleKernelLockMutex(int uid, int count, int timeout_addr, bool wait, bool doCallbacks) { SceKernelMutexInfo info = mutexMap[uid]; if (info == null) { //JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET: //ORIGINAL LINE: Console.WriteLine(String.format("hleKernelLockMutex uid=%d, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - unknown UID", uid, count, timeout_addr, wait, doCallbacks)); Console.WriteLine(string.Format("hleKernelLockMutex uid=%d, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - unknown UID", uid, count, timeout_addr, wait, doCallbacks)); return(ERROR_KERNEL_MUTEX_NOT_FOUND); } if (count <= 0) { //JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET: //ORIGINAL LINE: Console.WriteLine(String.format("hleKernelLockMutex uid=%d, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - illegal count", uid, count, timeout_addr, wait, doCallbacks)); Console.WriteLine(string.Format("hleKernelLockMutex uid=%d, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - illegal count", uid, count, timeout_addr, wait, doCallbacks)); return(SceKernelErrors.ERROR_KERNEL_ILLEGAL_COUNT); } if (count > 1 && (info.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0) { //JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET: //ORIGINAL LINE: Console.WriteLine(String.format("hleKernelLockMutex uid=%d, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - illegal count", uid, count, timeout_addr, wait, doCallbacks)); Console.WriteLine(string.Format("hleKernelLockMutex uid=%d, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - illegal count", uid, count, timeout_addr, wait, doCallbacks)); return(SceKernelErrors.ERROR_KERNEL_ILLEGAL_COUNT); } ThreadManForUser threadMan = Modules.ThreadManForUserModule; SceKernelThreadInfo currentThread = threadMan.CurrentThread; if (!tryLockMutex(info, count, currentThread)) { //if (log.DebugEnabled) { //JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET: //ORIGINAL LINE: Console.WriteLine(String.format("hleKernelLockMutex %s, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - fast check failed", info.toString(), count, timeout_addr, wait, doCallbacks)); Console.WriteLine(string.Format("hleKernelLockMutex %s, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - fast check failed", info.ToString(), count, timeout_addr, wait, doCallbacks)); } if (wait && info.threadid != currentThread.uid) { // Failed, but it's ok, just wait a little info.threadWaitingList.addWaitingThread(currentThread); // Wait on a specific mutex currentThread.wait.Mutex_id = uid; currentThread.wait.Mutex_count = count; threadMan.hleKernelThreadEnterWaitState(PSP_WAIT_MUTEX, uid, mutexWaitStateChecker, timeout_addr, doCallbacks); } else { if ((info.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) != PSP_MUTEX_ATTR_ALLOW_RECURSIVE) { return(ERROR_KERNEL_MUTEX_RECURSIVE_NOT_ALLOWED); } return(ERROR_KERNEL_MUTEX_LOCKED); } } else { // Success, do not reschedule the current thread. //if (log.DebugEnabled) { //JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET: //ORIGINAL LINE: Console.WriteLine(String.format("hleKernelLockMutex %s, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - fast check succeeded", info.toString(), count, timeout_addr, wait, doCallbacks)); Console.WriteLine(string.Format("hleKernelLockMutex %s, count=%d, timeout_addr=0x%08X, wait=%b, doCallbacks=%b - fast check succeeded", info.ToString(), count, timeout_addr, wait, doCallbacks)); } } return(0); }