mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
vm::wait_op improved
Now it accepts thread_t and its descendants (but may require adding friend vm::waiter_lock_t class)
This commit is contained in:
parent
ff1f6d3d4f
commit
71a378a3fb
@ -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<std::string()> thread_name);
|
||||
|
||||
|
@ -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<std::mutex> 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()
|
||||
|
@ -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<bool()> 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<typename T> inline waiter_lock_t(T& thread, u32 addr, u32 size)
|
||||
: m_waiter(_add_waiter(static_cast<thread_t&>(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<typename F, typename... Args> auto wait_op(CPUThread& thread, u32 addr, u32 size, F pred, Args&&... args) -> decltype(static_cast<void>(pred(args...)))
|
||||
template<typename T, typename F, typename... Args> auto wait_op(T& thread, u32 addr, u32 size, F pred, Args&&... args) -> decltype(static_cast<void>(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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user