mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-13 02:08:49 +12:00
SPU/PPU reservations: Optimizations part 1
- Implement vm::reservation_trylock, optimized locking on reservation stores with no waiting. Always fail if reservation lock bitsa are set. - Make SPU accurate GET transfers on non-TSX not modify reservation lock bits. - Add some optimization regarding to unmodified data reservations writes.
This commit is contained in:
parent
eb5ec211c2
commit
525453794f
3 changed files with 169 additions and 94 deletions
|
@ -1214,10 +1214,21 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, T reg_value)
|
|||
constexpr u64 size_off = (sizeof(T) * 8) & 63;
|
||||
|
||||
const T old_data = static_cast<T>(ppu.rdata << ((addr & 7) * 8) >> size_off);
|
||||
auto& res = vm::reservation_acquire(addr, sizeof(T));
|
||||
|
||||
if (ppu.raddr != addr || addr % sizeof(T) || old_data != data.load() || ppu.rtime != (vm::reservation_acquire(addr, sizeof(T)) & -128))
|
||||
if (std::exchange(ppu.raddr, 0) != addr || addr % sizeof(T) || old_data != data || ppu.rtime != res)
|
||||
{
|
||||
ppu.raddr = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reg_value == old_data)
|
||||
{
|
||||
if (res.compare_and_swap_test(ppu.rtime, ppu.rtime + 128))
|
||||
{
|
||||
res.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1230,27 +1241,21 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, T reg_value)
|
|||
case 0:
|
||||
{
|
||||
// Reservation lost
|
||||
ppu.raddr = 0;
|
||||
return false;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
vm::reservation_notifier(addr, sizeof(T)).notify_all();
|
||||
ppu.raddr = 0;
|
||||
res.notify_all();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
auto& res = vm::reservation_acquire(addr, sizeof(T));
|
||||
|
||||
ppu.raddr = 0;
|
||||
|
||||
if (res == ppu.rtime && res.compare_and_swap_test(ppu.rtime, ppu.rtime | 1))
|
||||
if (res == ppu.rtime && vm::reservation_trylock(res, ppu.rtime))
|
||||
{
|
||||
if (data.compare_and_swap_test(old_data, reg_value))
|
||||
{
|
||||
res += 127;
|
||||
vm::reservation_notifier(addr, sizeof(T)).notify_all();
|
||||
res.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1260,25 +1265,23 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, T reg_value)
|
|||
return false;
|
||||
}
|
||||
|
||||
vm::passive_unlock(ppu);
|
||||
if (!vm::reservation_trylock(res, ppu.rtime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& res = vm::reservation_lock(addr, sizeof(T));
|
||||
const u64 old_time = res.load() & -128;
|
||||
|
||||
const bool result = ppu.rtime == old_time && data.compare_and_swap_test(old_data, reg_value);
|
||||
const bool result = data.compare_and_swap_test(old_data, reg_value);
|
||||
|
||||
if (result)
|
||||
{
|
||||
res.release(old_time + 128);
|
||||
vm::reservation_notifier(addr, sizeof(T)).notify_all();
|
||||
res.release(ppu.rtime + 128);
|
||||
res.notify_all();
|
||||
}
|
||||
else
|
||||
{
|
||||
res.release(old_time);
|
||||
res.release(ppu.rtime);
|
||||
}
|
||||
|
||||
vm::passive_lock(ppu);
|
||||
ppu.raddr = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue