mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-11 17:28:36 +12: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
3 changed files with 30 additions and 30 deletions
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
#include "Utilities/Thread.h"
|
#include "Utilities/Thread.h"
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
class waiter_lock_t;
|
||||||
|
}
|
||||||
|
|
||||||
enum CPUThreadType
|
enum CPUThreadType
|
||||||
{
|
{
|
||||||
CPU_THREAD_PPU,
|
CPU_THREAD_PPU,
|
||||||
|
@ -53,6 +58,8 @@ public:
|
||||||
using thread_t::is_current;
|
using thread_t::is_current;
|
||||||
using thread_t::get_thread_ctrl;
|
using thread_t::get_thread_ctrl;
|
||||||
|
|
||||||
|
friend vm::waiter_lock_t;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CPUThread(CPUThreadType type, const std::string& name, std::function<std::string()> thread_name);
|
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;
|
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);
|
std::lock_guard<std::mutex> lock(g_waiter_list_mutex);
|
||||||
|
|
||||||
|
@ -242,25 +242,18 @@ namespace vm
|
||||||
addr = 0;
|
addr = 0;
|
||||||
mask = ~0;
|
mask = ~0;
|
||||||
|
|
||||||
// signal thread (must not be signaled yet)
|
// signal thread
|
||||||
if (!thread->signal())
|
thread->cv.notify_one();
|
||||||
{
|
|
||||||
throw EXCEPTION("Thread already signaled");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
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()
|
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())
|
if (m_waiter->pred())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -270,15 +263,6 @@ namespace vm
|
||||||
|
|
||||||
m_waiter->thread->cv.wait(m_lock);
|
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()
|
waiter_lock_t::~waiter_lock_t()
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
const class thread_ctrl_t* get_current_thread_ctrl();
|
const class thread_ctrl_t* get_current_thread_ctrl();
|
||||||
|
|
||||||
class CPUThread;
|
class thread_t;
|
||||||
|
|
||||||
namespace vm
|
namespace vm
|
||||||
{
|
{
|
||||||
|
@ -38,13 +38,13 @@ namespace vm
|
||||||
{
|
{
|
||||||
u32 addr = 0;
|
u32 addr = 0;
|
||||||
u32 mask = ~0;
|
u32 mask = ~0;
|
||||||
CPUThread* thread = nullptr;
|
thread_t* thread = nullptr;
|
||||||
|
|
||||||
std::function<bool()> pred;
|
std::function<bool()> pred;
|
||||||
|
|
||||||
waiter_t() = default;
|
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->addr = addr;
|
||||||
this->mask = ~(size - 1);
|
this->mask = ~(size - 1);
|
||||||
|
@ -62,6 +62,9 @@ namespace vm
|
||||||
bool try_notify();
|
bool try_notify();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// for internal use
|
||||||
|
waiter_t* _add_waiter(thread_t& thread, u32 addr, u32 size);
|
||||||
|
|
||||||
class waiter_lock_t
|
class waiter_lock_t
|
||||||
{
|
{
|
||||||
waiter_t* m_waiter;
|
waiter_t* m_waiter;
|
||||||
|
@ -70,7 +73,11 @@ namespace vm
|
||||||
public:
|
public:
|
||||||
waiter_lock_t() = delete;
|
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
|
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
|
// 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)
|
// return immediately if condition passed (optimistic case)
|
||||||
if (pred(args...)) return;
|
if (pred(args...)) return;
|
||||||
|
@ -396,15 +403,14 @@ namespace vm
|
||||||
}
|
}
|
||||||
|
|
||||||
void close();
|
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_ref.h"
|
||||||
#include "vm_ptr.h"
|
#include "vm_ptr.h"
|
||||||
#include "vm_var.h"
|
#include "vm_var.h"
|
||||||
|
|
||||||
|
class CPUThread;
|
||||||
|
|
||||||
namespace vm
|
namespace vm
|
||||||
{
|
{
|
||||||
class stack
|
class stack
|
||||||
|
@ -439,4 +445,7 @@ namespace vm
|
||||||
return m_begin + m_position;
|
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…
Add table
Add a link
Reference in a new issue