int sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) { u32 error; Mbx *m = kernelObjects.Get<Mbx>(id, error); if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMbxCB(%i, %08x, %08x): invalid mbx id", id, packetAddrPtr, timeoutPtr); return error; } if (m->nmb.numMessages > 0) { DEBUG_LOG(HLE, "sceKernelReceiveMbxCB(%i, %08x, %08x): sending first queue message", id, packetAddrPtr, timeoutPtr); hleCheckCurrentCallbacks(); return m->ReceiveMessage(packetAddrPtr); } else { DEBUG_LOG(HLE, "sceKernelReceiveMbxCB(%i, %08x, %08x): no message in queue, waiting", id, packetAddrPtr, timeoutPtr); __KernelMbxRemoveThread(m, __KernelGetCurThread()); m->AddWaitingThread(__KernelGetCurThread(), packetAddrPtr); __KernelWaitMbx(m, timeoutPtr); __KernelWaitCurThread(WAITTYPE_MBX, id, 0, timeoutPtr, true); return 0; } }
int sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) { u32 error; Mbx *m = kernelObjects.Get<Mbx>(id, error); if (!m) { ERROR_LOG(SCEKERNEL, "sceKernelReceiveMbx(%i, %08x, %08x): invalid mbx id", id, packetAddrPtr, timeoutPtr); return error; } if (m->nmb.numMessages > 0) { DEBUG_LOG(SCEKERNEL, "sceKernelReceiveMbx(%i, %08x, %08x): sending first queue message", id, packetAddrPtr, timeoutPtr); return m->ReceiveMessage(packetAddrPtr); } else { DEBUG_LOG(SCEKERNEL, "sceKernelReceiveMbx(%i, %08x, %08x): no message in queue, waiting", id, packetAddrPtr, timeoutPtr); HLEKernel::RemoveWaitingThread(m->waitingThreads, __KernelGetCurThread()); m->AddWaitingThread(__KernelGetCurThread(), packetAddrPtr); __KernelWaitMbx(m, timeoutPtr); __KernelWaitCurThread(WAITTYPE_MBX, id, 0, timeoutPtr, false, "mbx waited"); return 0; } }
void sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) { u32 error; Mbx *m = kernelObjects.Get<Mbx>(id, error); __KernelCheckCallbacks(); if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMbxCB(%i, %08x, %08x): invalid mbx id", id, packetAddrPtr, timeoutPtr); RETURN(error); return; } if (!m->messageQueue.empty()) { DEBUG_LOG(HLE, "sceKernelReceiveMbxCB(%i, %08x, %08x): sending first queue message", id, packetAddrPtr, timeoutPtr); Memory::Write_U32(m->messageQueue.front(), packetAddrPtr); m->messageQueue.erase(m->messageQueue.begin()); RETURN(0); } else { DEBUG_LOG(HLE, "sceKernelReceiveMbxCB(%i, %08x, %08x): no message in queue, waiting", id, packetAddrPtr, timeoutPtr); m->AddWaitingThread(id, packetAddrPtr); RETURN(0); __KernelWaitCurThread(WAITTYPE_MBX, 0, 0, 0, true); // ? } }
int sceKernelPollMbx(SceUID id, u32 packetAddrPtr) { u32 error; Mbx *m = kernelObjects.Get<Mbx>(id, error); if (!m) { ERROR_LOG(HLE, "sceKernelPollMbx(%i, %08x): invalid mbx id", id, packetAddrPtr); return error; } if (m->nmb.numMessages > 0) { DEBUG_LOG(HLE, "sceKernelPollMbx(%i, %08x): sending first queue message", id, packetAddrPtr); return m->ReceiveMessage(packetAddrPtr); } else { DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_MBOX_NOMSG=sceKernelPollMbx(%i, %08x): no message in queue", id, packetAddrPtr); return SCE_KERNEL_ERROR_MBOX_NOMSG; } }
int sceKernelSendMbx(SceUID id, u32 packetAddr) { u32 error; Mbx *m = kernelObjects.Get<Mbx>(id, error); if (!m) { ERROR_LOG(HLE, "sceKernelSendMbx(%i, %08x): invalid mbx id", id, packetAddr); return error; } NativeMbxPacket *addPacket = (NativeMbxPacket*)Memory::GetPointer(packetAddr); if (addPacket == 0) { ERROR_LOG(HLE, "sceKernelSendMbx(%i, %08x): invalid packet address", id, packetAddr); return -1; } // If the queue is empty, maybe someone is waiting. // We have to check them first, they might've timed out. if (m->nmb.numMessages == 0) { bool wokeThreads = false; std::vector<MbxWaitingThread>::iterator iter; while (!wokeThreads && !m->waitingThreads.empty()) { if ((m->nmb.attr & SCE_KERNEL_MBA_THPRI) != 0) iter = __KernelMbxFindPriority(m->waitingThreads); else iter = m->waitingThreads.begin(); MbxWaitingThread t = *iter; __KernelUnlockMbxForThread(m, t, error, 0, wokeThreads); m->waitingThreads.erase(iter); if (wokeThreads) { DEBUG_LOG(HLE, "sceKernelSendMbx(%i, %08x): threads waiting, resuming %d", id, packetAddr, t.first); Memory::Write_U32(packetAddr, t.second); hleReSchedule("mbx sent"); // We don't need to do anything else, finish here. return 0; } } } DEBUG_LOG(HLE, "sceKernelSendMbx(%i, %08x): no threads currently waiting, adding message to queue", id, packetAddr); if (m->nmb.numMessages == 0) m->AddInitialMessage(packetAddr); else { u32 next = m->nmb.packetListHead, prev; for (int i = 0, n = m->nmb.numMessages; i < n; i++) { if (next == packetAddr) return PSP_MBX_ERROR_DUPLICATE_MSG; if (!Memory::IsValidAddress(next)) return SCE_KERNEL_ERROR_ILLEGAL_ADDR; prev = next; next = Memory::Read_U32(next); } bool inserted = false; if (m->nmb.attr & SCE_KERNEL_MBA_MSPRI) { NativeMbxPacket p; for (int i = 0, n = m->nmb.numMessages; i < n; i++) { Memory::ReadStruct<NativeMbxPacket>(next, &p); if (addPacket->priority < p.priority) { if (i == 0) m->AddFirstMessage(prev, packetAddr); else m->AddMessage(prev, next, packetAddr); inserted = true; break; } prev = next; next = Memory::Read_U32(next); } } if (!inserted) m->AddLastMessage(prev, packetAddr); } return 0; }