mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 20:22:30 +01:00
CELL: More efficient reservation notificatins
This commit is contained in:
parent
c71edc0719
commit
f948a80242
@ -3256,6 +3256,8 @@ const auto ppu_stcx_accurate_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime
|
||||
#endif
|
||||
});
|
||||
|
||||
extern atomic_t<u8>& get_resrv_waiters_count(u32 raddr);
|
||||
|
||||
template <typename T>
|
||||
static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
|
||||
{
|
||||
@ -3500,19 +3502,30 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
|
||||
|
||||
if (notify)
|
||||
{
|
||||
vm::reservation_notifier(notify).notify_all();
|
||||
bool notified = false;
|
||||
|
||||
if (ppu.res_notify_time == (vm::reservation_acquire(notify) & -128))
|
||||
{
|
||||
vm::reservation_notifier(notify).notify_all();
|
||||
notified = true;
|
||||
}
|
||||
|
||||
if (!notified || (addr ^ notify) & -128)
|
||||
{
|
||||
res.notify_all();
|
||||
}
|
||||
|
||||
ppu.res_notify = 0;
|
||||
}
|
||||
|
||||
if (!notify)
|
||||
else
|
||||
{
|
||||
// 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
|
||||
ppu.res_notify = addr;
|
||||
}
|
||||
else if ((addr ^ notify) & -128)
|
||||
{
|
||||
res.notify_all();
|
||||
if (get_resrv_waiters_count(addr))
|
||||
{
|
||||
ppu.res_notify = addr;
|
||||
ppu.res_notify_time = rtime + 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3531,7 +3544,11 @@ 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))
|
||||
{
|
||||
vm::reservation_notifier(notify).notify_all();
|
||||
if (ppu.res_notify_time == (vm::reservation_acquire(notify) & -128))
|
||||
{
|
||||
vm::reservation_notifier(notify).notify_all();
|
||||
}
|
||||
|
||||
ppu.res_notify = 0;
|
||||
}
|
||||
|
||||
|
@ -262,7 +262,8 @@ public:
|
||||
u64 rtime{0};
|
||||
alignas(64) std::byte rdata[128]{}; // Reservation data
|
||||
bool use_full_rdata{};
|
||||
u32 res_notify{};
|
||||
u32 res_notify{0};
|
||||
u64 res_notify_time{0};
|
||||
|
||||
union ppu_prio_t
|
||||
{
|
||||
|
@ -446,10 +446,10 @@ waitpkg_func static void __tpause(u32 cycles, u32 cstate)
|
||||
|
||||
static std::array<atomic_t<u8>, 128> g_resrv_waiters_count;
|
||||
|
||||
static inline atomic_t<u8>& get_resrv_waiters_count(u32 raddr)
|
||||
extern atomic_t<u8>& get_resrv_waiters_count(u32 raddr)
|
||||
{
|
||||
// Storage efficient method to distinguish different nearby addresses (which are likely)
|
||||
return g_resrv_waiters_count[std::popcount(raddr) + ((raddr / 128) % 4) * 32];
|
||||
return g_resrv_waiters_count[std::popcount(raddr & -512) + ((raddr / 128) % 4) * 32];
|
||||
}
|
||||
|
||||
void do_cell_atomic_128_store(u32 addr, const void* to_write);
|
||||
|
@ -1333,9 +1333,12 @@ bool lv2_obj::sleep(cpu_thread& cpu, const u64 timeout)
|
||||
{
|
||||
static_cast<ppu_thread&>(cpu).res_notify = 0;
|
||||
|
||||
const usz notify_later_idx = std::basic_string_view<const void*>{g_to_notify, std::size(g_to_notify)}.find_first_of(std::add_pointer_t<const void>{});
|
||||
|
||||
if (notify_later_idx != umax)
|
||||
if (static_cast<ppu_thread&>(cpu).res_notify_time != (vm::reservation_acquire(addr) & -128))
|
||||
{
|
||||
// Ignore outdated notification request
|
||||
}
|
||||
else if (usz notify_later_idx = std::basic_string_view<const void*>{g_to_notify, std::size(g_to_notify)}.find_first_of(std::add_pointer_t<const void>{});
|
||||
notify_later_idx != umax)
|
||||
{
|
||||
g_to_notify[notify_later_idx] = &vm::reservation_notifier(addr);
|
||||
|
||||
@ -1384,9 +1387,12 @@ bool lv2_obj::awake(cpu_thread* thread, s32 prio)
|
||||
{
|
||||
ppu->res_notify = 0;
|
||||
|
||||
const usz notify_later_idx = std::basic_string_view<const void*>{g_to_notify, std::size(g_to_notify)}.find_first_of(std::add_pointer_t<const void>{});
|
||||
|
||||
if (notify_later_idx != umax)
|
||||
if (ppu->res_notify_time != (vm::reservation_acquire(addr) & -128))
|
||||
{
|
||||
// Ignore outdated notification request
|
||||
}
|
||||
else if (usz notify_later_idx = std::basic_string_view<const void*>{g_to_notify, std::size(g_to_notify)}.find_first_of(std::add_pointer_t<const void>{});
|
||||
notify_later_idx != umax)
|
||||
{
|
||||
g_to_notify[notify_later_idx] = &vm::reservation_notifier(addr);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user