protected internal virtual int hleUmdWaitDriveStat(int wantedStat, bool doCallbacks, bool doTimeout, int timeout) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; if (!checkDriveStat(wantedStat)) { SceKernelThreadInfo currentThread = threadMan.CurrentThread; // Wait on a specific umdStat. currentThread.wait.wantedUmdStat = wantedStat; waitingThreads.Add(currentThread); threadMan.hleKernelThreadEnterWaitState(currentThread, JPCSP_WAIT_UMD, -1, umdWaitStateChecker, timeout, !doTimeout, doCallbacks); } threadMan.hleRescheduleCurrentThread(doCallbacks); return(0); }
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 bool tryReceiveMsgPipe(SceKernelMppInfo info, TPointer addr, int size, int waitMode, TPointer32 resultSizeAddr) { if (size > 0) { int availableSize = info.availableReadSize(); if (availableSize == 0) { return(false); } // Trying to receive more than available? if (size > availableSize) { // Do we need to receive the complete size? if (waitMode == PSP_MPP_WAIT_MODE_COMPLETE) { return(false); } // We can just receive the available size. size = availableSize; } info.consume(addr.Memory, addr.Address, size); if (info.bufSize == 0 && info.availableReadSize() == 0 && info.NumSendWaitThreads > 0) { SceKernelThreadInfo thread = info.sendThreadWaitingList.FirstWaitingThread; if (thread.wait.MsgPipe_isSend) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("tryReceiveMsgPipe waking thread {0}", thread)); } ThreadManForUser threadMan = Modules.ThreadManForUserModule; info.sendThreadWaitingList.removeWaitingThread(thread); thread.cpuContext._v0 = 0; threadMan.hleChangeThreadState(thread, PSP_THREAD_READY); threadMan.hleRescheduleCurrentThread(); } } } resultSizeAddr.setValue(size); return(true); }
private void onFplFree(SceKernelFplInfo info) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; SceKernelThreadInfo checkedThread = null; while (info.freeBlocks > 0) { SceKernelThreadInfo thread = info.threadWaitingList.getNextWaitingThread(checkedThread); if (thread == null) { break; } int addr = tryAllocateFpl(info); if (addr != 0) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("onFplFree waking thread {0}", thread)); } // Return the allocated address thread.wait.Fpl_dataAddr.setValue(addr); 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) { threadMan.hleRescheduleCurrentThread(); } }
private void onMbxDeletedCancelled(int mbxid, int result) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; for (IEnumerator <SceKernelThreadInfo> it = threadMan.GetEnumerator(); it.MoveNext();) { SceKernelThreadInfo thread = it.Current; if (thread.isWaitingFor(PSP_WAIT_MBX, mbxid)) { thread.cpuContext._v0 = result; threadMan.hleChangeThreadState(thread, PSP_THREAD_READY); reschedule = true; } } // Reschedule only if threads waked up. if (reschedule) { threadMan.hleRescheduleCurrentThread(); } }
private void onLwMutexDeleted(int lwmid) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; for (IEnumerator <SceKernelThreadInfo> it = threadMan.GetEnumerator(); it.MoveNext();) { SceKernelThreadInfo thread = it.Current; if (thread.isWaitingFor(PSP_WAIT_LWMUTEX, lwmid)) { thread.cpuContext._v0 = ERROR_KERNEL_WAIT_DELETE; threadMan.hleChangeThreadState(thread, PSP_THREAD_READY); reschedule = true; } } // Reschedule only if threads waked up. if (reschedule) { threadMan.hleRescheduleCurrentThread(); } }
private void onMsgPipeReceiveModified(SceKernelMppInfo info) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; SceKernelThreadInfo checkedThread = null; while (true) { SceKernelThreadInfo thread = info.receiveThreadWaitingList.getNextWaitingThread(checkedThread); if (thread == null) { break; } if (!thread.wait.MsgPipe_isSend && tryReceiveMsgPipe(info, thread.wait.MsgPipe_address, thread.wait.MsgPipe_size, thread.wait.MsgPipe_waitMode, thread.wait.MsgPipe_resultSize_addr)) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("onMsgPipeReceiveModified waking thread {0}", thread)); } info.receiveThreadWaitingList.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) { threadMan.hleRescheduleCurrentThread(); } }
private void onSemaphoreModified(SceKernelSemaInfo sema) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; SceKernelThreadInfo checkedThread = null; while (sema.currentCount > 0) { SceKernelThreadInfo thread = sema.threadWaitingList.getNextWaitingThread(checkedThread); if (thread == null) { break; } if (tryWaitSemaphore(sema, thread.wait.Semaphore_signal)) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("onSemaphoreModified waking thread {0}", thread)); } sema.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) { threadMan.hleRescheduleCurrentThread(); } }
private void onEventFlagModified(SceKernelEventFlagInfo @event) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; SceKernelThreadInfo checkedThread = null; while (@event.currentPattern != 0) { SceKernelThreadInfo thread = @event.threadWaitingList.getNextWaitingThread(checkedThread); if (thread == null) { break; } if (checkEventFlag(@event, thread.wait.EventFlag_bits, thread.wait.EventFlag_wait, thread.wait.EventFlag_outBits_addr)) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("onEventFlagModified waking thread {0}", thread)); } @event.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) { threadMan.hleRescheduleCurrentThread(); } }