diff --git a/rpcs3/Emu/Memory/atomic.h b/rpcs3/Emu/Memory/atomic.h index b4436c3de9..e6f9995ec6 100644 --- a/rpcs3/Emu/Memory/atomic.h +++ b/rpcs3/Emu/Memory/atomic.h @@ -211,9 +211,9 @@ template inline static typename std::enable_if template inline static typename std::enable_if::value, T>::type operator --(_atomic_base>& left, int) { - u64 result; + T result; - left.atomic_op([&result](be_t& value) + left.atomic_op([&result](be_t& value) { result = value--; }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 23cef8ccf4..618653b7d9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -25,13 +25,13 @@ s32 syncMutexInitialize(vm::ptr mutex) { return CELL_SYNC_ERROR_NULL_POINTER; } + if (mutex.addr() % 4) { return CELL_SYNC_ERROR_ALIGN; } - // prx: set zero and sync - mutex->data.exchange({}); + mutex->sync_var.exchange({}); return CELL_OK; } @@ -51,26 +51,22 @@ s32 cellSyncMutexLock(vm::ptr mutex) { return CELL_SYNC_ERROR_NULL_POINTER; } + if (mutex.addr() % 4) { return CELL_SYNC_ERROR_ALIGN; } - // prx: increase m_acq and remember its old value - be_t order; - mutex->data.atomic_op([&order](CellSyncMutex::data_t& mutex) - { - order = mutex.m_acq++; - }); + // prx: increase acquire_count and remember its old value + const be_t order = be_t::make(mutex->acquire_count++); - // prx: wait until this old value is equal to m_rel + // prx: wait until release_count is equal to old acquire_count g_sync_mutex_wm.wait_op(mutex.addr(), [mutex, order]() { - return order == mutex->data.read_relaxed().m_rel; + return order == mutex->release_count.read_relaxed(); }); - // prx: sync - mutex->data.read_sync(); + mutex->sync_var.read_sync(); return CELL_OK; } @@ -83,19 +79,16 @@ s32 cellSyncMutexTryLock(vm::ptr mutex) { return CELL_SYNC_ERROR_NULL_POINTER; } + if (mutex.addr() % 4) { return CELL_SYNC_ERROR_ALIGN; } - // prx: exit if m_acq and m_rel are not equal, increase m_acq - return mutex->data.atomic_op(CELL_OK, [](CellSyncMutex::data_t& mutex) -> s32 + // prx: lock only if acquire_count and release_count are equal + return mutex->sync_var.atomic_op(CELL_OK, [](CellSyncMutex::sync_t& mutex) -> s32 { - if (mutex.m_acq++ != mutex.m_rel) - { - return CELL_SYNC_ERROR_BUSY; - } - return CELL_OK; + return (mutex.acquire_count++ != mutex.release_count) ? CELL_SYNC_ERROR_BUSY : CELL_OK; }); } @@ -112,10 +105,8 @@ s32 cellSyncMutexUnlock(vm::ptr mutex) return CELL_SYNC_ERROR_ALIGN; } - mutex->data.atomic_op_sync([](CellSyncMutex::data_t& mutex) - { - mutex.m_rel++; - }); + // prx: increase release count + mutex->release_count++; g_sync_mutex_wm.notify(mutex.addr()); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index ba7ab97781..0fb5912579 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -29,15 +29,21 @@ enum CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, // ??? }; -struct CellSyncMutex +union CellSyncMutex { - struct data_t + struct sync_t { - be_t m_rel; // release order (increased when mutex is unlocked) - be_t m_acq; // acquire order (increased when mutex is locked) + be_t release_count; // increased when mutex is unlocked + be_t acquire_count; // increased when mutex is locked }; - atomic_t data; + struct + { + atomic_t release_count; + atomic_t acquire_count; + }; + + atomic_t sync_var; }; static_assert(sizeof(CellSyncMutex) == 4, "CellSyncMutex: wrong size");