mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 21:41:26 +12:00
sys_event_flag_set: Break atomic operation dependencies
This commit is contained in:
parent
a325eb52bd
commit
3ecb14dcda
1 changed files with 39 additions and 12 deletions
|
@ -357,16 +357,14 @@ error_code sys_event_flag_set(cpu_thread& cpu, u32 id, u64 bitptn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process all waiters in single atomic op
|
|
||||||
const u32 count = flag->pattern.atomic_op([&](u64& value)
|
|
||||||
{
|
|
||||||
value |= bitptn;
|
|
||||||
u32 count = 0;
|
u32 count = 0;
|
||||||
|
|
||||||
if (!flag->sq)
|
// Process all waiters in single atomic op
|
||||||
|
for (u64 pattern = flag->pattern, to_write = pattern, dependant_mask = 0;; to_write = pattern, dependant_mask = 0)
|
||||||
{
|
{
|
||||||
return count;
|
count = 0;
|
||||||
}
|
to_write |= bitptn;
|
||||||
|
dependant_mask = 0;
|
||||||
|
|
||||||
for (auto ppu = +flag->sq; ppu; ppu = ppu->next_cpu)
|
for (auto ppu = +flag->sq; ppu; ppu = ppu->next_cpu)
|
||||||
{
|
{
|
||||||
|
@ -405,10 +403,20 @@ error_code sys_event_flag_set(cpu_thread& cpu, u32 id, u64 bitptn)
|
||||||
const u64 pattern = ppu.gpr[4];
|
const u64 pattern = ppu.gpr[4];
|
||||||
const u64 mode = ppu.gpr[5];
|
const u64 mode = ppu.gpr[5];
|
||||||
|
|
||||||
if (lv2_event_flag::check_pattern(value, pattern, mode, &ppu.gpr[6]))
|
// If it's OR mode, set bits must have waken up the thread therefore no
|
||||||
|
// dependency on old value
|
||||||
|
const u64 dependant_mask_or = ((mode & 0xf) == SYS_EVENT_FLAG_WAIT_OR || (bitptn & pattern & to_write) == pattern ? 0 : pattern);
|
||||||
|
|
||||||
|
if (lv2_event_flag::check_pattern(to_write, pattern, mode, &ppu.gpr[6]))
|
||||||
{
|
{
|
||||||
|
dependant_mask |= dependant_mask_or;
|
||||||
ppu.gpr[3] = CELL_OK;
|
ppu.gpr[3] = CELL_OK;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
if (!to_write)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -416,9 +424,28 @@ error_code sys_event_flag_set(cpu_thread& cpu, u32 id, u64 bitptn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
auto [new_val, ok] = flag->pattern.fetch_op([&](u64& x)
|
||||||
|
{
|
||||||
|
if ((x ^ pattern) & dependant_mask)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
x |= bitptn;
|
||||||
|
|
||||||
|
// Clear the bit-wise difference
|
||||||
|
x &= ~((pattern | bitptn) & ~to_write);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern = new_val;
|
||||||
|
}
|
||||||
|
|
||||||
if (!count)
|
if (!count)
|
||||||
{
|
{
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue