From 045ec84fe408373a4182165a7fe18fbc40c8f8af Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Fri, 9 Oct 2026 09:32:50 -0700 Subject: [PATCH] ppcexec: Avoid excessive timer polling in realtime mode When the interpreter can run faster than realtime (depends on the host system's performance), we would end up checking timer more frequently. This is because the `max_cycles` value returned by `process_events()` was based on the absolute timer deadline converted to instruction counts. Once `g_icycles` got ahead of that value, we would check timers after every instruction. Instead, use the time remaining until the next timer to schedule an instruction batch relative to `g_icycles`, capped using the existing 500us polling interval. --- cpu/ppc/ppcexec.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index 3248165486..8704ab26fa 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -364,16 +364,32 @@ void set_virt_time_ns(uint64_t time_now) LOG_F(INFO, "time before: %lld after: %lld change: %lld", time_now, time_new, time_new - time_now); } +static constexpr uint64_t TIMER_POLL_INTERVAL_NS = 500'000; + static uint64_t process_events() { exec_timer = false; uint64_t next_ns = TimerManager::get_instance()->process_timers(); + if (g_realtime) { + uint64_t time_now = get_virt_time_ns(); + uint64_t delay_ns; + if (next_ns) { + delay_ns = next_ns > time_now ? next_ns - time_now : 0; + } else { + delay_ns = TIMER_POLL_INTERVAL_NS; + } + // Host time and the instruction counter advance independently. Schedule + // a relative instruction batch, capped so long deadlines still poll. + // Comparing an absolute wall-time deadline with g_icycles can otherwise + // make a fast interpreter process timers after every instruction. + return g_icycles + (std::min(delay_ns, TIMER_POLL_INTERVAL_NS) >> icnt_factor) + 1; + } return ( ( next_ns ? next_ns : - TimerManager::get_instance()->current_time_ns() + 500'000 + TimerManager::get_instance()->current_time_ns() + TIMER_POLL_INTERVAL_NS ) >> icnt_factor ) + 1; }