From ed6ea61283ca69940c3f586c3f5d173a7d1d7dfc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 27 Apr 2014 15:52:36 -0700 Subject: [PATCH] Fix deadlock in multithreading. Fixes #5971. --- Core/HLE/sceGe.cpp | 73 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 2636e0c290..dadf984534 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -49,8 +49,71 @@ struct GeInterruptData u32 cmd; }; -static recursive_mutex ge_pending_lock; -static std::list ge_pending_cb; +template < typename T, class Alloc = std::allocator > +class ThreadSafeList { +public: + explicit ThreadSafeList(const Alloc &a = Alloc()) : list(a) {} + explicit ThreadSafeList(std::size_t n, const T &v = T(), const Alloc &a = Alloc()) : list(n, v, a) {} + ThreadSafeList(const std::list &other) : list(other) {} + ThreadSafeList(const ThreadSafeList &other) { + lock_guard guard(other.lock); + list.assign(other.list); + } + + template + ThreadSafeList(Iter first, Iter last, const Alloc &a = Alloc()) : list(first, last, a) {} + + inline T front() const { + lock_guard guard(lock); + return list.front(); + } + + inline void pop_front() { + lock_guard guard(lock); + return list.pop_front(); + } + + inline void push_front(const T &v) { + lock_guard guard(lock); + return list.push_front(v); + } + + inline T back() const { + lock_guard guard(lock); + return list.back(); + } + + inline void pop_back() { + lock_guard guard(lock); + return list.pop_back(); + } + + inline void push_back(const T &v) { + lock_guard guard(lock); + return list.push_back(v); + } + + bool empty() const { + lock_guard guard(lock); + return list.empty(); + } + + inline void clear() { + lock_guard guard(lock); + return list.clear(); + } + + void DoState(PointerWrap &p) { + lock_guard guard(lock); + p.Do(list); + } + +private: + mutable recursive_mutex lock; + std::list list; +}; + +static ThreadSafeList ge_pending_cb; static int geSyncEvent; static int geInterruptEvent; static int geCycleEvent; @@ -66,7 +129,6 @@ public: bool run(PendingInterrupt& pend) { - lock_guard guard(ge_pending_lock); GeInterruptData intrdata = ge_pending_cb.front(); DisplayList* dl = gpu->getList(intrdata.listid); @@ -142,7 +204,6 @@ public: virtual void handleResult(PendingInterrupt& pend) { - lock_guard guard(ge_pending_lock); GeInterruptData intrdata = ge_pending_cb.front(); ge_pending_cb.pop_front(); @@ -206,7 +267,6 @@ void __GeCheckCycles(u64 userdata, int cyclesLate) void __GeInit() { - lock_guard guard(ge_pending_lock); memset(&ge_used_callbacks, 0, sizeof(ge_used_callbacks)); ge_pending_cb.clear(); __RegisterIntrHandler(PSP_GE_INTR, new GeIntrHandler()); @@ -236,8 +296,6 @@ void __GeDoState(PointerWrap &p) if (!s) return; - lock_guard guard(ge_pending_lock); - p.DoArray(ge_callback_data, ARRAY_SIZE(ge_callback_data)); p.DoArray(ge_used_callbacks, ARRAY_SIZE(ge_used_callbacks)); @@ -295,7 +353,6 @@ bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) intrdata.pc = pc; intrdata.cmd = Memory::ReadUnchecked_U32(pc - 4) >> 24; - lock_guard guard(ge_pending_lock); ge_pending_cb.push_back(intrdata); u64 userdata = (u64)listid << 32 | (u64) pc;