From e40b76b25362ccaf28bfa8f547abe03c64681fd5 Mon Sep 17 00:00:00 2001 From: eladash Date: Tue, 7 May 2019 22:05:16 +0300 Subject: [PATCH] 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) --- rpcs3/Emu/Cell/lv2/sys_lwcond.cpp | 21 ++++++++++++++++----- rpcs3/Emu/Cell/lv2/sys_lwcond.h | 4 +++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp index 1178466114..bde908e6d8 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp @@ -16,13 +16,24 @@ error_code _sys_lwcond_create(ppu_thread& ppu, vm::ptr 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(lwmutex_id)) + u32 protocol; + + // Extract protocol from lwmutex + if (!idm::check(lwmutex_id, [&protocol](lv2_lwmutex& mutex) + { + protocol = mutex.protocol; + })) { return CELL_ESRCH; } - if (const u32 id = idm::make(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(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(cond.sq, cond.control->lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK); + result = cond.schedule(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(cond.sq, cond.control->lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK)) + while (const auto cpu = cond.schedule(cond.sq, cond.protocol)) { cond.waiters--; diff --git a/rpcs3/Emu/Cell/lv2/sys_lwcond.h b/rpcs3/Emu/Cell/lv2/sys_lwcond.h index ce38c4feec..6e9c353977 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwcond.h +++ b/rpcs3/Emu/Cell/lv2/sys_lwcond.h @@ -27,15 +27,17 @@ struct lv2_lwcond final : lv2_obj const u64 name; const u32 lwid; + const u32 protocol; vm::ptr control; shared_mutex mutex; atomic_t waiters{0}; std::deque sq; - lv2_lwcond(u64 name, u32 lwid, vm::ptr control) + lv2_lwcond(u64 name, u32 lwid, u32 protocol, vm::ptr control) : name(name) , lwid(lwid) + , protocol(protocol) , control(control) { }