| 269 | } |
| 270 | |
| 271 | error_code sys_lwcond_wait(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u64 timeout) |
| 272 | { |
| 273 | sysPrxForUser.trace("sys_lwcond_wait(lwcond=*0x%x, timeout=0x%llx)", lwcond, timeout); |
| 274 | |
| 275 | if (g_cfg.core.hle_lwmutex) |
| 276 | { |
| 277 | return sys_cond_wait(ppu, lwcond->lwcond_queue, timeout); |
| 278 | } |
| 279 | |
| 280 | auto& sstate = *ppu.optional_savestate_state; |
| 281 | const auto lwcond_ec = sstate.try_read<error_code>().second; |
| 282 | |
| 283 | const be_t<u32> tid(ppu.id); |
| 284 | |
| 285 | const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex; |
| 286 | |
| 287 | if (lwmutex->vars.owner.load() != tid) |
| 288 | { |
| 289 | // if not owner of the mutex |
| 290 | return CELL_EPERM; |
| 291 | } |
| 292 | |
| 293 | // save old recursive value |
| 294 | const be_t<u32> recursive_value = !lwcond_ec ? lwmutex->recursive_count : sstate.operator be_t<u32>(); |
| 295 | |
| 296 | // set special value |
| 297 | lwmutex->vars.owner = lwmutex_reserved; |
| 298 | lwmutex->recursive_count = 0; |
| 299 | |
| 300 | // call the syscall |
| 301 | const error_code res = !lwcond_ec ? _sys_lwcond_queue_wait(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, timeout) : lwcond_ec; |
| 302 | |
| 303 | static_cast<void>(ppu.test_stopped()); |
| 304 | |
| 305 | if (ppu.state & cpu_flag::again) |
| 306 | { |
| 307 | sstate.pos = 0; |
| 308 | sstate(error_code{}, recursive_value); // Not aborted on mutex sleep |
| 309 | return {}; |
| 310 | } |
| 311 | |
| 312 | if (res == CELL_OK || res + 0u == CELL_ESRCH) |
| 313 | { |
| 314 | if (res == CELL_OK) |
| 315 | { |
| 316 | lwmutex->all_info--; |
| 317 | } |
| 318 | |
| 319 | // restore owner and recursive value |
| 320 | const auto old = lwmutex->vars.owner.exchange(tid); |
| 321 | lwmutex->recursive_count = recursive_value; |
| 322 | |
| 323 | if (old == lwmutex_free || old == lwmutex_dead) |
| 324 | { |
| 325 | fmt::throw_exception("Locking failed (lwmutex=*0x%x, owner=0x%x)", lwmutex, old); |
| 326 | } |
| 327 | |
| 328 | return res; |
nothing calls this directly
no test coverage detected