From 48eb66383bb972329c67b8c57d6a30f8618f9204 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 11 Oct 2014 02:37:20 +0400 Subject: [PATCH] waiter_reg_t, cellSyncBarrier improved --- Utilities/Thread.cpp | 8 +++-- Utilities/Thread.h | 25 +++++++++------ rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 42 ++++++++++++++----------- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 10970be896..f3afef6a42 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -235,7 +235,9 @@ bool waiter_is_stopped(const char* func_name, u64 signal_id) return false; } -void waiter_register(u64 signal_id, NamedThreadBase* thread) +waiter_reg_t::waiter_reg_t(u64 signal_id) + : signal_id(signal_id) + , thread(GetCurrentNamedThread()) { std::lock_guard lock(g_waiter_map.m_mutex); @@ -243,12 +245,12 @@ void waiter_register(u64 signal_id, NamedThreadBase* thread) g_waiter_map.m_waiters.push_back({ signal_id, thread }); } -void waiter_unregister(u64 signal_id, NamedThreadBase* thread) +waiter_reg_t::~waiter_reg_t() { std::lock_guard lock(g_waiter_map.m_mutex); // remove waiter - for (s32 i = g_waiter_map.m_waiters.size() - 1; i >= 0; i--) + for (size_t i = g_waiter_map.m_waiters.size() - 1; i >= 0; i--) { if (g_waiter_map.m_waiters[i].signal_id == signal_id && g_waiter_map.m_waiters[i].thread == thread) { diff --git a/Utilities/Thread.h b/Utilities/Thread.h index acef1eb77b..02f0388e5d 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -73,27 +73,32 @@ public: // for internal use (checks if Emu is stopped) bool waiter_is_stopped(const char* func_name, u64 signal_id); -// for internal use -void waiter_register(u64 signal_id, NamedThreadBase* thread); -// for internal use -void waiter_unregister(u64 signal_id, NamedThreadBase* thread); -// wait until waiter_func() returns true, signal_id is arbitrary number +struct waiter_reg_t +{ + const u64 signal_id; + NamedThreadBase* const thread; + + waiter_reg_t(u64 signal_id); + ~waiter_reg_t(); +}; + +// wait until waiter_func() returns true, signal_id is an arbitrary number template static __forceinline void waiter_op(const char* func_name, u64 signal_id, const WT waiter_func) { + // check condition if (waiter_func()) return; - NamedThreadBase* thread = GetCurrentNamedThread(); - waiter_register(signal_id, thread); + // register waiter + waiter_reg_t waiter(signal_id); while (true) { - thread->WaitForAnySignal(1); + // wait for 1 ms or until signal arrived + waiter.thread->WaitForAnySignal(1); if (waiter_is_stopped(func_name, signal_id)) break; if (waiter_func()) break; } - - waiter_unregister(signal_id, thread); } // signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 5f55d6d0fa..7232898418 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -174,15 +174,12 @@ s32 cellSyncBarrierNotify(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - while (barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryNotifyOp)) + waiter_op(__FUNCTION__, barrier.addr(), [barrier]() { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncBarrierNotify(barrier_addr=0x%x) aborted", barrier.addr()); - return CELL_OK; - } - } + return barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryNotifyOp) == CELL_OK; + }); + + waiter_signal(barrier.addr() ^ 1); return CELL_OK; } @@ -199,7 +196,13 @@ s32 cellSyncBarrierTryNotify(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - return barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryNotifyOp); + if (s32 res = barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryNotifyOp)) + { + return res; + } + + waiter_signal(barrier.addr() ^ 1); + return CELL_OK; } s32 syncBarrierTryWaitOp(CellSyncBarrier::data_t& barrier) @@ -233,15 +236,12 @@ s32 cellSyncBarrierWait(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - while (barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryWaitOp)) + waiter_op(__FUNCTION__, barrier.addr() ^ 1, [barrier]() { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncBarrierWait(barrier_addr=0x%x) aborted", barrier.addr()); - return CELL_OK; - } - } + return barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryWaitOp) == CELL_OK; + }); + + waiter_signal(barrier.addr()); return CELL_OK; } @@ -258,7 +258,13 @@ s32 cellSyncBarrierTryWait(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - return barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryWaitOp); + if (s32 res = barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryWaitOp)) + { + return res; + } + + waiter_signal(barrier.addr()); + return CELL_OK; } s32 syncRwmInitialize(vm::ptr rwm, vm::ptr buffer, u32 buffer_size)