int sys_event_queue_receive(u32 equeue_id, mem_ptr_t<sys_event_data> event, u64 timeout) { sys_event.Warning("sys_event_queue_receive(equeue_id=%d, event_addr=0x%x, timeout=%lld)", equeue_id, event.GetAddr(), timeout); if (!event.IsGood()) { return CELL_EFAULT; } EventQueue* eq; if (!Emu.GetIdManager().GetIDData(equeue_id, eq)) { return CELL_ESRCH; } if (eq->type != SYS_PPU_QUEUE) { return CELL_EINVAL; } u32 tid = GetCurrentPPUThread().GetId(); eq->push(tid); // add thread to sleep queue timeout = timeout ? (timeout / 1000) : ~0; u64 counter = 0; while (true) { switch (eq->owner.trylock(tid)) { case SMR_OK: if (!eq->events.count()) { eq->owner.unlock(tid); break; } else { u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->pop() : eq->pop_prio(); if (next != tid) { eq->owner.unlock(tid, next); break; } } case SMR_SIGNAL: { eq->events.pop(*(sys_event_data*)(Memory + event)); eq->owner.unlock(tid); return CELL_OK; } case SMR_FAILED: break; default: eq->invalidate(tid); return CELL_ECANCELED; } Sleep(1); if (counter++ > timeout || Emu.IsStopped()) { if (Emu.IsStopped()) ConLog.Warning("sys_event_queue_receive(equeue=%d) aborted", equeue_id); eq->invalidate(tid); return CELL_ETIMEDOUT; } } /* auto queue_receive = [&](int status) -> bool { if(status == CPUThread_Stopped) { result = CELL_ECANCELED; return false; } EventQueue* equeue; if (!Emu.GetIdManager().GetIDData(equeue_id, equeue)) { result = CELL_ESRCH; return false; } for(int i=0; i<equeue->pos; ++i) { if(!equeue->ports[i]->has_data && equeue->ports[i]->thread) { SPUThread* thr = (SPUThread*)equeue->ports[i]->thread; if(thr->SPU.OutIntr_Mbox.GetCount()) { u32 val; thr->SPU.OutIntr_Mbox.Pop(val); if(!thr->SPU.Out_MBox.Pop(val)) val = 0; equeue->ports[i]->data1 = val; equeue->ports[i]->data2 = 0; equeue->ports[i]->data3 = 0; equeue->ports[i]->has_data = true; } } } for(int i=0; i<equeue->pos; i++) { if(equeue->ports[i]->has_data) { event->source = equeue->ports[i]->name; event->data1 = equeue->ports[i]->data1; event->data2 = equeue->ports[i]->data2; event->data3 = equeue->ports[i]->data3; equeue->ports[i]->has_data = false; result = CELL_OK; return false; } } return true; }; GetCurrentPPUThread().WaitFor(queue_receive);*/ }