Skip to content

Commit

Permalink
SPU: Fix potential deadlock in event queue syscalls
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 authored and Nekotekina committed Sep 1, 2022
1 parent 5a0a5d9 commit fb01ed5
Showing 1 changed file with 34 additions and 18 deletions.
52 changes: 34 additions & 18 deletions rpcs3/Emu/Cell/SPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4431,19 +4431,27 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)

spu_log.trace("sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, value & 0x00ffffff, data);

std::lock_guard lock(group->mutex);
std::shared_ptr<lv2_event_queue> queue;
{
std::lock_guard lock(group->mutex);

if (ch_in_mbox.get_count())
{
// TODO: Check this
spu_log.error("sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): In_MBox is not empty (%d)", spup, (value & 0x00ffffff), data, ch_in_mbox.get_count());
ch_in_mbox.set_values(1, CELL_EBUSY);
return true;
}

const auto queue = this->spup[spup].get();
// Reserve a place in the inbound mailbox
ch_in_mbox.set_values(1, CELL_OK);
queue = this->spup[spup];
}

const auto res = ch_in_mbox.get_count() ? CELL_EBUSY :
!queue ? CELL_ENOTCONN :
const auto res = !queue ? CELL_ENOTCONN :
queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data);

if (ch_in_mbox.get_count())
{
spu_log.warning("sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): In_MBox is not empty (%d)", spup, (value & 0x00ffffff), data, ch_in_mbox.get_count());
}
else if (res == CELL_ENOTCONN)
if (res == CELL_ENOTCONN)
{
spu_log.warning("sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): error (%s)", spup, (value & 0x00ffffff), data, res);
}
Expand All @@ -4454,7 +4462,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
return false;
}

ch_in_mbox.set_values(1, res);
atomic_storage<u32>::release(ch_in_mbox.values.raw().value0, res);
return true;
}
else if (code < 128)
Expand Down Expand Up @@ -4501,23 +4509,31 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)

spu_log.trace("sys_event_flag_set_bit(id=%d, value=0x%x (flag=%d))", data, value, flag);

std::lock_guard lock(group->mutex);
{
std::lock_guard lock(group->mutex);

if (ch_in_mbox.get_count())
{
// TODO: Check this
spu_log.error("sys_event_flag_set_bit(value=0x%x (flag=%d)): In_MBox is not empty (%d)", value, flag, ch_in_mbox.get_count());
ch_in_mbox.set_values(1, CELL_EBUSY);
return true;
}

// Reserve a place in the inbound mailbox
ch_in_mbox.set_values(1, CELL_OK);
}

// Use the syscall to set flag
const auto res = ch_in_mbox.get_count() ? CELL_EBUSY : 0u + sys_event_flag_set(*this, data, 1ull << flag);
const auto res = 0u + sys_event_flag_set(*this, data, 1ull << flag);

if (res == CELL_EAGAIN)
{
ch_out_mbox.set_value(data);
return false;
}

if (res == CELL_EBUSY)
{
spu_log.warning("sys_event_flag_set_bit(value=0x%x (flag=%d)): In_MBox is not empty (%d)", value, flag, ch_in_mbox.get_count());
}

ch_in_mbox.set_values(1, res);
atomic_storage<u32>::release(ch_in_mbox.values.raw().value0, res);
return true;
}
else if (code == 192)
Expand Down

0 comments on commit fb01ed5

Please sign in to comment.