SPU: Fix events ACK, minor optimizations (#8771)

This commit is contained in:
Eladash 2020-08-27 23:36:54 +03:00 committed by GitHub
parent 190822c2b2
commit 47b545282e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 39 deletions

View file

@ -2346,7 +2346,7 @@ bool spu_thread::process_mfc_cmd()
ch_mfc_cmd.cmd, ch_mfc_cmd.lsa, ch_mfc_cmd.eal, ch_mfc_cmd.tag, ch_mfc_cmd.size);
}
u32 spu_thread::get_events(bool waiting)
u32 spu_thread::get_events(u32 mask_hint)
{
const u32 mask1 = ch_event_mask;
@ -2356,36 +2356,29 @@ u32 spu_thread::get_events(bool waiting)
}
// Check reservation status and set SPU_EVENT_LR if lost
if (raddr && ((vm::reservation_acquire(raddr, sizeof(rdata)) & -128) != rtime || !cmp_rdata(rdata, vm::_ref<decltype(rdata)>(raddr))))
if (mask_hint & SPU_EVENT_LR && raddr && ((vm::reservation_acquire(raddr, sizeof(rdata)) & -128) != rtime || !cmp_rdata(rdata, vm::_ref<decltype(rdata)>(raddr))))
{
ch_event_stat |= SPU_EVENT_LR;
raddr = 0;
}
// SPU Decrementer Event on underflow (use the upper 32-bits to determine it)
if (const u64 res = (ch_dec_value - (get_timebased_time() - ch_dec_start_timestamp)) >> 32)
if (mask_hint & SPU_EVENT_TM)
{
// Set next event to the next time the decrementer underflows
ch_dec_start_timestamp -= res << 32;
if ((ch_event_stat & SPU_EVENT_TM) == 0)
if (const u64 res = (ch_dec_value - (get_timebased_time() - ch_dec_start_timestamp)) >> 32)
{
ch_event_stat |= SPU_EVENT_TM;
// Set next event to the next time the decrementer underflows
ch_dec_start_timestamp -= res << 32;
if ((ch_event_stat & SPU_EVENT_TM) == 0)
{
ch_event_stat |= SPU_EVENT_TM;
}
}
}
// Simple polling or polling with atomically set/removed SPU_EVENT_WAITING flag
return !waiting ? ch_event_stat & mask1 : ch_event_stat.atomic_op([&](u32& stat) -> u32
{
if (u32 res = stat & mask1)
{
stat &= ~SPU_EVENT_WAITING;
return res;
}
stat |= SPU_EVENT_WAITING;
return 0;
});
return ch_event_stat & mask1;
}
void spu_thread::set_events(u32 mask)
@ -2580,7 +2573,9 @@ s64 spu_thread::get_ch_value(u32 ch)
case SPU_RdEventStat:
{
u32 res = get_events();
const u32 mask1 = ch_event_mask;
u32 res = get_events(mask1);
if (res)
{
@ -2589,8 +2584,6 @@ s64 spu_thread::get_ch_value(u32 ch)
spu_function_logger logger(*this, "MFC Events read");
const u32 mask1 = ch_event_mask;
if (mask1 & SPU_EVENT_LR && raddr)
{
if (mask1 != SPU_EVENT_LR && mask1 != SPU_EVENT_LR + SPU_EVENT_TM)
@ -2599,7 +2592,7 @@ s64 spu_thread::get_ch_value(u32 ch)
fmt::throw_exception("Not supported: event mask 0x%x" HERE, mask1);
}
while (res = get_events(), !res)
while (res = get_events(mask1), !res)
{
state += cpu_flag::wait;
@ -2615,7 +2608,7 @@ s64 spu_thread::get_ch_value(u32 ch)
return res;
}
while (res = get_events(true), !res)
while (res = get_events(mask1), !res)
{
state += cpu_flag::wait;
@ -2928,6 +2921,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
case SPU_WrDec:
{
get_events(SPU_EVENT_TM); // Don't discard possibly occured old event
ch_dec_start_timestamp = get_timebased_time();
ch_dec_value = value;
return true;
@ -2941,6 +2935,8 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
case SPU_WrEventAck:
{
// "Collect" events before final acknowledgment
get_events(value);
ch_event_stat &= ~value;
return true;
}