mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 00:40:11 +00: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
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
|
extern atomic_t<u8>& get_resrv_waiters_count(u32 raddr);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
|
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)
|
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;
|
ppu.res_notify = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!notify)
|
|
||||||
{
|
{
|
||||||
// Try to postpone notification to when PPU is asleep or join notifications on the same address
|
// 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
|
// 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;
|
if (get_resrv_waiters_count(addr))
|
||||||
}
|
{
|
||||||
else if ((addr ^ notify) & -128)
|
ppu.res_notify = addr;
|
||||||
{
|
ppu.res_notify_time = rtime + 128;
|
||||||
res.notify_all();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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
|
// And on failure it has some time to do something else
|
||||||
if (notify && ((addr ^ notify) & -128))
|
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;
|
ppu.res_notify = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +262,8 @@ public:
|
|||||||
u64 rtime{0};
|
u64 rtime{0};
|
||||||
alignas(64) std::byte rdata[128]{}; // Reservation data
|
alignas(64) std::byte rdata[128]{}; // Reservation data
|
||||||
bool use_full_rdata{};
|
bool use_full_rdata{};
|
||||||
u32 res_notify{};
|
u32 res_notify{0};
|
||||||
|
u64 res_notify_time{0};
|
||||||
|
|
||||||
union ppu_prio_t
|
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 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)
|
// 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);
|
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;
|
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 (static_cast<ppu_thread&>(cpu).res_notify_time != (vm::reservation_acquire(addr) & -128))
|
||||||
|
{
|
||||||
if (notify_later_idx != umax)
|
// 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);
|
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;
|
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 (ppu->res_notify_time != (vm::reservation_acquire(addr) & -128))
|
||||||
|
{
|
||||||
if (notify_later_idx != umax)
|
// 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);
|
g_to_notify[notify_later_idx] = &vm::reservation_notifier(addr);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user