sys_event_queue: Fix forced event queue destruction

Add missing last existence check at sys_spu_thread_(try)receive_event and lv2_event_queue::send.
This commit is contained in:
Eladash 2020-05-02 11:22:28 +03:00 committed by Ivan
parent 37ce7056ac
commit edde748519
5 changed files with 39 additions and 44 deletions

View File

@ -1300,7 +1300,7 @@ void camera_context::operator()()
data3 = 0; // unused data3 = 0; // unused
} }
if (queue->send(evt_data.source, CELL_CAMERA_FRAME_UPDATE, data2, data3)) [[likely]] if (queue->send(evt_data.source, CELL_CAMERA_FRAME_UPDATE, data2, data3) == CELL_OK) [[likely]]
{ {
++frame_num; ++frame_num;
} }
@ -1347,7 +1347,7 @@ void camera_context::send_attach_state(bool attached)
if (auto queue = lv2_event_queue::find(key)) if (auto queue = lv2_event_queue::find(key))
{ {
if (queue->send(evt_data.source, attached ? CELL_CAMERA_ATTACH : CELL_CAMERA_DETACH, 0, 0)) [[likely]] if (queue->send(evt_data.source, attached ? CELL_CAMERA_ATTACH : CELL_CAMERA_DETACH, 0, 0) == CELL_OK) [[likely]]
{ {
is_attached = attached; is_attached = attached;
} }

View File

@ -2479,20 +2479,15 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
const auto queue = (std::lock_guard{group->mutex}, this->spup[spup].lock()); const auto queue = (std::lock_guard{group->mutex}, this->spup[spup].lock());
if (!lv2_event_queue::check(queue)) const auto res = !queue ? CELL_ENOTCONN :
queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data);
if (res == CELL_ENOTCONN)
{ {
spu_log.warning("sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (value & 0x00ffffff), data); spu_log.warning("sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (value & 0x00ffffff), data);
ch_in_mbox.set_values(1, CELL_ENOTCONN);
return true;
}
ch_in_mbox.set_values(1, CELL_OK);
if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data))
{
ch_in_mbox.set_values(1, CELL_EBUSY);
} }
ch_in_mbox.set_values(1, res);
return true; return true;
} }
else if (code < 128) else if (code < 128)
@ -2511,16 +2506,10 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
const auto queue = (std::lock_guard{group->mutex}, this->spup[spup].lock()); const auto queue = (std::lock_guard{group->mutex}, this->spup[spup].lock());
if (!lv2_event_queue::check(queue))
{
spu_log.warning("sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (value & 0x00ffffff), data);
return true;
}
// TODO: check passing spup value // TODO: check passing spup value
if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data)) if (auto res = queue ? queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data) : CELL_ENOTCONN)
{ {
spu_log.warning("sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (queue is full)", spup, (value & 0x00ffffff), data); spu_log.warning("sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (error=%s)", spup, (value & 0x00ffffff), data, res);
} }
return true; return true;
@ -2544,13 +2533,9 @@ 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); spu_log.trace("sys_event_flag_set_bit(id=%d, value=0x%x (flag=%d))", data, value, flag);
ch_in_mbox.set_values(1, CELL_OK);
// Use the syscall to set flag // Use the syscall to set flag
if (s32 res = sys_event_flag_set(data, 1ull << flag)) const auto res = sys_event_flag_set(data, 1ull << flag);
{
ch_in_mbox.set_values(1, res); ch_in_mbox.set_values(1, res);
}
return true; return true;
} }
@ -2904,11 +2889,17 @@ bool spu_thread::stop_and_signal(u32 code)
if (!lv2_event_queue::check(queue)) if (!lv2_event_queue::check(queue))
{ {
check_state(); check_state();
return ch_in_mbox.set_values(1, CELL_EINVAL), true; // TODO: check error value return ch_in_mbox.set_values(1, CELL_EINVAL), true;
} }
std::lock_guard qlock(queue->mutex); std::lock_guard qlock(queue->mutex);
if (!queue->exists)
{
check_state();
return ch_in_mbox.set_values(1, CELL_EINVAL), true;
}
if (queue->events.empty()) if (queue->events.empty())
{ {
queue->sq.emplace_back(this); queue->sq.emplace_back(this);
@ -2941,13 +2932,12 @@ bool spu_thread::stop_and_signal(u32 code)
while (true) while (true)
{ {
if (state & (cpu_flag::exit + cpu_flag::dbg_global_stop)) if (is_stopped())
{ {
return false;
}
// The thread group cannot be stopped while waiting for an event // The thread group cannot be stopped while waiting for an event
verify(HERE), !(state & cpu_flag::stop); verify(HERE), !(state & cpu_flag::stop);
return false;
}
if (!state.test_and_reset(cpu_flag::signal)) if (!state.test_and_reset(cpu_flag::signal))
{ {
@ -3028,6 +3018,11 @@ bool spu_thread::stop_and_signal(u32 code)
std::lock_guard qlock(queue->mutex); std::lock_guard qlock(queue->mutex);
if (!queue->exists)
{
return ch_in_mbox.set_values(1, CELL_EINVAL), true;
}
if (queue->events.empty()) if (queue->events.empty())
{ {
return ch_in_mbox.set_values(1, CELL_EBUSY), true; return ch_in_mbox.set_values(1, CELL_EBUSY), true;

View File

@ -180,7 +180,7 @@ private:
{ {
if (auto sptr = queue.lock()) if (auto sptr = queue.lock())
{ {
return sptr->send(source, d1, d2, d3); return sptr->send(source, d1, d2, d3) == CELL_OK;
} }
return false; return false;
} }

View File

@ -43,20 +43,25 @@ bool lv2_event_queue::check(const std::shared_ptr<lv2_event_queue>& sptr)
return sptr && sptr->exists; return sptr && sptr->exists;
} }
bool lv2_event_queue::send(lv2_event event) CellError lv2_event_queue::send(lv2_event event)
{ {
std::lock_guard lock(mutex); std::lock_guard lock(mutex);
if (!exists)
{
return CELL_ENOTCONN;
}
if (sq.empty()) if (sq.empty())
{ {
if (events.size() < this->size + 0u) if (events.size() < this->size + 0u)
{ {
// Save event // Save event
events.emplace_back(event); events.emplace_back(event);
return true; return {};
} }
return false; return CELL_EBUSY;
} }
if (type == SYS_PPU_QUEUE) if (type == SYS_PPU_QUEUE)
@ -85,7 +90,7 @@ bool lv2_event_queue::send(lv2_event event)
spu.notify(); spu.notify();
} }
return true; return {};
} }
error_code sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attribute_t> attr, u64 event_queue_key, s32 size) error_code sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attribute_t> attr, u64 event_queue_key, s32 size)
@ -514,12 +519,7 @@ error_code sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
{ {
const u64 source = port.name ? port.name : (s64{process_getpid()} << 32) | u64{eport_id}; const u64 source = port.name ? port.name : (s64{process_getpid()} << 32) | u64{eport_id};
if (queue->send(source, data1, data2, data3)) return queue->send(source, data1, data2, data3);
{
return {};
}
return CELL_EBUSY;
} }
return CELL_ENOTCONN; return CELL_ENOTCONN;

View File

@ -99,9 +99,9 @@ struct lv2_event_queue final : public lv2_obj
{ {
} }
bool send(lv2_event); CellError send(lv2_event);
bool send(u64 source, u64 d1, u64 d2, u64 d3) CellError send(u64 source, u64 d1, u64 d2, u64 d3)
{ {
return send(std::make_tuple(source, d1, d2, d3)); return send(std::make_tuple(source, d1, d2, d3));
} }