sys_event: Fix PPU queue forced uproot of waiters (#11147)

This commit is contained in:
Eladash 2021-11-13 19:22:54 +02:00 committed by GitHub
parent 05881ffa62
commit 48ad959697
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 6 deletions

View File

@ -133,6 +133,8 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
return CELL_EINVAL;
}
std::vector<lv2_event> events;
const auto queue = idm::withdraw<lv2_obj, lv2_event_queue>(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<cpu_thread*> 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::ptr<sy
std::lock_guard lock(queue->mutex);
if (!queue->exists)
{
return CELL_ESRCH;
}
s32 count = 0;
while (queue->sq.empty() && count < size && !queue->events.empty())

View File

@ -49,6 +49,8 @@ namespace logs
return reinterpret_cast<const channel*>(reinterpret_cast<uptr>(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 <typename... Args>
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)
{