mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 06:51:26 +12:00
CPU: Improve suspend_all g_suspend_counter handling
Increase in two stages, giving more chances to use it. Second stage is when all wait flags have been seen.
This commit is contained in:
parent
083397a555
commit
cdaa8cb5c4
2 changed files with 30 additions and 32 deletions
|
@ -587,10 +587,19 @@ bool cpu_thread::check_state() noexcept
|
||||||
{
|
{
|
||||||
bool store = false;
|
bool store = false;
|
||||||
|
|
||||||
if (flags & cpu_flag::pause && !(flags & cpu_flag::wait))
|
if (flags & cpu_flag::pause)
|
||||||
{
|
{
|
||||||
// Save value before state is saved and cpu_flag::wait is observed
|
// Save value before state is saved and cpu_flag::wait is observed
|
||||||
susp_ctr = g_suspend_counter;
|
susp_ctr = g_suspend_counter;
|
||||||
|
|
||||||
|
if (susp_ctr & 1 && flags & cpu_flag::wait)
|
||||||
|
{
|
||||||
|
susp_ctr = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
susp_ctr = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & cpu_flag::temp) [[unlikely]]
|
if (flags & cpu_flag::temp) [[unlikely]]
|
||||||
|
@ -705,29 +714,16 @@ bool cpu_thread::check_state() noexcept
|
||||||
// If only cpu_flag::pause was set, wait on suspend counter instead
|
// If only cpu_flag::pause was set, wait on suspend counter instead
|
||||||
if (state0 & cpu_flag::pause)
|
if (state0 & cpu_flag::pause)
|
||||||
{
|
{
|
||||||
if (state0 & cpu_flag::wait)
|
|
||||||
{
|
|
||||||
// Otherwise, value must be reliable because cpu_flag::wait hasn't been observed yet
|
|
||||||
susp_ctr = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hard way
|
|
||||||
if (susp_ctr == umax) [[unlikely]]
|
|
||||||
{
|
|
||||||
g_fxo->get<cpu_counter>()->cpu_suspend_lock.lock_unlock();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for current suspend_all operation
|
// Wait for current suspend_all operation
|
||||||
for (u64 i = 0;; i++)
|
for (u64 i = 0;; i++)
|
||||||
{
|
{
|
||||||
if (i < 20)
|
if (i < 20 || susp_ctr & 1)
|
||||||
{
|
{
|
||||||
busy_wait(300);
|
busy_wait(300);
|
||||||
}
|
}
|
||||||
else
|
else if (g_suspend_counter.load() >> 1 >= susp_ctr >> 1)
|
||||||
{
|
{
|
||||||
g_suspend_counter.wait(susp_ctr);
|
g_suspend_counter.wait(susp_ctr, -2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(state & cpu_flag::pause))
|
if (!(state & cpu_flag::pause))
|
||||||
|
@ -907,6 +903,8 @@ bool cpu_thread::suspend_work::push(cpu_thread* _this, bool cancel_if_not_suspen
|
||||||
_mm_pause();
|
_mm_pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_suspend_counter++;
|
||||||
|
|
||||||
// Extract queue and reverse element order (FILO to FIFO) (TODO: maybe leave order as is?)
|
// Extract queue and reverse element order (FILO to FIFO) (TODO: maybe leave order as is?)
|
||||||
auto* head = queue.exchange(nullptr);
|
auto* head = queue.exchange(nullptr);
|
||||||
|
|
||||||
|
@ -959,11 +957,8 @@ bool cpu_thread::suspend_work::push(cpu_thread* _this, bool cancel_if_not_suspen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not sure if needed, may be overkill. Some workloads may execute instructions with non-temporal hint.
|
// Finalization (second increment)
|
||||||
_mm_sfence();
|
verify(HERE), g_suspend_counter++ & 1;
|
||||||
|
|
||||||
// Finalization
|
|
||||||
g_suspend_counter++;
|
|
||||||
|
|
||||||
// Exact bitset for flag pause removal
|
// Exact bitset for flag pause removal
|
||||||
std::memcpy(ctr->cpu_copy_bits, copy2, sizeof(copy2));
|
std::memcpy(ctr->cpu_copy_bits, copy2, sizeof(copy2));
|
||||||
|
|
|
@ -1996,18 +1996,22 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
|
||||||
{
|
{
|
||||||
if (_cpu->state & cpu_flag::pause)
|
if (_cpu->state & cpu_flag::pause)
|
||||||
{
|
{
|
||||||
cpu_thread::if_suspended<0>(_cpu, {dst, dst + 64, &res}, [&]
|
const bool ok = cpu_thread::if_suspended<0>(_cpu, {dst, dst + 64, &res}, [&]
|
||||||
{
|
{
|
||||||
std::memcpy(dst, src, size0);
|
std::memcpy(dst, src, size0);
|
||||||
res += 128;
|
res += 128;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
// Exit loop and function
|
// Exit loop and function
|
||||||
i = -1;
|
i = -1;
|
||||||
bits = nullptr;
|
bits = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (++i < 10)
|
}
|
||||||
|
|
||||||
|
if (++i < 10)
|
||||||
{
|
{
|
||||||
busy_wait(500);
|
busy_wait(500);
|
||||||
}
|
}
|
||||||
|
@ -2941,18 +2945,17 @@ bool spu_thread::process_mfc_cmd()
|
||||||
{
|
{
|
||||||
auto& sdata = *vm::get_super_ptr<spu_rdata_t>(addr);
|
auto& sdata = *vm::get_super_ptr<spu_rdata_t>(addr);
|
||||||
|
|
||||||
cpu_thread::if_suspended<0>(this, {}, [&]
|
const bool ok = cpu_thread::if_suspended<0>(this, {&ntime}, [&]
|
||||||
{
|
{
|
||||||
// Guaranteed success
|
// Guaranteed success
|
||||||
ntime = vm::reservation_acquire(addr, 128);
|
ntime = vm::reservation_acquire(addr, 128);
|
||||||
mov_rdata_nt(rdata, sdata);
|
mov_rdata_nt(rdata, sdata);
|
||||||
});
|
});
|
||||||
|
|
||||||
_mm_mfence();
|
|
||||||
|
|
||||||
// Exit loop
|
// Exit loop
|
||||||
if ((ntime & 127) == 0)
|
if (ok && (ntime & 127) == 0)
|
||||||
{
|
{
|
||||||
|
_mm_mfence();
|
||||||
i = -1;
|
i = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue