sys_lwcond: Extract protocol from lwmutex at creation

This is the only reason theres a need to specify lwmutex_sq id at creation. unlike sys_cond, lwcond isn't connected to lwmutex at the lv2 level.
SYS_SYNC_RETRY fix is done explicitly at the firmware level.
This fixes issues when the original lwcond and lwmutexol data got corrupted or deallocated, this can happen when the program simply memcpy the control data to somewhere else.
Or if it uses direct lv2 the lwcond conrol param can even be NULL which will make it access violate when dereferncing it. (This param is unchecked and can be anything)
This commit is contained in:
eladash 2019-05-07 22:05:16 +03:00 committed by Nekotekina
parent 7508ae6e65
commit e40b76b253
2 changed files with 19 additions and 6 deletions

View file

@ -16,13 +16,24 @@ error_code _sys_lwcond_create(ppu_thread& ppu, vm::ptr<u32> lwcond_id, u32 lwmut
sys_lwcond.warning("_sys_lwcond_create(lwcond_id=*0x%x, lwmutex_id=0x%x, control=*0x%x, name=0x%llx, arg5=0x%x)", lwcond_id, lwmutex_id, control, name, arg5);
// Temporarily
if (!idm::check<lv2_obj, lv2_lwmutex>(lwmutex_id))
u32 protocol;
// Extract protocol from lwmutex
if (!idm::check<lv2_obj, lv2_lwmutex>(lwmutex_id, [&protocol](lv2_lwmutex& mutex)
{
protocol = mutex.protocol;
}))
{
return CELL_ESRCH;
}
if (const u32 id = idm::make<lv2_obj, lv2_lwcond>(name, lwmutex_id, control))
if (protocol == SYS_SYNC_RETRY)
{
// Lwcond can't have SYS_SYNC_RETRY protocol
protocol = SYS_SYNC_PRIORITY;
}
if (const u32 id = idm::make<lv2_obj, lv2_lwcond>(name, lwmutex_id, protocol, control))
{
*lwcond_id = id;
return CELL_OK;
@ -114,7 +125,7 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u3
}
else
{
result = cond.schedule<ppu_thread>(cond.sq, cond.control->lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK);
result = cond.schedule<ppu_thread>(cond.sq, cond.protocol);
}
if (result)
@ -206,7 +217,7 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
u32 result = 0;
while (const auto cpu = cond.schedule<ppu_thread>(cond.sq, cond.control->lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK))
while (const auto cpu = cond.schedule<ppu_thread>(cond.sq, cond.protocol))
{
cond.waiters--;

View file

@ -27,15 +27,17 @@ struct lv2_lwcond final : lv2_obj
const u64 name;
const u32 lwid;
const u32 protocol;
vm::ptr<sys_lwcond_t> control;
shared_mutex mutex;
atomic_t<u32> waiters{0};
std::deque<cpu_thread*> sq;
lv2_lwcond(u64 name, u32 lwid, vm::ptr<sys_lwcond_t> control)
lv2_lwcond(u64 name, u32 lwid, u32 protocol, vm::ptr<sys_lwcond_t> control)
: name(name)
, lwid(lwid)
, protocol(protocol)
, control(control)
{
}