CELL: Rewrite reservation notification postponing

This commit is contained in:
Elad 2024-11-30 10:46:33 +02:00
parent 729826ec40
commit a4ea71d18f
6 changed files with 60 additions and 33 deletions

View file

@ -3541,49 +3541,62 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
// Avoid notifications from lwmutex or sys_spinlock
if (new_data != old_data && (ppu.cia < liblv2_begin || ppu.cia >= liblv2_end))
{
const u32 notify = ppu.res_notify;
u32 notify = ppu.res_notify;
if (notify)
{
bool notified = false;
if (ppu.res_notify_time == (vm::reservation_acquire(notify) & -128))
if (ppu.res_notify_time == vm::reservation_notifier_count_index(notify).second)
{
ppu.state += cpu_flag::wait;
vm::reservation_notifier_notify(notify);
notified = true;
}
if (vm::reservation_notifier_count(addr))
{
if (!notified)
{
ppu.res_notify = addr;
ppu.res_notify_time = rtime + 128;
}
else if ((addr ^ notify) & -128)
{
vm::reservation_notifier_notify(addr);
ppu.res_notify = 0;
}
}
else
{
ppu.res_notify = 0;
notify = 0;
}
static_cast<void>(ppu.test_stopped());
ppu.res_notify = 0;
}
else
if ((addr ^ notify) & -128)
{
// Try to postpone notification to when PPU is asleep or join notifications on the same address
// This also optimizes a mutex - won't notify after lock is aqcuired (prolonging the critical section duration), only notifies on unlock
if (vm::reservation_notifier_count(addr))
const auto [count, index] = vm::reservation_notifier_count_index(addr);
switch (count)
{
ppu.res_notify = addr;
ppu.res_notify_time = rtime + 128;
case 0:
{
// Nothing to do
break;
}
case 1:
{
if (!notify)
{
ppu.res_notify = addr;
ppu.res_notify_time = index;
break;
}
// Notify both
[[fallthrough]];
}
default:
{
if (!notify)
{
ppu.state += cpu_flag::wait;
}
vm::reservation_notifier_notify(addr);
break;
}
}
}
static_cast<void>(ppu.test_stopped());
}
if (addr == ppu.last_faddr)
@ -3601,7 +3614,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
// And on failure it has some time to do something else
if (notify && ((addr ^ notify) & -128))
{
if (ppu.res_notify_time == (vm::reservation_acquire(notify) & -128))
if (ppu.res_notify_time == vm::reservation_notifier_count_index(notify).second)
{
ppu.state += cpu_flag::wait;
vm::reservation_notifier_notify(notify);