diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index e66b8a4f3a..604aab4902 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -4,51 +4,17 @@ #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "cellSync.h" + //void cellSync_init(); //Module cellSync("cellSync", cellSync_init); Module *cellSync = nullptr; -// Return Codes -enum -{ - CELL_SYNC_ERROR_AGAIN = 0x80410101, - CELL_SYNC_ERROR_INVAL = 0x80410102, - CELL_SYNC_ERROR_NOMEM = 0x80410104, - CELL_SYNC_ERROR_DEADLK = 0x80410108, - CELL_SYNC_ERROR_PERM = 0x80410109, - CELL_SYNC_ERROR_BUSY = 0x8041010A, - CELL_SYNC_ERROR_STAT = 0x8041010F, - CELL_SYNC_ERROR_ALIGN = 0x80410110, - CELL_SYNC_ERROR_NULL_POINTER = 0x80410111, - CELL_SYNC_ERROR_NOT_SUPPORTED_THREAD = 0x80410112, - CELL_SYNC_ERROR_NO_NOTIFIER = 0x80410113, - CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, -}; - -struct CellSyncMutex -{ - be_t m_freed; - be_t m_order; - - volatile u32& m_data() - { - return *reinterpret_cast(this); - }; - /* - (???) Initialize: set zeros - (???) Lock: increase m_order and wait until m_freed == old m_order - (???) Unlock: increase m_freed - (???) TryLock: ????? - */ -}; - -static_assert(sizeof(CellSyncMutex) == 4, "CellSyncMutex: wrong sizeof"); - int cellSyncMutexInitialize(mem_ptr_t mutex) { cellSync->Log("cellSyncMutexInitialize(mutex=0x%x)", mutex.GetAddr()); - if (!mutex.IsGood()) + if (!mutex) { return CELL_SYNC_ERROR_NULL_POINTER; } @@ -57,7 +23,8 @@ int cellSyncMutexInitialize(mem_ptr_t mutex) return CELL_SYNC_ERROR_ALIGN; } - mutex->m_data() = 0; + // prx: set zero and sync + InterlockedExchange(&mutex->m_data(), 0); return CELL_OK; } @@ -65,7 +32,7 @@ int cellSyncMutexLock(mem_ptr_t mutex) { cellSync->Log("cellSyncMutexLock(mutex=0x%x)", mutex.GetAddr()); - if (!mutex.IsGood()) + if (!mutex) { return CELL_SYNC_ERROR_NULL_POINTER; } @@ -74,6 +41,7 @@ int cellSyncMutexLock(mem_ptr_t mutex) return CELL_SYNC_ERROR_ALIGN; } + // prx: increase u16 and remember its old value be_t old_order; while (true) { @@ -82,11 +50,12 @@ int cellSyncMutexLock(mem_ptr_t mutex) new_mutex.m_data() = old_data; old_order = new_mutex.m_order; - new_mutex.m_order++; + new_mutex.m_order++; // increase m_order if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break; } - while (old_order != mutex->m_freed) + // prx: wait until another u16 value == old value + while (old_order != mutex->m_freed) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); if (Emu.IsStopped()) @@ -95,7 +64,9 @@ int cellSyncMutexLock(mem_ptr_t mutex) break; } } - _mm_mfence(); + + // prx: sync + InterlockedCompareExchange(&mutex->m_data(), 0, 0); return CELL_OK; } @@ -103,7 +74,7 @@ int cellSyncMutexTryLock(mem_ptr_t mutex) { cellSync->Log("cellSyncMutexTryLock(mutex=0x%x)", mutex.GetAddr()); - if (!mutex.IsGood()) + if (!mutex) { return CELL_SYNC_ERROR_NULL_POINTER; } @@ -112,34 +83,32 @@ int cellSyncMutexTryLock(mem_ptr_t mutex) return CELL_SYNC_ERROR_ALIGN; } - int res; - while (true) { const u32 old_data = mutex->m_data(); CellSyncMutex new_mutex; new_mutex.m_data() = old_data; + // prx: compare two u16 values and exit if not equal if (new_mutex.m_order != new_mutex.m_freed) { - res = CELL_SYNC_ERROR_BUSY; + return CELL_SYNC_ERROR_BUSY; } else { new_mutex.m_order++; - res = CELL_OK; } if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break; } - return res; + return CELL_OK; } int cellSyncMutexUnlock(mem_ptr_t mutex) { cellSync->Log("cellSyncMutexUnlock(mutex=0x%x)", mutex.GetAddr()); - if (!mutex.IsGood()) + if (!mutex) { return CELL_SYNC_ERROR_NULL_POINTER; } @@ -148,6 +117,8 @@ int cellSyncMutexUnlock(mem_ptr_t mutex) return CELL_SYNC_ERROR_ALIGN; } + InterlockedCompareExchange(&mutex->m_data(), 0, 0); + while (true) { const u32 old_data = mutex->m_data(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h new file mode 100644 index 0000000000..36a768986e --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -0,0 +1,38 @@ +#pragma once + +// Return Codes +enum +{ + CELL_SYNC_ERROR_AGAIN = 0x80410101, + CELL_SYNC_ERROR_INVAL = 0x80410102, + CELL_SYNC_ERROR_NOMEM = 0x80410104, + CELL_SYNC_ERROR_DEADLK = 0x80410108, + CELL_SYNC_ERROR_PERM = 0x80410109, + CELL_SYNC_ERROR_BUSY = 0x8041010A, + CELL_SYNC_ERROR_STAT = 0x8041010F, + CELL_SYNC_ERROR_ALIGN = 0x80410110, + CELL_SYNC_ERROR_NULL_POINTER = 0x80410111, + CELL_SYNC_ERROR_NOT_SUPPORTED_THREAD = 0x80410112, + CELL_SYNC_ERROR_NO_NOTIFIER = 0x80410113, + CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, +}; + +struct CellSyncMutex +{ + be_t m_freed; + be_t m_order; + + volatile u32& m_data() + { + return *reinterpret_cast(this); + }; +}; + +static_assert(sizeof(CellSyncMutex) == 4, "CellSyncMutex: wrong size"); + +struct CellSyncBarrier +{ + be_t m_data; +}; + +static_assert(sizeof(CellSyncBarrier) == 4, "CellSyncBarrier: wrong size"); \ No newline at end of file diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 058d68e32b..2ee34fa688 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -352,6 +352,7 @@ + @@ -560,4 +561,4 @@ - + \ No newline at end of file diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 36357d7e1a..446d1a2613 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1090,5 +1090,8 @@ Emu\Memory + + Emu\SysCalls\Modules + - + \ No newline at end of file