mirror of
https://github.com/ARMSX2/ARMSX3.git
synced 2026-08-24 16:58:52 -07:00
Spin detector: a wait sample skips, it does not reset
Erasing the tracked state whenever cpu_flag::wait was set is what stopped this firing. The loop dips into a syscall regularly -- almost certainly sys_ppu_thread_yield, seen at ~100 million -- and every dip cleared the accumulated seconds, so the counter never got past 2. The device reported it precisely once the range was instrumented: widest_range=0x0, meaning an identical cia on every single sample. As tight a spin as can exist, and invisible purely because of that erase. A wait sample is now skipped rather than treated as evidence against a spin. A thread genuinely parked in a syscall never accumulates running samples at all, so idle threads still cannot trip it.
This commit is contained in:
@@ -1288,11 +1288,18 @@ public:
|
||||
|
||||
idm::select<named_thread<ppu_thread>>([&](u32 id, ppu_thread& ppu)
|
||||
{
|
||||
// Only threads actually executing. cpu_flag::wait means parked in a
|
||||
// syscall, which is the ordinary way for a thread to sit still.
|
||||
// A wait sample is SKIPPED, not a reset.
|
||||
//
|
||||
// Erasing here was the bug: this loop dips into a syscall regularly --
|
||||
// almost certainly sys_ppu_thread_yield, which was running at ~100M --
|
||||
// and every dip cleared the accumulated state, so the counter never got
|
||||
// past 2s. Measured with widest_range=0x0, i.e. an identical cia on every
|
||||
// sample: as tight a spin as exists, and invisible because of this line.
|
||||
//
|
||||
// A thread genuinely parked in a syscall simply never accumulates running
|
||||
// samples, so idle threads still cannot trip the detector.
|
||||
if (!ppu.state.load().none_of(cpu_flag::wait))
|
||||
{
|
||||
s_spin.erase(id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user