diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index dac76e1b3c..b43f9ad805 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -2,6 +2,11 @@ #include "Utilities/Thread.h" +namespace vm +{ + class waiter_lock_t; +} + enum CPUThreadType { CPU_THREAD_PPU, @@ -53,6 +58,8 @@ public: using thread_t::is_current; using thread_t::get_thread_ctrl; + friend vm::waiter_lock_t; + protected: CPUThread(CPUThreadType type, const std::string& name, std::function thread_name); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 14f891a683..29b5dc0945 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -152,7 +152,7 @@ namespace vm std::mutex g_waiter_list_mutex; - waiter_t* _add_waiter(CPUThread& thread, u32 addr, u32 size) + waiter_t* _add_waiter(thread_t& thread, u32 addr, u32 size) { std::lock_guard lock(g_waiter_list_mutex); @@ -242,25 +242,18 @@ namespace vm addr = 0; mask = ~0; - // signal thread (must not be signaled yet) - if (!thread->signal()) - { - throw EXCEPTION("Thread already signaled"); - } + // signal thread + thread->cv.notify_one(); return true; } - waiter_lock_t::waiter_lock_t(CPUThread& thread, u32 addr, u32 size) - : m_waiter(_add_waiter(thread, addr, size)) - , m_lock(thread.mutex, std::adopt_lock) // must be locked in _add_waiter - { - } - void waiter_lock_t::wait() { - while (!m_waiter->thread->unsignal()) + // if another thread successfully called pred(), it must be set to null + while (m_waiter->pred) { + // if pred() called by another thread threw an exception, it'll be rethrown if (m_waiter->pred()) { return; @@ -270,15 +263,6 @@ namespace vm m_waiter->thread->cv.wait(m_lock); } - - // if another thread successfully called pred(), it must be set to null - if (m_waiter->pred) - { - // if pred() called by another thread threw an exception, rethrow it - m_waiter->pred(); - - throw EXCEPTION("Unexpected"); - } } waiter_lock_t::~waiter_lock_t() diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index a39e76b00f..30ef47076e 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -4,7 +4,7 @@ const class thread_ctrl_t* get_current_thread_ctrl(); -class CPUThread; +class thread_t; namespace vm { @@ -38,13 +38,13 @@ namespace vm { u32 addr = 0; u32 mask = ~0; - CPUThread* thread = nullptr; + thread_t* thread = nullptr; std::function pred; waiter_t() = default; - waiter_t* reset(u32 addr, u32 size, CPUThread& thread) + waiter_t* reset(u32 addr, u32 size, thread_t& thread) { this->addr = addr; this->mask = ~(size - 1); @@ -62,6 +62,9 @@ namespace vm bool try_notify(); }; + // for internal use + waiter_t* _add_waiter(thread_t& thread, u32 addr, u32 size); + class waiter_lock_t { waiter_t* m_waiter; @@ -70,7 +73,11 @@ namespace vm public: waiter_lock_t() = delete; - waiter_lock_t(CPUThread& thread, u32 addr, u32 size); + template inline waiter_lock_t(T& thread, u32 addr, u32 size) + : m_waiter(_add_waiter(static_cast(thread), addr, size)) + , m_lock(thread.mutex, std::adopt_lock) // must be locked in _add_waiter + { + } waiter_t* operator ->() const { @@ -83,7 +90,7 @@ namespace vm }; // wait until pred() returns true, addr must be aligned to size which must be a power of 2, pred() may be called by any thread - template auto wait_op(CPUThread& thread, u32 addr, u32 size, F pred, Args&&... args) -> decltype(static_cast(pred(args...))) + template auto wait_op(T& thread, u32 addr, u32 size, F pred, Args&&... args) -> decltype(static_cast(pred(args...))) { // return immediately if condition passed (optimistic case) if (pred(args...)) return; @@ -396,15 +403,14 @@ namespace vm } void close(); - - u32 stack_push(CPUThread& CPU, u32 size, u32 align, u32& old_pos); - void stack_pop(CPUThread& CPU, u32 addr, u32 old_pos); } #include "vm_ref.h" #include "vm_ptr.h" #include "vm_var.h" +class CPUThread; + namespace vm { class stack @@ -439,4 +445,7 @@ namespace vm return m_begin + m_position; } }; + + u32 stack_push(CPUThread& cpu, u32 size, u32 align, u32& old_pos); + void stack_pop(CPUThread& cpu, u32 addr, u32 old_pos); }