1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 18:53:28 +01:00

Update sys_lwmutex_lock and sys_lwmutex_unlock (liblv2 HLE)

Implement missing SYS_SYNC_RETRY logic
Following #5680
This commit is contained in:
Nekotekina 2019-03-06 15:09:50 +03:00
parent 986c750fdc
commit 4ea76def7c

View File

@ -85,7 +85,7 @@ error_code sys_lwmutex_destroy(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
}
// deleting succeeded
lwmutex->vars.owner.exchange(lwmutex_dead);
lwmutex->vars.owner.release(lwmutex_dead);
return CELL_OK;
}
@ -184,8 +184,57 @@ error_code sys_lwmutex_lock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex, u64
if (res == CELL_EBUSY && lwmutex->attribute & SYS_SYNC_RETRY)
{
// TODO (protocol is ignored in current implementation)
fmt::throw_exception("Unimplemented" HERE);
while (true)
{
for (u32 i = 0; i < 10; i++)
{
busy_wait();
if (lwmutex->vars.owner.load() == lwmutex_free)
{
if (lwmutex->vars.owner.compare_and_swap_test(lwmutex_free, tid))
{
return CELL_OK;
}
}
}
lwmutex->all_info++;
if (lwmutex->vars.owner.compare_and_swap_test(lwmutex_free, tid))
{
lwmutex->all_info--;
return CELL_OK;
}
const u64 time0 = timeout ? get_system_time() : 0;
const error_code res_ = _sys_lwmutex_lock(ppu, lwmutex->sleep_queue, timeout);
if (res_ == CELL_OK)
{
lwmutex->vars.owner.release(tid);
}
else if (timeout && res_ != CELL_ETIMEDOUT)
{
const u64 time_diff = get_system_time() - time0;
if (timeout <= time_diff)
{
lwmutex->all_info--;
return not_an_error(CELL_ETIMEDOUT);
}
timeout -= time_diff;
}
lwmutex->all_info--;
if (res_ != CELL_EBUSY)
{
return res_;
}
}
}
return res;
@ -297,11 +346,19 @@ error_code sys_lwmutex_unlock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
if (lwmutex->attribute & SYS_SYNC_RETRY)
{
// TODO (protocol is ignored in current implementation)
lwmutex->vars.owner.release(lwmutex_free);
// Call the alternative syscall
if (_sys_lwmutex_unlock2(lwmutex->sleep_queue) == CELL_ESRCH)
{
return CELL_ESRCH;
}
return CELL_OK;
}
// set special value
lwmutex->vars.owner.exchange(lwmutex_reserved);
lwmutex->vars.owner.release(lwmutex_reserved);
// call the syscall
if (_sys_lwmutex_unlock(ppu, lwmutex->sleep_queue) == CELL_ESRCH)