| 390 | } |
| 391 | |
| 392 | error_code sys_event_queue_receive(ppu_thread &ppu, u32 equeue_id, |
| 393 | vm::ptr<sys_event_t> dummy_event, |
| 394 | u64 timeout) { |
| 395 | ppu.state += cpu_flag::wait; |
| 396 | |
| 397 | sys_event.trace( |
| 398 | "sys_event_queue_receive(equeue_id=0x%x, *0x%x, timeout=0x%llx)", |
| 399 | equeue_id, dummy_event, timeout); |
| 400 | |
| 401 | ppu.gpr[3] = CELL_OK; |
| 402 | |
| 403 | const auto queue = idm::get<lv2_obj, lv2_event_queue>( |
| 404 | equeue_id, |
| 405 | [&, |
| 406 | notify = lv2_obj::notify_all_t()](lv2_event_queue &queue) -> CellError { |
| 407 | if (queue.type != SYS_PPU_QUEUE) { |
| 408 | return CELL_EINVAL; |
| 409 | } |
| 410 | |
| 411 | lv2_obj::prepare_for_sleep(ppu); |
| 412 | |
| 413 | std::lock_guard lock(queue.mutex); |
| 414 | |
| 415 | // "/dev_flash/vsh/module/msmw2.sprx" seems to rely on some cryptic |
| 416 | // shared memory behaviour that we don't emulate correctly |
| 417 | // This is a hack to avoid waiting for 1m40s every time we boot vsh |
| 418 | if (queue.key == 0x8005911000000012 && Emu.IsVsh()) { |
| 419 | sys_event.todo("sys_event_queue_receive(equeue_id=0x%x, *0x%x, " |
| 420 | "timeout=0x%llx) Bypassing timeout for msmw2.sprx", |
| 421 | equeue_id, dummy_event, timeout); |
| 422 | timeout = 1; |
| 423 | } |
| 424 | |
| 425 | if (queue.events.empty()) { |
| 426 | queue.sleep(ppu, timeout); |
| 427 | lv2_obj::emplace(queue.pq, &ppu); |
| 428 | return CELL_EBUSY; |
| 429 | } |
| 430 | |
| 431 | std::tie(ppu.gpr[4], ppu.gpr[5], ppu.gpr[6], ppu.gpr[7]) = |
| 432 | queue.events.front(); |
| 433 | queue.events.pop_front(); |
| 434 | return {}; |
| 435 | }); |
| 436 | |
| 437 | if (!queue) { |
| 438 | return CELL_ESRCH; |
| 439 | } |
| 440 | |
| 441 | if (queue.ret) { |
| 442 | if (queue.ret != CELL_EBUSY) { |
| 443 | return queue.ret; |
| 444 | } |
| 445 | } else { |
| 446 | return CELL_OK; |
| 447 | } |
| 448 | |
| 449 | // If cancelled, gpr[3] will be non-zero. Other registers must contain event |
no test coverage detected