mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-08 07:51:28 +12:00
PPU: Optimize reservation load for success
This commit is contained in:
parent
3419d15878
commit
f03d4cf8fd
1 changed files with 18 additions and 109 deletions
|
@ -1228,117 +1228,26 @@ static T ppu_load_acquire_reservation(ppu_thread& ppu, u32 addr)
|
||||||
ppu.last_faddr = 0;
|
ppu.last_faddr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip loop if already loaded
|
ppu.rtime = vm::reservation_acquire(addr, sizeof(T)) & -128;
|
||||||
for (u64 count = 0; count != umax; [&]()
|
|
||||||
{
|
|
||||||
if (ppu.state)
|
|
||||||
{
|
|
||||||
if (ppu.state & cpu_flag::pause)
|
|
||||||
{
|
|
||||||
auto& sdata = *vm::get_super_ptr<spu_rdata_t>(addr & -128);
|
|
||||||
|
|
||||||
verify(HERE), cpu_thread::if_suspended<-1>(&ppu, {}, [&]()
|
|
||||||
{
|
|
||||||
// Guaranteed success
|
|
||||||
ppu.rtime = vm::reservation_acquire(addr, sizeof(T));
|
|
||||||
mov_rdata_nt(ppu.rdata, sdata);
|
|
||||||
});
|
|
||||||
|
|
||||||
_mm_mfence();
|
|
||||||
|
|
||||||
// Exit loop
|
|
||||||
if ((ppu.rtime & 127) == 0)
|
|
||||||
{
|
|
||||||
count = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ppu.check_state();
|
|
||||||
}
|
|
||||||
else if (++count < 20) [[likely]]
|
|
||||||
{
|
|
||||||
busy_wait(300);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ppu.state += cpu_flag::wait;
|
|
||||||
std::this_thread::yield();
|
|
||||||
ppu.check_state();
|
|
||||||
}
|
|
||||||
}())
|
|
||||||
{
|
|
||||||
ppu.rtime = vm::reservation_acquire(addr, sizeof(T));
|
|
||||||
|
|
||||||
if (ppu.rtime & vm::rsrv_unique_lock)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
be_t<u64> rdata;
|
|
||||||
|
|
||||||
u64 test_mask = ~vm::rsrv_shared_mask;
|
|
||||||
|
|
||||||
if (ppu.use_full_rdata)
|
|
||||||
{
|
|
||||||
if (ppu.rtime & 127)
|
|
||||||
{
|
|
||||||
// Try to use TSX to obtain data atomically
|
|
||||||
if (!g_use_rtm || !spu_getllar_tx(addr & -128, ppu.rdata, &ppu, ppu.rtime & -128))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mov_rdata(ppu.rdata, vm::_ref<spu_rdata_t>(addr & -128));
|
|
||||||
|
|
||||||
// Check all bit changes
|
|
||||||
test_mask = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rdata = data.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((vm::reservation_acquire(addr, sizeof(T)) & test_mask) == (ppu.rtime & test_mask)) [[likely]]
|
|
||||||
{
|
|
||||||
if (!ppu.use_full_rdata)
|
|
||||||
{
|
|
||||||
if (ppu.rtime & 127)
|
|
||||||
{
|
|
||||||
// Let the ongoing operation some tiny time to complete
|
|
||||||
busy_wait(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.load() != rdata)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store only 64 bits of reservation data
|
|
||||||
std::memcpy(&ppu.rdata[addr & 0x78], &rdata, 8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Load relevant 64 bits of reservation data
|
|
||||||
std::memcpy(&rdata, &ppu.rdata[addr & 0x78], 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count >= 15 && g_cfg.core.perf_report) [[unlikely]]
|
|
||||||
{
|
|
||||||
perf_log.warning("%s: took too long: %u", sizeof(T) == 4 ? "LWARX" : "LDARX", count);
|
|
||||||
}
|
|
||||||
|
|
||||||
ppu.rtime &= ~vm::rsrv_shared_mask;
|
|
||||||
|
|
||||||
return static_cast<T>(rdata << data_off >> size_off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
be_t<u64> rdata;
|
be_t<u64> rdata;
|
||||||
std::memcpy(&rdata, &ppu.rdata[addr & 0x78], 8);
|
|
||||||
|
if (!ppu.use_full_rdata)
|
||||||
|
{
|
||||||
|
rdata = data.load();
|
||||||
|
|
||||||
|
// Store only 64 bits of reservation data
|
||||||
|
std::memcpy(&ppu.rdata[addr & 0x78], &rdata, 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mov_rdata(ppu.rdata, vm::_ref<spu_rdata_t>(addr & -128));
|
||||||
|
std::atomic_thread_fence(std::memory_order_acquire);
|
||||||
|
|
||||||
|
// Load relevant 64 bits of reservation data
|
||||||
|
std::memcpy(&rdata, &ppu.rdata[addr & 0x78], 8);
|
||||||
|
}
|
||||||
|
|
||||||
return static_cast<T>(rdata << data_off >> size_off);
|
return static_cast<T>(rdata << data_off >> size_off);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue