public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait) { // Check if the thread has to continue its wait state or if the mbx // has received a new message during the callback execution. SceKernelMbxInfo info = outerInstance.mbxMap[wait.Mbx_id]; if (info == null) { thread.cpuContext._v0 = ERROR_KERNEL_NOT_FOUND_MESSAGE_BOX; return(false); } // Check the mbx for a new message. if (info.hasMessage()) { Memory mem = Memory.Instance; int msgAddr = info.removeMsg(mem); wait.Mbx_resultAddr.setValue(msgAddr); info.threadWaitingList.removeWaitingThread(thread); thread.cpuContext._v0 = 0; return(false); } return(true); }
public virtual int sceKernelSendMbx(int uid, TPointer msgAddr) { SceKernelMbxInfo info = mbxMap[uid]; bool msgConsumed = false; // If the Mbx is empty, check if some thread is already waiting. // If a thread is already waiting, do not update the msg "nextMsgPacketAddr" FieldInfo. if (!info.hasMessage()) { SceKernelThreadInfo thread = info.threadWaitingList.FirstWaitingThread; if (thread != null) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("sceKernelSendMbx waking thread {0}", thread)); } thread.wait.Mbx_resultAddr.setValue(msgAddr.Address); info.threadWaitingList.removeWaitingThread(thread); thread.cpuContext._v0 = 0; ThreadManForUser threadMan = Modules.ThreadManForUserModule; threadMan.hleChangeThreadState(thread, PSP_THREAD_READY); threadMan.hleRescheduleCurrentThread(); msgConsumed = true; } } // Add the message if it has not yet been consumed by a waiting thread if (!msgConsumed) { if ((info.attr & PSP_MBX_ATTR_MSG_PRIORITY) == PSP_MBX_ATTR_MSG_FIFO) { info.addMsg(msgAddr.Memory, msgAddr.Address); } else if ((info.attr & PSP_MBX_ATTR_MSG_PRIORITY) == PSP_MBX_ATTR_MSG_PRIORITY) { info.addMsgByPriority(msgAddr.Memory, msgAddr.Address); } } return(0); }
private int hleKernelReceiveMbx(int uid, TPointer32 addrMsgAddr, TPointer32 timeoutAddr, bool doCallbacks, bool poll) { SceKernelMbxInfo info = mbxMap[uid]; ThreadManForUser threadMan = Modules.ThreadManForUserModule; if (!info.hasMessage()) { if (!poll) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelReceiveMbx - {0} (waiting)", info)); } SceKernelThreadInfo currentThread = threadMan.CurrentThread; info.threadWaitingList.addWaitingThread(currentThread); currentThread.wait.Mbx_id = uid; currentThread.wait.Mbx_resultAddr = addrMsgAddr; threadMan.hleKernelThreadEnterWaitState(PSP_WAIT_MBX, uid, mbxWaitStateChecker, timeoutAddr.Address, doCallbacks); } else { //if (log.DebugEnabled) { Console.WriteLine("hleKernelReceiveMbx has no messages."); } return(ERROR_KERNEL_MESSAGEBOX_NO_MESSAGE); } } else { // Success, do not reschedule the current thread. //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelReceiveMbx - {0} fast check succeeded", info)); } int msgAddr = info.removeMsg(Memory.Instance); addrMsgAddr.setValue(msgAddr); } return(0); }