diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index 21727ec559..4470c813e3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -133,6 +133,8 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) return CELL_EINVAL; } + std::vector events; + const auto queue = idm::withdraw(equeue_id, [&](lv2_event_queue& queue) -> CellError { std::lock_guard lock(queue.mutex); @@ -142,6 +144,18 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) return CELL_EBUSY; } + if (queue.sq.empty()) + { + // Optimization + mode = 0; + } + + if (!queue.events.empty()) + { + // Copy events for logging, does not empty + events.insert(events.begin(), queue.events.begin(), queue.events.end()); + } + lv2_obj::on_id_destroy(queue, queue.key); return {}; }); @@ -156,6 +170,8 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) return queue.ret; } + std::string lost_data; + if (mode == SYS_EVENT_QUEUE_DESTROY_FORCE) { std::deque sq; @@ -163,7 +179,18 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) std::lock_guard lock(queue->mutex); sq = std::move(queue->sq); - + + if (sys_event.warning) + { + fmt::append(lost_data, "Forcefully awaken waiters (%u):\n", sq.size()); + + for (auto cpu : sq) + { + lost_data += cpu->get_name(); + lost_data += '\n'; + } + } + if (queue->type == SYS_PPU_QUEUE) { for (auto cpu : sq) @@ -172,10 +199,7 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) queue->append(cpu); } - if (!queue->sq.empty()) - { - lv2_obj::awake_all(); - } + lv2_obj::awake_all(); } else { @@ -187,6 +211,25 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) } } + if (sys_event.warning) + { + if (!events.empty()) + { + fmt::append(lost_data, "Unread queue events (%u):\n", events.size()); + } + + for (const lv2_event& evt : events) + { + fmt::append(lost_data, "data0=0x%x, data1=0x%x, data2=0x%x, data3=0x%x\n" + , std::get<0>(evt), std::get<1>(evt), std::get<2>(evt), std::get<3>(evt)); + } + + if (!lost_data.empty()) + { + sys_event.warning("sys_event_queue_destroy(): %s", lost_data); + } + } + return CELL_OK; } @@ -210,6 +253,11 @@ error_code sys_event_queue_tryreceive(ppu_thread& ppu, u32 equeue_id, vm::ptrmutex); + if (!queue->exists) + { + return CELL_ESRCH; + } + s32 count = 0; while (queue->sq.empty() && count < size && !queue->events.empty()) diff --git a/rpcs3/util/logs.hpp b/rpcs3/util/logs.hpp index 39ba189816..daaded35fd 100644 --- a/rpcs3/util/logs.hpp +++ b/rpcs3/util/logs.hpp @@ -49,6 +49,8 @@ namespace logs return reinterpret_cast(reinterpret_cast(this) & -16); } + inline explicit operator bool() const; + private: // Send log message to global logger instance void broadcast(const char*, const fmt_type_info*, ...) const; @@ -122,10 +124,16 @@ namespace logs #undef GEN_LOG_METHOD }; + inline logs::message::operator bool() const + { + // Test if enabled + return *this <= (*this)->enabled.observe(); + } + template FORCE_INLINE SAFE_BUFFERS(void) message::operator()(const const_str& fmt, const Args&... args) const { - if (*this <= (*this)->enabled.observe()) [[unlikely]] + if (operator bool()) [[unlikely]] { if constexpr (sizeof...(Args) > 0) {