public virtual int sceKernelCreateLwMutex(TPointer workAreaAddr, string name, int attr, int count, TPointer option) { SceKernelLwMutexInfo info = new SceKernelLwMutexInfo(workAreaAddr, name, count, attr); lwMutexMap[info.uid] = info; // Return 0 in case of no error, do not return the UID of the created mutex return(0); }
private bool removeWaitingThread(SceKernelThreadInfo thread) { SceKernelLwMutexInfo info = lwMutexMap[thread.wait.LwMutex_id]; if (info == null) { return(false); } info.threadWaitingList.removeWaitingThread(thread); return(true); }
public virtual int sceKernelReferLwMutexStatusByID(int uid, TPointer addr) { SceKernelLwMutexInfo info = lwMutexMap[uid]; if (info == null) { Console.WriteLine("sceKernelReferLwMutexStatus unknown UID " + uid.ToString("x")); return(ERROR_KERNEL_LWMUTEX_NOT_FOUND); } info.write(addr); return(0); }
public virtual int sceKernelDeleteLwMutex(TPointer workAreaAddr) { int uid = workAreaAddr.getValue32(); SceKernelLwMutexInfo info = lwMutexMap.Remove(uid); if (info == null) { Console.WriteLine("sceKernelDeleteLwMutex unknown UID " + uid.ToString("x")); return(ERROR_KERNEL_LWMUTEX_NOT_FOUND); } workAreaAddr.setValue32(0); // Clear uid. onLwMutexDeleted(uid); return(0); }
public virtual int sceKernelUnlockLwMutex(TPointer workAreaAddr, int count) { int uid = workAreaAddr.getValue32(); SceKernelLwMutexInfo info = lwMutexMap[uid]; if (info == null) { if (uid == 0) { // Avoid spamming messages for uid==0 //if (log.DebugEnabled) { Console.WriteLine(string.Format("sceKernelUnlockLwMutex unknown uid=0x{0:X}", uid)); } } else { Console.WriteLine(string.Format("sceKernelUnlockLwMutex unknown uid=0x{0:X}", uid)); } return(ERROR_KERNEL_LWMUTEX_NOT_FOUND); } if (info.lockedCount == 0) { Console.WriteLine("sceKernelUnlockLwMutex not locked"); return(ERROR_KERNEL_LWMUTEX_UNLOCKED); } if (info.lockedCount < 0) { Console.WriteLine("sceKernelUnlockLwMutex underflow"); return(ERROR_KERNEL_LWMUTEX_UNLOCK_UNDERFLOW); } info.lockedCount -= count; if (info.lockedCount == 0) { info.threadid = -1; onLwMutexModified(info); } return(0); }
public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait) { // Check if the thread has to continue its wait state or if the lwmutex // has been unlocked during the callback execution. SceKernelLwMutexInfo info = outerInstance.lwMutexMap[wait.LwMutex_id]; if (info == null) { thread.cpuContext._v0 = ERROR_KERNEL_LWMUTEX_NOT_FOUND; return(false); } // Check the lwmutex. if (outerInstance.tryLockLwMutex(info, wait.LwMutex_count, thread)) { info.threadWaitingList.removeWaitingThread(thread); thread.cpuContext._v0 = 0; return(false); } return(true); }
private bool tryLockLwMutex(SceKernelLwMutexInfo info, int count, SceKernelThreadInfo thread) { if (info.lockedCount == 0) { // If the lwmutex 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 lwmutex 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_LWMUTEX_ATTR_ALLOW_RECURSIVE) == PSP_LWMUTEX_ATTR_ALLOW_RECURSIVE)) { info.lockedCount += count; return(true); } } return(false); }
private void onLwMutexModified(SceKernelLwMutexInfo info) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; SceKernelThreadInfo checkedThread = null; while (true) { SceKernelThreadInfo thread = info.threadWaitingList.getNextWaitingThread(checkedThread); if (thread == null) { break; } if (tryLockLwMutex(info, thread.wait.LwMutex_count, thread)) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("onLwMutexModified waking thread {0}", thread)); } // New thread is taking control of LwMutex. info.threadid = thread.uid; 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 hleKernelLockLwMutex(int uid, int count, TPointer32 timeoutAddr, bool wait, bool doCallbacks) { SceKernelLwMutexInfo info = lwMutexMap[uid]; if (info == null) { if (uid == 0) { // Avoid spamming messages for uid==0 //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("hleKernelLockLwMutex uid=%d, count=%d, timeout_addr=%s, wait=%b, doCallbacks=%b - - unknown UID", uid, count, timeoutAddr, wait, doCallbacks)); Console.WriteLine(string.Format("hleKernelLockLwMutex uid=%d, count=%d, timeout_addr=%s, wait=%b, doCallbacks=%b - - unknown UID", uid, count, timeoutAddr, wait, doCallbacks)); } } else { //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("hleKernelLockLwMutex uid=%d, count=%d, timeout_addr=%s, wait=%b, doCallbacks=%b - - unknown UID", uid, count, timeoutAddr, wait, doCallbacks)); Console.WriteLine(string.Format("hleKernelLockLwMutex uid=%d, count=%d, timeout_addr=%s, wait=%b, doCallbacks=%b - - unknown UID", uid, count, timeoutAddr, wait, doCallbacks)); } return(ERROR_KERNEL_LWMUTEX_NOT_FOUND); } ThreadManForUser threadMan = Modules.ThreadManForUserModule; SceKernelThreadInfo currentThread = threadMan.CurrentThread; if (!tryLockLwMutex(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("hleKernelLockLwMutex %s, count=%d, timeout_addr=%s, wait=%b, doCallbacks=%b - fast check failed", info.toString(), count, timeoutAddr, wait, doCallbacks)); Console.WriteLine(string.Format("hleKernelLockLwMutex %s, count=%d, timeout_addr=%s, wait=%b, doCallbacks=%b - fast check failed", info.ToString(), count, timeoutAddr, 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 lwmutex currentThread.wait.LwMutex_id = uid; currentThread.wait.LwMutex_count = count; threadMan.hleKernelThreadEnterWaitState(PSP_WAIT_LWMUTEX, uid, lwMutexWaitStateChecker, timeoutAddr.Address, doCallbacks); } else { if ((info.attr & PSP_LWMUTEX_ATTR_ALLOW_RECURSIVE) != PSP_LWMUTEX_ATTR_ALLOW_RECURSIVE) { return(ERROR_KERNEL_LWMUTEX_RECURSIVE_NOT_ALLOWED); } return(ERROR_KERNEL_LWMUTEX_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("hleKernelLockLwMutex %s, count=%d, timeout_addr=%s, wait=%b, doCallbacks=%b - fast check succeeded", info.toString(), count, timeoutAddr, wait, doCallbacks)); Console.WriteLine(string.Format("hleKernelLockLwMutex %s, count=%d, timeout_addr=%s, wait=%b, doCallbacks=%b - fast check succeeded", info.ToString(), count, timeoutAddr, wait, doCallbacks)); } } return(0); }