Skip to content

Commit

Permalink
SPU: Optimize concurrent PUTLLUC
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Sep 12, 2020
1 parent 5585f6a commit f63824e
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 10 deletions.
4 changes: 2 additions & 2 deletions rpcs3/Emu/Cell/PPUThread.cpp
Expand Up @@ -1285,7 +1285,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, T reg_value)
}
}

if (res == ppu.rtime && vm::reservation_trylock(res, ppu.rtime))
if (res == ppu.rtime && vm::reservation_trylock(res, ppu.rtime).first)
{
if (data.compare_and_swap_test(old_data, reg_value))
{
Expand All @@ -1300,7 +1300,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, T reg_value)
return false;
}

if (!vm::reservation_trylock(res, ppu.rtime))
if (!vm::reservation_trylock(res, ppu.rtime).first)
{
return false;
}
Expand Down
31 changes: 29 additions & 2 deletions rpcs3/Emu/Cell/SPUThread.cpp
Expand Up @@ -1883,7 +1883,7 @@ bool spu_thread::do_putllc(const spu_mfc_cmd& args)
}
}

if (!vm::reservation_trylock(res, rtime))
if (!vm::reservation_trylock(res, rtime).first)
{
return false;
}
Expand Down Expand Up @@ -2003,7 +2003,34 @@ void spu_thread::do_putlluc(const spu_mfc_cmd& args)
else
{
auto& data = vm::_ref<decltype(rdata)>(addr);
auto [res, time0] = vm::reservation_lock(addr, 128);
auto& res = vm::reservation_acquire(addr, 128);

for(u64 time0 = UINT64_MAX & -128;;)
{
auto [ok, time1] = vm::reservation_trylock(res, res & -128, vm::putlluc_lockb);

if (time0 & vm::putlluc_lockb && time1 > time0)
{
// Other PUTLLUC completed, don't execute

if (ok)
{
res.release(time1 & -128);
}

return;
}

if (ok)
{
break;
}

if (time1 & vm::putlluc_lockb)
{
time0 = time1;
}
}

*reinterpret_cast<atomic_t<u32>*>(&data) += 0;

Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Memory/vm.cpp
Expand Up @@ -444,7 +444,7 @@ namespace vm
{
for (u64 i = 0;; i++)
{
if (u64 rtime = res; !(rtime & 127) && reservation_trylock(res, rtime, lock_bits)) [[likely]]
if (u64 rtime = res; !(rtime & 127) && reservation_trylock(res, rtime, lock_bits).first) [[likely]]
{
return rtime;
}
Expand Down
10 changes: 5 additions & 5 deletions rpcs3/Emu/Memory/vm_reservation.h
Expand Up @@ -40,22 +40,22 @@ namespace vm

u64 reservation_lock_internal(u32, atomic_t<u64>&, u64);

inline bool reservation_trylock(atomic_t<u64>& res, u64 rtime, u64 lock_bits = stcx_lockb)
inline std::pair<bool, u64> reservation_trylock(atomic_t<u64>& res, u64 rtime, u64 lock_bits = stcx_lockb)
{
if (res.compare_and_swap_test(rtime, rtime + lock_bits)) [[likely]]
if (res.compare_exchange(rtime, rtime + lock_bits)) [[likely]]
{
return true;
return {true, rtime};
}

return false;
return {false, rtime};
}

inline std::pair<atomic_t<u64>&, u64> reservation_lock(u32 addr, u32 size, u64 lock_bits = stcx_lockb)
{
auto res = &vm::reservation_acquire(addr, size);
auto rtime = res->load();

if (rtime & 127 || !reservation_trylock(*res, rtime, lock_bits)) [[unlikely]]
if (rtime & 127 || !reservation_trylock(*res, rtime, lock_bits).first) [[unlikely]]
{
static atomic_t<u64> no_lock{};

Expand Down

0 comments on commit f63824e

Please sign in to comment.