mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 15:31:26 +12:00
Exceptions passed to wait_op caller
This commit is contained in:
parent
a7668ff57f
commit
1519a2b468
1 changed files with 38 additions and 13 deletions
|
@ -212,23 +212,45 @@ namespace vm
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(thread->mutex);
|
std::lock_guard<std::mutex> lock(thread->mutex);
|
||||||
|
|
||||||
// check predicate
|
try
|
||||||
if (pred && pred())
|
|
||||||
{
|
{
|
||||||
// clear predicate and signal if succeeded
|
// test predicate
|
||||||
pred = nullptr;
|
if (!pred || !pred())
|
||||||
|
|
||||||
if (thread->Signal())
|
|
||||||
{
|
{
|
||||||
return true;
|
return false;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw EXCEPTION("Thread already signaled");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// catch exception thrown by predicate
|
||||||
|
auto exception = std::current_exception();
|
||||||
|
|
||||||
return false;
|
// set new predicate that will throw this exception from the original thread
|
||||||
|
pred = [exception]() -> bool
|
||||||
|
{
|
||||||
|
// rethrow exception
|
||||||
|
std::rethrow_exception(exception);
|
||||||
|
|
||||||
|
// dummy return value
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// signal unconditionally (may be already signaled)
|
||||||
|
thread->Signal();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear predicate if succeeded
|
||||||
|
pred = nullptr;
|
||||||
|
|
||||||
|
// signal if succeeded or an exception thrown
|
||||||
|
if (!thread->Signal())
|
||||||
|
{
|
||||||
|
throw EXCEPTION("Thread already signaled");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
waiter_lock_t::waiter_lock_t(CPUThread& thread, u32 addr, u32 size)
|
waiter_lock_t::waiter_lock_t(CPUThread& thread, u32 addr, u32 size)
|
||||||
|
@ -254,6 +276,9 @@ namespace vm
|
||||||
// if another thread called pred(), it must be removed
|
// if another thread called pred(), it must be removed
|
||||||
if (m_waiter->pred)
|
if (m_waiter->pred)
|
||||||
{
|
{
|
||||||
|
// pred() should rethrow exception caught by another thread
|
||||||
|
m_waiter->pred();
|
||||||
|
|
||||||
throw EXCEPTION("Unexpected");
|
throw EXCEPTION("Unexpected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,7 +304,7 @@ namespace vm
|
||||||
{
|
{
|
||||||
waiter_t& waiter = g_waiter_list[i];
|
waiter_t& waiter = g_waiter_list[i];
|
||||||
|
|
||||||
if (((waiter.addr ^ addr) & (mask & waiter.mask)) == 0 && waiter.thread)
|
if (((waiter.addr ^ addr) & (mask & waiter.mask)) == 0 && waiter.thread && waiter.pred)
|
||||||
{
|
{
|
||||||
waiter.try_notify();
|
waiter.try_notify();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue