Savestates: Fix saving sys_event_queue_destroy

This commit is contained in:
Eladash 2022-07-07 05:03:16 +03:00 committed by Ivan
commit f0c71ae2ae
3 changed files with 28 additions and 15 deletions

View file

@ -1330,7 +1330,6 @@ static u32 spu_rdch(spu_thread* _spu, u32 ch)
if (result < 0 || _spu->state & cpu_flag::again) if (result < 0 || _spu->state & cpu_flag::again)
{ {
_spu->state += cpu_flag::again;
spu_runtime::g_escape(_spu); spu_runtime::g_escape(_spu);
} }
@ -2269,7 +2268,6 @@ static void spu_wrch_mfc(spu_thread* _spu)
{ {
if (!_spu->process_mfc_cmd() || _spu->state & cpu_flag::again) if (!_spu->process_mfc_cmd() || _spu->state & cpu_flag::again)
{ {
_spu->state += cpu_flag::again;
spu_runtime::g_escape(_spu); spu_runtime::g_escape(_spu);
} }

View file

@ -5588,7 +5588,6 @@ public:
if (result < 0 || _spu->state & cpu_flag::again) if (result < 0 || _spu->state & cpu_flag::again)
{ {
_spu->state += cpu_flag::again;
spu_runtime::g_escape(_spu); spu_runtime::g_escape(_spu);
} }
@ -5882,7 +5881,6 @@ public:
{ {
if (!_spu->set_ch_value(ch, value) || _spu->state & cpu_flag::again) if (!_spu->set_ch_value(ch, value) || _spu->state & cpu_flag::again)
{ {
_spu->state += cpu_flag::again;
spu_runtime::g_escape(_spu); spu_runtime::g_escape(_spu);
} }
@ -5906,7 +5904,6 @@ public:
{ {
if (!_spu->process_mfc_cmd() || _spu->state & cpu_flag::again) if (!_spu->process_mfc_cmd() || _spu->state & cpu_flag::again)
{ {
_spu->state += cpu_flag::again;
spu_runtime::g_escape(_spu); spu_runtime::g_escape(_spu);
} }

View file

@ -235,21 +235,17 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
std::vector<lv2_event> events; std::vector<lv2_event> events;
std::unique_lock<shared_mutex> qlock;
const auto queue = idm::withdraw<lv2_obj, lv2_event_queue>(equeue_id, [&](lv2_event_queue& queue) -> CellError const auto queue = idm::withdraw<lv2_obj, lv2_event_queue>(equeue_id, [&](lv2_event_queue& queue) -> CellError
{ {
std::lock_guard lock(queue.mutex); qlock.lock(queue.mutex);
if (!mode && !queue.sq.empty()) if (!mode && !queue.sq.empty())
{ {
return CELL_EBUSY; return CELL_EBUSY;
} }
if (queue.sq.empty())
{
// Optimization
mode = 0;
}
if (!queue.events.empty()) if (!queue.events.empty())
{ {
// Copy events for logging, does not empty // Copy events for logging, does not empty
@ -257,6 +253,23 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
} }
lv2_obj::on_id_destroy(queue, queue.key); lv2_obj::on_id_destroy(queue, queue.key);
if (queue.sq.empty())
{
qlock.unlock();
}
else
{
for (auto cpu : queue.sq)
{
if (cpu->state & cpu_flag::again)
{
ppu.state += cpu_flag::again;
return CELL_EAGAIN;
}
}
}
return {}; return {};
}); });
@ -265,6 +278,11 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (ppu.state & cpu_flag::again)
{
return {};
}
if (queue.ret) if (queue.ret)
{ {
return queue.ret; return queue.ret;
@ -272,12 +290,10 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
std::string lost_data; std::string lost_data;
if (mode == SYS_EVENT_QUEUE_DESTROY_FORCE) if (qlock.owns_lock())
{ {
std::deque<cpu_thread*> sq; std::deque<cpu_thread*> sq;
std::lock_guard lock(queue->mutex);
sq = std::move(queue->sq); sq = std::move(queue->sq);
if (sys_event.warning) if (sys_event.warning)
@ -309,6 +325,8 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
resume_spu_thread_group_from_waiting(static_cast<spu_thread&>(*cpu)); resume_spu_thread_group_from_waiting(static_cast<spu_thread&>(*cpu));
} }
} }
qlock.unlock();
} }
if (sys_event.warning) if (sys_event.warning)