From 18930a43f2fb163ec977852f05b38045bea5d8bb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 18 Oct 2014 00:13:25 +0400 Subject: [PATCH] waiter_map_t small fix --- Utilities/Thread.cpp | 13 +++-- Utilities/Thread.h | 69 +++++++++++++++++++++---- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 15 +++--- 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 63f0e83078..d45fe55fd8 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -219,11 +219,12 @@ bool waiter_map_t::is_stopped(u64 signal_id) return false; } -waiter_map_t::waiter_reg_t::waiter_reg_t(waiter_map_t& map, u64 signal_id) - : signal_id(signal_id) - , thread(GetCurrentNamedThread()) - , map(map) +void waiter_map_t::waiter_reg_t::init() { + if (thread) return; + + thread = GetCurrentNamedThread(); + std::lock_guard lock(map.m_mutex); // add waiter @@ -232,10 +233,12 @@ waiter_map_t::waiter_reg_t::waiter_reg_t(waiter_map_t& map, u64 signal_id) waiter_map_t::waiter_reg_t::~waiter_reg_t() { + if (!thread) return; + std::lock_guard lock(map.m_mutex); // remove waiter - for (size_t i = map.m_waiters.size() - 1; i >= 0; i--) + for (s64 i = map.m_waiters.size() - 1; i >= 0; i--) { if (map.m_waiters[i].signal_id == signal_id && map.m_waiters[i].thread == thread) { diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 3e793c523d..09334171dc 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -71,6 +71,48 @@ public: bool joinable() const; }; +class s_mutex_t +{ + +}; + +class s_shared_mutex_t +{ + +}; + +class s_cond_var_t +{ + +//public: +// s_cond_var_t(); +// ~s_cond_var_t(); +// +// s_cond_var_t(s_cond_var_t& right) = delete; +// s_cond_var_t& operator = (s_cond_var_t& right) = delete; +// +// void wait(); +// void wait_for(); +// +// void notify(); +// void notify_all(); +}; + +class slw_mutex_t +{ + +}; + +class slw_recursive_mutex_t +{ + +}; + +class slw_shared_mutex_t +{ + +}; + class waiter_map_t { // TODO: optimize (use custom lightweight readers-writer lock) @@ -88,34 +130,43 @@ class waiter_map_t struct waiter_reg_t { + NamedThreadBase* thread; const u64 signal_id; - NamedThreadBase* const thread; waiter_map_t& map; - waiter_reg_t(waiter_map_t& map, u64 signal_id); + waiter_reg_t(waiter_map_t& map, u64 signal_id) + : thread(nullptr) + , signal_id(signal_id) + , map(map) + { + } + ~waiter_reg_t(); + + void init(); }; bool is_stopped(u64 signal_id); public: - waiter_map_t(const char* name) : m_name(name) {} + waiter_map_t(const char* name) + : m_name(name) + { + } // wait until waiter_func() returns true, signal_id is an arbitrary number template __forceinline void wait_op(u64 signal_id, const WT waiter_func) { - // check condition - if (waiter_func()) return; - // register waiter waiter_reg_t waiter(*this, signal_id); - while (true) + // check condition or if emulator is stopped + while (!waiter_func() && !is_stopped(signal_id)) { + // initialize waiter (only first time) + waiter.init(); // wait for 1 ms or until signal arrived waiter.thread->WaitForAnySignal(1); - if (is_stopped(signal_id)) break; - if (waiter_func()) break; } } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index a8899f250f..4617bdc8ac 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -568,10 +568,11 @@ s32 cellSyncQueueTryPush(vm::ptr queue, vm::ptr buffe assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); u32 position; - if (s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 + s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 { return syncQueueTryPushOp(queue, depth, position); - })) + }); + if (res) { return res; } @@ -657,10 +658,11 @@ s32 cellSyncQueueTryPop(vm::ptr queue, vm::ptr buffer) assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); u32 position; - if (s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 + s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 { return syncQueueTryPopOp(queue, depth, position); - })) + }); + if (res) { return res; } @@ -737,10 +739,11 @@ s32 cellSyncQueueTryPeek(vm::ptr queue, vm::ptr buffer) assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); u32 position; - if (s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 + s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 { return syncQueueTryPeekOp(queue, depth, position); - })) + }); + if (res) { return res; }