From a3d400b5cca5d778e4ec6188f46663e7d621e804 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 11 Mar 2015 18:30:50 +0300 Subject: [PATCH] Minor cleanup --- rpcs3/Emu/Cell/RawSPUThread.h | 8 ++++ rpcs3/Emu/Cell/SPUThread.cpp | 49 ++++++++++++----------- rpcs3/Emu/Memory/Memory.h | 9 ----- rpcs3/Emu/SysCalls/lv2/sys_cond.cpp | 10 +++-- rpcs3/Emu/SysCalls/lv2/sys_cond.h | 2 +- rpcs3/Emu/SysCalls/lv2/sys_event.cpp | 47 +++++++--------------- rpcs3/Emu/SysCalls/lv2/sys_event.h | 10 ++++- rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp | 44 +++++++++----------- rpcs3/Emu/SysCalls/lv2/sys_event_flag.h | 3 +- rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp | 32 ++++++++++----- rpcs3/Emu/SysCalls/lv2/sys_lwcond.h | 2 +- rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp | 16 ++++++-- rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h | 2 +- rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp | 14 ++++--- rpcs3/Emu/SysCalls/lv2/sys_mutex.h | 2 +- rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp | 44 ++++++++++++++------ rpcs3/Emu/SysCalls/lv2/sys_rwlock.h | 11 +++-- rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp | 24 ++++++++--- rpcs3/Emu/SysCalls/lv2/sys_semaphore.h | 2 +- rpcs3/Emu/SysCalls/lv2/sys_timer.cpp | 9 +++-- 20 files changed, 195 insertions(+), 145 deletions(-) diff --git a/rpcs3/Emu/Cell/RawSPUThread.h b/rpcs3/Emu/Cell/RawSPUThread.h index d401a917c7..51811d4f22 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.h +++ b/rpcs3/Emu/Cell/RawSPUThread.h @@ -1,6 +1,14 @@ #pragma once #include "SPUThread.h" +enum : u32 +{ + RAW_SPU_OFFSET = 0x00100000, + RAW_SPU_BASE_ADDR = 0xE0000000, + RAW_SPU_LS_OFFSET = 0x00000000, + RAW_SPU_PROB_OFFSET = 0x00040000, +}; + __forceinline static u32 GetRawSPURegAddrByNum(int num, int offset) { return RAW_SPU_OFFSET * num + RAW_SPU_BASE_ADDR + RAW_SPU_PROB_OFFSET + offset; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 5ccec5fcc5..b529b6276f 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -604,19 +604,17 @@ void SPUThread::set_ch_value(u32 ch, u32 value) if (!queue) { LOG_WARNING(SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (value & 0x00ffffff), data); - ch_in_mbox.push_uncond(CELL_ENOTCONN); // TODO: check error passing - return; + return ch_in_mbox.push_uncond(CELL_ENOTCONN); // TODO: check error passing } if (queue->events.size() >= queue->size) { - ch_in_mbox.push_uncond(CELL_EBUSY); - return; + return ch_in_mbox.push_uncond(CELL_EBUSY); } queue->push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data); - ch_in_mbox.push_uncond(CELL_OK); - return; + + return ch_in_mbox.push_uncond(CELL_OK); } else if (code < 128) { @@ -685,20 +683,22 @@ void SPUThread::set_ch_value(u32 ch, u32 value) if (!Emu.GetIdManager().GetIDData(data, ef)) { - ch_in_mbox.push_uncond(CELL_ESRCH); - return; + return ch_in_mbox.push_uncond(CELL_ESRCH); } - while (ef->waiters < 0) + while (ef->cancelled) { ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } ef->flags |= 1ull << flag; - ef->cv.notify_all(); - ch_in_mbox.push_uncond(CELL_OK); - return; + if (ef->waiters) + { + ef->cv.notify_all(); + } + + return ch_in_mbox.push_uncond(CELL_OK); } else if (code == 192) { @@ -732,13 +732,18 @@ void SPUThread::set_ch_value(u32 ch, u32 value) return; } - while (ef->waiters < 0) + while (ef->cancelled) { ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } ef->flags |= 1ull << flag; - ef->cv.notify_all(); + + if (ef->waiters) + { + ef->cv.notify_all(); + } + return; } else @@ -958,8 +963,7 @@ void SPUThread::stop_and_signal(u32 code) if (ch_in_mbox.get_count()) { LOG_ERROR(SPU, "sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq); - ch_in_mbox.push_uncond(CELL_EBUSY); - return; + return ch_in_mbox.push_uncond(CELL_EBUSY); } if (Ini.HLELogging.GetValue()) @@ -986,20 +990,17 @@ void SPUThread::stop_and_signal(u32 code) if (!queue) { - ch_in_mbox.push_uncond(CELL_EINVAL); // TODO: check error value - return; + return ch_in_mbox.push_uncond(CELL_EINVAL); // TODO: check error value } // protocol is ignored in current implementation - queue->waiters++; assert(queue->waiters > 0); + queue->waiters++; while (queue->events.empty()) { - if (queue->waiters < 0) + if (queue->cancelled) { - queue->waiters--; assert(queue->waiters < 0); - ch_in_mbox.push_uncond(CELL_ECANCELED); - return; + return ch_in_mbox.push_uncond(CELL_ECANCELED); } if (Emu.IsStopped()) @@ -1018,7 +1019,7 @@ void SPUThread::stop_and_signal(u32 code) ch_in_mbox.push_uncond((u32)event.data3); queue->events.pop_front(); - queue->waiters--; assert(queue->waiters >= 0); + queue->waiters--; if (queue->events.size()) { diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index ae07d8442f..a7d82989ac 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -14,14 +14,6 @@ enum MemoryType Memory_PSP, }; -enum : u32 -{ - RAW_SPU_OFFSET = 0x00100000, - RAW_SPU_BASE_ADDR = 0xE0000000, - RAW_SPU_LS_OFFSET = 0x00000000, - RAW_SPU_PROB_OFFSET = 0x00040000, -}; - class MemoryBase { std::vector MemoryBlocks; @@ -98,4 +90,3 @@ public: extern MemoryBase Memory; #include "vm.h" - diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp index 31eb558f9f..844fb58641 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp @@ -170,11 +170,15 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout) } // protocol is ignored in current implementation - cond->waiters++; assert(cond->waiters > 0); + cond->waiters++; // unlock mutex cond->mutex->owner.reset(); - cond->mutex->cv.notify_one(); + + if (cond->mutex->waiters) + { + cond->mutex->cv.notify_one(); + } // save recursive value const u32 recursive_value = cond->mutex->recursive_count.exchange(0); @@ -189,7 +193,7 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout) // cancel waiting if the mutex is free, restore its owner and recursive value cond->mutex->owner = thread; cond->mutex->recursive_count = recursive_value; - cond->waiters--; assert(cond->waiters >= 0); + cond->waiters--; return CELL_ETIMEDOUT; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.h b/rpcs3/Emu/SysCalls/lv2/sys_cond.h index eb9f3b5d40..6b2bda4720 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.h @@ -24,7 +24,7 @@ struct cond_t // TODO: use sleep queue, possibly remove condition variable std::condition_variable cv; - std::atomic waiters; + std::atomic waiters; cond_t(std::shared_ptr& mutex, u64 name) : mutex(mutex) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp index e94af91c3f..fbe5ea7b8d 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp @@ -49,18 +49,11 @@ s32 sys_event_queue_create(vm::ptr equeue_id, vm::ptr default: sys_event.Error("sys_event_queue_create(): unknown type (0x%x)", type); return CELL_EINVAL; } - LV2_LOCK; - - if (Emu.GetEventManager().CheckKey(event_queue_key)) - { - return CELL_EEXIST; - } - std::shared_ptr queue(new event_queue_t(protocol, type, attr->name_u64, event_queue_key, size)); if (!Emu.GetEventManager().RegisterKey(queue, event_queue_key)) { - return CELL_EAGAIN; + return CELL_EEXIST; } *equeue_id = Emu.GetIdManager().GetNewID(queue, TYPE_EVENT_QUEUE); @@ -86,16 +79,18 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode) return CELL_EINVAL; } - assert(queue->waiters >= 0); - if (!mode && queue->waiters) { return CELL_EBUSY; } - else + + if (queue->cancelled.exchange(true)) + { + throw __FUNCTION__; + } + + if (queue->waiters) { - // set special value for waiters - queue->waiters.exchange(-1); queue->cv.notify_all(); } @@ -107,7 +102,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode) s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_array, s32 size, vm::ptr number) { - sys_event.Warning("sys_event_queue_tryreceive(equeue_id=%d, event_array=*0x%x, size=%d, number=*0x%x)", equeue_id, event_array, size, number); + sys_event.Log("sys_event_queue_tryreceive(equeue_id=%d, event_array=*0x%x, size=%d, number=*0x%x)", equeue_id, event_array, size, number); LV2_LOCK; @@ -130,7 +125,7 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_array, s32 count = 0; - while (count < size && queue->events.size()) + while (!queue->waiters && count < size && queue->events.size()) { auto& event = queue->events.front(); event_array[count++] = { be_t::make(event.source), be_t::make(event.data1), be_t::make(event.data2), be_t::make(event.data3) }; @@ -140,11 +135,6 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_array, *number = count; - if (queue->events.size()) - { - queue->cv.notify_one(); - } - return CELL_OK; } @@ -169,19 +159,19 @@ s32 sys_event_queue_receive(PPUThread& CPU, u32 equeue_id, vm::ptr } // protocol is ignored in current implementation - queue->waiters++; assert(queue->waiters > 0); + queue->waiters++; while (queue->events.empty()) { - if (queue->waiters < 0) + if (queue->cancelled) { - queue->waiters--; assert(queue->waiters < 0); + queue->waiters--; return CELL_ECANCELED; } if (timeout && get_system_time() - start_time > timeout) { - queue->waiters--; assert(queue->waiters >= 0); + queue->waiters--; return CELL_ETIMEDOUT; } @@ -202,12 +192,7 @@ s32 sys_event_queue_receive(PPUThread& CPU, u32 equeue_id, vm::ptr CPU.GPR[7] = event.data3; queue->events.pop_front(); - queue->waiters--; assert(queue->waiters >= 0); - - if (queue->events.size()) - { - queue->cv.notify_one(); - } + queue->waiters--; return CELL_OK; } @@ -247,8 +232,6 @@ s32 sys_event_port_create(vm::ptr eport_id, s32 port_type, u64 name) return CELL_EINVAL; } - LV2_LOCK; - std::shared_ptr eport(new event_port_t(port_type, name)); *eport_id = Emu.GetIdManager().GetNewID(eport, TYPE_EVENT_PORT); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.h b/rpcs3/Emu/SysCalls/lv2/sys_event.h index 781df1d5a5..842d4b267a 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.h @@ -78,10 +78,11 @@ struct event_queue_t const s32 size; std::deque events; + std::atomic cancelled; // TODO: use sleep queue, possibly remove condition variable std::condition_variable cv; - std::atomic waiters; + std::atomic waiters; event_queue_t(u32 protocol, s32 type, u64 name, u64 key, s32 size) : protocol(protocol) @@ -89,6 +90,7 @@ struct event_queue_t , name(name) , key(key) , size(size) + , cancelled(false) , waiters(0) { } @@ -96,7 +98,11 @@ struct event_queue_t void push(u64 source, u64 data1, u64 data2, u64 data3) { events.emplace_back(source, data1, data2, data3); - cv.notify_one(); + + if (waiters) + { + cv.notify_one(); + } } }; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp index 718260f28c..bd1857bdd4 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp @@ -16,8 +16,6 @@ s32 sys_event_flag_create(vm::ptr id, vm::ptr attr, u6 { sys_event_flag.Warning("sys_event_flag_create(id=*0x%x, attr=*0x%x, init=0x%llx)", id, attr, init); - LV2_LOCK; - if (!id || !attr) { return CELL_EFAULT; @@ -69,11 +67,6 @@ s32 sys_event_flag_destroy(u32 id) return CELL_ESRCH; } - while (ef->waiters < 0) - { - ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); - } - if (ef->waiters) { return CELL_EBUSY; @@ -124,7 +117,7 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr result, u64 t return CELL_EPERM; } - while (ef->waiters < 0) + while (ef->cancelled) { // wait until other threads return CELL_ECANCELED (to prevent modifying bit pattern) ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); @@ -150,11 +143,9 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr result, u64 t break; } - if (ef->waiters <= 0) + if (ef->cancelled) { - ef->waiters++; assert(ef->waiters <= 0); - - if (!ef->waiters) + if (!--ef->cancelled) { ef->cv.notify_all(); } @@ -164,7 +155,7 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr result, u64 t if (timeout && get_system_time() - start_time > timeout) { - ef->waiters--; assert(ef->waiters >= 0); + ef->waiters--; return CELL_ETIMEDOUT; } @@ -187,9 +178,7 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr result, u64 t ef->flags = 0; } - ef->waiters--; assert(ef->waiters >= 0); - - if (ef->flags) + if (--ef->waiters && ef->flags) { ef->cv.notify_one(); } @@ -235,7 +224,7 @@ s32 sys_event_flag_trywait(u32 id, u64 bitptn, u32 mode, vm::ptr result) return CELL_EBUSY; } - while (ef->waiters < 0) + while (ef->cancelled) { ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } @@ -270,13 +259,17 @@ s32 sys_event_flag_set(u32 id, u64 bitptn) return CELL_ESRCH; } - while (ef->waiters < 0) + while (ef->cancelled) { ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } ef->flags |= bitptn; - ef->cv.notify_all(); + + if (ef->waiters) + { + ef->cv.notify_all(); + } return CELL_OK; } @@ -294,7 +287,7 @@ s32 sys_event_flag_clear(u32 id, u64 bitptn) return CELL_ESRCH; } - while (ef->waiters < 0) + while (ef->cancelled) { ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } @@ -322,7 +315,7 @@ s32 sys_event_flag_cancel(u32 id, vm::ptr num) return CELL_ESRCH; } - while (ef->waiters < 0) + while (ef->cancelled) { ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } @@ -332,10 +325,11 @@ s32 sys_event_flag_cancel(u32 id, vm::ptr num) *num = ef->waiters; } - // negate value to signal waiting threads and prevent modifying bit pattern - ef->waiters = -ef->waiters; - ef->cv.notify_all(); - + if ((ef->cancelled = ef->waiters.exchange(0))) + { + ef->cv.notify_all(); + } + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h index a470d6e496..7e15f27246 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h @@ -34,10 +34,11 @@ struct event_flag_t const u64 name; std::atomic flags; + std::atomic cancelled; // TODO: use sleep queue, possibly remove condition variable std::condition_variable cv; - std::atomic waiters; + std::atomic waiters; event_flag_t(u64 pattern, u32 protocol, s32 type, u64 name) : flags(pattern) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp index 9cb791bfb7..a2765b462a 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp @@ -38,6 +38,7 @@ s32 _sys_lwcond_destroy(u32 lwcond_id) LV2_LOCK; std::shared_ptr cond; + if (!Emu.GetIdManager().GetIDData(lwcond_id, cond)) { return CELL_ESRCH; @@ -60,12 +61,13 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod LV2_LOCK; std::shared_ptr cond; + std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(lwcond_id, cond)) { return CELL_ESRCH; } - std::shared_ptr mutex; if (lwmutex_id && !Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) { return CELL_ESRCH; @@ -117,8 +119,10 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod cond->signaled1++; } - cond->waiters--; - cond->cv.notify_one(); + if (--cond->waiters) + { + cond->cv.notify_one(); + } return CELL_OK; } @@ -130,12 +134,13 @@ s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode) LV2_LOCK; std::shared_ptr cond; + std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(lwcond_id, cond)) { return CELL_ESRCH; } - std::shared_ptr mutex; if (lwmutex_id && !Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) { return CELL_ESRCH; @@ -147,7 +152,11 @@ s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode) } const s32 count = cond->waiters.exchange(0); - cond->cv.notify_all(); + + if (count) + { + cond->cv.notify_all(); + } if (mode == 1) { @@ -176,12 +185,13 @@ s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout) LV2_LOCK; std::shared_ptr cond; + std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(lwcond_id, cond)) { return CELL_ESRCH; } - std::shared_ptr mutex; if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) { return CELL_ESRCH; @@ -189,10 +199,14 @@ s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout) // finalize unlocking the mutex mutex->signaled++; - mutex->cv.notify_one(); + + if (mutex->waiters) + { + mutex->cv.notify_one(); + } // protocol is ignored in current implementation - cond->waiters++; assert(cond->waiters > 0); + cond->waiters++; while (!(cond->signaled1 && mutex->signaled) && !cond->signaled2) { @@ -202,7 +216,7 @@ s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout) if (is_timedout && !cond->signaled1) { // cancel waiting - cond->waiters--; assert(cond->waiters >= 0); + cond->waiters--; if (mutex->signaled) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h index 8236cc2fe6..ef02f85899 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h @@ -26,7 +26,7 @@ struct lwcond_t // TODO: use sleep queue std::condition_variable cv; - std::atomic waiters; + std::atomic waiters; lwcond_t(u64 name) : name(name) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp index 96d87ab0b4..5b8f99e1c3 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp @@ -53,6 +53,7 @@ s32 _sys_lwmutex_destroy(u32 lwmutex_id) LV2_LOCK; std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) { return CELL_ESRCH; @@ -77,19 +78,20 @@ s32 _sys_lwmutex_lock(u32 lwmutex_id, u64 timeout) LV2_LOCK; std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) { return CELL_ESRCH; } // protocol is ignored in current implementation - mutex->waiters++; assert(mutex->waiters > 0); + mutex->waiters++; while (!mutex->signaled) { if (timeout && get_system_time() - start_time > timeout) { - mutex->waiters--; assert(mutex->waiters >= 0); + mutex->waiters--; return CELL_ETIMEDOUT; } @@ -104,7 +106,7 @@ s32 _sys_lwmutex_lock(u32 lwmutex_id, u64 timeout) mutex->signaled--; - mutex->waiters--; assert(mutex->waiters >= 0); + mutex->waiters--; return CELL_OK; } @@ -116,6 +118,7 @@ s32 _sys_lwmutex_trylock(u32 lwmutex_id) LV2_LOCK; std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) { return CELL_ESRCH; @@ -138,6 +141,7 @@ s32 _sys_lwmutex_unlock(u32 lwmutex_id) LV2_LOCK; std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) { return CELL_ESRCH; @@ -149,7 +153,11 @@ s32 _sys_lwmutex_unlock(u32 lwmutex_id) } mutex->signaled++; - mutex->cv.notify_one(); + + if (mutex->waiters) + { + mutex->cv.notify_one(); + } return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h index f29e2866d6..4a26d65909 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h @@ -76,7 +76,7 @@ struct lwmutex_t // TODO: use sleep queue, possibly remove condition variable std::condition_variable cv; - std::atomic waiters; + std::atomic waiters; lwmutex_t(u32 protocol, u64 name) : protocol(protocol) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp index 4eefd74ca0..29ee05df8d 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp @@ -16,8 +16,6 @@ s32 sys_mutex_create(vm::ptr mutex_id, vm::ptr attr) { sys_mutex.Warning("sys_mutex_create(mutex_id=*0x%x, attr=*0x%x)", mutex_id, attr); - LV2_LOCK; - if (!mutex_id || !attr) { return CELL_EFAULT; @@ -119,13 +117,13 @@ s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout) } // protocol is ignored in current implementation - mutex->waiters++; assert(mutex->waiters > 0); + mutex->waiters++; while (!mutex->owner.expired()) { if (timeout && get_system_time() - start_time > timeout) { - mutex->waiters--; assert(mutex->waiters >= 0); + mutex->waiters--; return CELL_ETIMEDOUT; } @@ -139,7 +137,7 @@ s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout) } mutex->owner = thread; - mutex->waiters--; assert(mutex->waiters >= 0); + mutex->waiters--; return CELL_OK; } @@ -218,7 +216,11 @@ s32 sys_mutex_unlock(PPUThread& CPU, u32 mutex_id) else { mutex->owner.reset(); - mutex->cv.notify_one(); + + if (mutex->waiters) + { + mutex->cv.notify_one(); + } } return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h index 3d5f01e509..31f155b574 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h @@ -29,7 +29,7 @@ struct mutex_t // TODO: use sleep queue, possibly remove condition variable std::condition_variable cv; - std::atomic waiters; + std::atomic waiters; mutex_t(bool recursive, u32 protocol, u64 name) : recursive(recursive) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp index 45998a738a..81c79aacf4 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp @@ -50,12 +50,13 @@ s32 sys_rwlock_destroy(u32 rw_lock_id) LV2_LOCK; std::shared_ptr rwlock; + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock)) { return CELL_ESRCH; } - if (rwlock.use_count() > 2 || rwlock->readers || rwlock->writer || rwlock->waiters) + if (rwlock->readers || rwlock->writer || rwlock->rwaiters || rwlock->wwaiters) { return CELL_EBUSY; } @@ -74,15 +75,20 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) LV2_LOCK; std::shared_ptr rwlock; + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock)) { return CELL_ESRCH; } - while (rwlock->writer || rwlock->waiters) + // waiting threads are not properly registered in current implementation + rwlock->rwaiters++; + + while (rwlock->writer || rwlock->wwaiters) { if (timeout && get_system_time() - start_time > timeout) { + rwlock->rwaiters--; return CELL_ETIMEDOUT; } @@ -92,10 +98,11 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) return CELL_OK; } - rwlock->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); + rwlock->rcv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } rwlock->readers++; + rwlock->rwaiters--; return CELL_OK; } @@ -107,12 +114,13 @@ s32 sys_rwlock_tryrlock(u32 rw_lock_id) LV2_LOCK; std::shared_ptr rwlock; + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock)) { return CELL_ESRCH; } - if (rwlock->writer || rwlock->waiters) + if (rwlock->writer || rwlock->wwaiters) { return CELL_EBUSY; } @@ -129,6 +137,7 @@ s32 sys_rwlock_runlock(u32 rw_lock_id) LV2_LOCK; std::shared_ptr rwlock; + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock)) { return CELL_ESRCH; @@ -139,9 +148,9 @@ s32 sys_rwlock_runlock(u32 rw_lock_id) return CELL_EPERM; } - if (!--rwlock->readers) + if (!--rwlock->readers && rwlock->wwaiters) { - rwlock->cv.notify_one(); + rwlock->wcv.notify_one(); } return CELL_OK; @@ -156,6 +165,7 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout) LV2_LOCK; std::shared_ptr rwlock; + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock)) { return CELL_ESRCH; @@ -167,13 +177,13 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout) } // protocol is ignored in current implementation - rwlock->waiters++; assert(rwlock->waiters > 0); + rwlock->wwaiters++; while (rwlock->readers || rwlock->writer) { if (timeout && get_system_time() - start_time > timeout) { - rwlock->waiters--; assert(rwlock->waiters >= 0); + rwlock->wwaiters--; return CELL_ETIMEDOUT; } @@ -183,11 +193,11 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout) return CELL_OK; } - rwlock->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); + rwlock->wcv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } rwlock->writer = CPU.GetId(); - rwlock->waiters--; assert(rwlock->waiters >= 0); + rwlock->wwaiters--; return CELL_OK; } @@ -199,6 +209,7 @@ s32 sys_rwlock_trywlock(PPUThread& CPU, u32 rw_lock_id) LV2_LOCK; std::shared_ptr rwlock; + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock)) { return CELL_ESRCH; @@ -209,7 +220,7 @@ s32 sys_rwlock_trywlock(PPUThread& CPU, u32 rw_lock_id) return CELL_EDEADLK; } - if (rwlock->readers || rwlock->writer || rwlock->waiters) + if (rwlock->readers || rwlock->writer || rwlock->wwaiters) { return CELL_EBUSY; } @@ -226,6 +237,7 @@ s32 sys_rwlock_wunlock(PPUThread& CPU, u32 rw_lock_id) LV2_LOCK; std::shared_ptr rwlock; + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock)) { return CELL_ESRCH; @@ -237,7 +249,15 @@ s32 sys_rwlock_wunlock(PPUThread& CPU, u32 rw_lock_id) } rwlock->writer = 0; - rwlock->cv.notify_all(); + + if (rwlock->wwaiters) + { + rwlock->wcv.notify_one(); + } + else if (rwlock->rwaiters) + { + rwlock->rcv.notify_all(); + } return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.h b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.h index 495b94bac9..5fdfa81e94 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.h @@ -23,16 +23,19 @@ struct rwlock_t std::atomic readers; // reader count std::atomic writer; // writer id - // TODO: use sleep queue, possibly remove condition variable - std::condition_variable cv; - std::atomic waiters; + // TODO: use sleep queue, possibly remove condition variables + std::condition_variable rcv; + std::condition_variable wcv; + std::atomic rwaiters; + std::atomic wwaiters; rwlock_t(u32 protocol, u64 name) : protocol(protocol) , name(name) , readers(0) , writer(0) - , waiters(0) + , rwaiters(0) + , wwaiters(0) { } }; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp index a0366516fa..72b7fd7bd0 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp @@ -62,6 +62,7 @@ s32 sys_semaphore_destroy(u32 sem) LV2_LOCK; std::shared_ptr semaphore; + if (!Emu.GetIdManager().GetIDData(sem, semaphore)) { return CELL_ESRCH; @@ -86,19 +87,20 @@ s32 sys_semaphore_wait(u32 sem, u64 timeout) LV2_LOCK; std::shared_ptr semaphore; + if (!Emu.GetIdManager().GetIDData(sem, semaphore)) { return CELL_ESRCH; } // protocol is ignored in current implementation - semaphore->waiters++; assert(semaphore->waiters > 0); + semaphore->waiters++; while (semaphore->value <= 0) { if (timeout && get_system_time() - start_time > timeout) { - semaphore->waiters--; assert(semaphore->waiters >= 0); + semaphore->waiters--; return CELL_ETIMEDOUT; } @@ -112,7 +114,7 @@ s32 sys_semaphore_wait(u32 sem, u64 timeout) } semaphore->value--; - semaphore->waiters--; assert(semaphore->waiters >= 0); + semaphore->waiters--; return CELL_OK; } @@ -124,6 +126,7 @@ s32 sys_semaphore_trywait(u32 sem) LV2_LOCK; std::shared_ptr semaphore; + if (!Emu.GetIdManager().GetIDData(sem, semaphore)) { return CELL_ESRCH; @@ -146,6 +149,7 @@ s32 sys_semaphore_post(u32 sem, s32 count) LV2_LOCK; std::shared_ptr semaphore; + if (!Emu.GetIdManager().GetIDData(sem, semaphore)) { return CELL_ESRCH; @@ -156,13 +160,20 @@ s32 sys_semaphore_post(u32 sem, s32 count) return CELL_EINVAL; } - if (semaphore->value + count > semaphore->max + semaphore->waiters) + const u64 new_value = semaphore->value + count; + const u64 max_value = semaphore->max + semaphore->waiters; + + if (new_value > max_value) { return CELL_EBUSY; } - semaphore->value += count; assert(semaphore->value >= 0); - semaphore->cv.notify_all(); + semaphore->value += count; + + if (semaphore->waiters) + { + semaphore->cv.notify_all(); + } return CELL_OK; } @@ -179,6 +190,7 @@ s32 sys_semaphore_get_value(u32 sem, vm::ptr count) LV2_LOCK; std::shared_ptr semaphore; + if (!Emu.GetIdManager().GetIDData(sem, semaphore)) { return CELL_ESRCH; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h index 674b2d94a8..102545bc2c 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h @@ -25,7 +25,7 @@ struct semaphore_t // TODO: use sleep queue, possibly remove condition variable std::condition_variable cv; - std::atomic waiters; + std::atomic waiters; semaphore_t(u32 protocol, s32 max, u64 name, s32 value) : protocol(protocol) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp index 7f86c570a9..823199a827 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp @@ -32,8 +32,7 @@ s32 sys_timer_create(vm::ptr timer_id) if (queue) { - queue->events.emplace_back(timer->source, timer->data1, timer->data2, timer->start); - queue->cv.notify_one(); + queue->push(timer->source, timer->data1, timer->data2, timer->start); } if (timer->period && queue) @@ -64,6 +63,7 @@ s32 sys_timer_destroy(u32 timer_id) LV2_LOCK; std::shared_ptr timer; + if (!Emu.GetIdManager().GetIDData(timer_id, timer)) { return CELL_ESRCH; @@ -86,6 +86,7 @@ s32 sys_timer_get_information(u32 timer_id, vm::ptr inf LV2_LOCK; std::shared_ptr timer; + if (!Emu.GetIdManager().GetIDData(timer_id, timer)) { return CELL_ESRCH; @@ -94,7 +95,6 @@ s32 sys_timer_get_information(u32 timer_id, vm::ptr inf info->next_expiration_time = timer->start; info->period = timer->period; - info->timer_state = timer->state; return CELL_OK; @@ -109,6 +109,7 @@ s32 _sys_timer_start(u32 timer_id, u64 base_time, u64 period) LV2_LOCK; std::shared_ptr timer; + if (!Emu.GetIdManager().GetIDData(timer_id, timer)) { return CELL_ESRCH; @@ -160,6 +161,7 @@ s32 sys_timer_stop(u32 timer_id) LV2_LOCK; std::shared_ptr timer; + if (!Emu.GetIdManager().GetIDData(timer_id, timer)) { return CELL_ESRCH; @@ -204,6 +206,7 @@ s32 sys_timer_disconnect_event_queue(u32 timer_id) LV2_LOCK; std::shared_ptr timer; + if (!Emu.GetIdManager().GetIDData(timer_id, timer)) { return CELL_ESRCH;