diff --git a/rpcs3/Emu/Cell/Modules/cellCamera.cpp b/rpcs3/Emu/Cell/Modules/cellCamera.cpp index e58a36672f..b833a1d790 100644 --- a/rpcs3/Emu/Cell/Modules/cellCamera.cpp +++ b/rpcs3/Emu/Cell/Modules/cellCamera.cpp @@ -1300,7 +1300,7 @@ void camera_context::operator()() 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; } @@ -1347,7 +1347,7 @@ void camera_context::send_attach_state(bool attached) 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; } diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index aed63e5c77..cce4834273 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -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()); - 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); - 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; } 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()); - 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 - 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; @@ -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); - ch_in_mbox.set_values(1, CELL_OK); - // Use the syscall to set flag - if (s32 res = sys_event_flag_set(data, 1ull << flag)) - { - ch_in_mbox.set_values(1, res); - } + const auto res = sys_event_flag_set(data, 1ull << flag); + ch_in_mbox.set_values(1, res); return true; } @@ -2904,11 +2889,17 @@ bool spu_thread::stop_and_signal(u32 code) if (!lv2_event_queue::check(queue)) { 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); + if (!queue->exists) + { + check_state(); + return ch_in_mbox.set_values(1, CELL_EINVAL), true; + } + if (queue->events.empty()) { queue->sq.emplace_back(this); @@ -2941,14 +2932,13 @@ bool spu_thread::stop_and_signal(u32 code) while (true) { - if (state & (cpu_flag::exit + cpu_flag::dbg_global_stop)) + if (is_stopped()) { + // The thread group cannot be stopped while waiting for an event + verify(HERE), !(state & cpu_flag::stop); return false; } - // The thread group cannot be stopped while waiting for an event - verify(HERE), !(state & cpu_flag::stop); - if (!state.test_and_reset(cpu_flag::signal)) { thread_ctrl::wait(); @@ -3028,6 +3018,11 @@ bool spu_thread::stop_and_signal(u32 code) std::lock_guard qlock(queue->mutex); + if (!queue->exists) + { + return ch_in_mbox.set_values(1, CELL_EINVAL), true; + } + if (queue->events.empty()) { return ch_in_mbox.set_values(1, CELL_EBUSY), true; diff --git a/rpcs3/Emu/Cell/lv2/sys_config.h b/rpcs3/Emu/Cell/lv2/sys_config.h index 77f5f4654a..97bc9cb5ba 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.h +++ b/rpcs3/Emu/Cell/lv2/sys_config.h @@ -180,7 +180,7 @@ private: { if (auto sptr = queue.lock()) { - return sptr->send(source, d1, d2, d3); + return sptr->send(source, d1, d2, d3) == CELL_OK; } return false; } diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index eab69b92c6..248edfe5d3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -43,20 +43,25 @@ bool lv2_event_queue::check(const std::shared_ptr& sptr) 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); + if (!exists) + { + return CELL_ENOTCONN; + } + if (sq.empty()) { if (events.size() < this->size + 0u) { // Save event events.emplace_back(event); - return true; + return {}; } - return false; + return CELL_EBUSY; } if (type == SYS_PPU_QUEUE) @@ -85,7 +90,7 @@ bool lv2_event_queue::send(lv2_event event) spu.notify(); } - return true; + return {}; } error_code sys_event_queue_create(vm::ptr equeue_id, vm::ptr 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}; - if (queue->send(source, data1, data2, data3)) - { - return {}; - } - - return CELL_EBUSY; + return queue->send(source, data1, data2, data3); } return CELL_ENOTCONN; diff --git a/rpcs3/Emu/Cell/lv2/sys_event.h b/rpcs3/Emu/Cell/lv2/sys_event.h index 3bef33a3cc..6679dced7a 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.h +++ b/rpcs3/Emu/Cell/lv2/sys_event.h @@ -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)); }