The timer must be rearmed if a new timeout is added at the start of the timeout list (or the new timeout will be expired too late.) However, as the rearming always happens after servicing expired timers, do not rearm in that case.
Also, move the setting of the dirty flag outside conditional in host_alarm_handler(), to make sure it is always done. This broke kvm. Cheers, Anders.
diff --git a/vl.c b/vl.c index 129166d..a7d9021 100644 --- a/vl.c +++ b/vl.c @@ -822,7 +822,7 @@ struct qemu_alarm_timer { }; #define ALARM_FLAG_DYNTICKS 0x1 -#define ALARM_FLAG_MODIFIED 0x2 +#define ALARM_FLAG_EXPIRED 0x2 static inline int alarm_has_dynticks(struct qemu_alarm_timer *t) { @@ -834,11 +834,6 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t) if (!alarm_has_dynticks(t)) return; - if (!(t->flags & ALARM_FLAG_MODIFIED)) - return; - - t->flags &= ~(ALARM_FLAG_MODIFIED); - t->rearm(t); } @@ -1001,8 +996,6 @@ void qemu_del_timer(QEMUTimer *ts) { QEMUTimer **pt, *t; - alarm_timer->flags |= ALARM_FLAG_MODIFIED; - /* NOTE: this code must be signal safe because qemu_timer_expired() can be called from a signal. */ pt = &active_timers[ts->clock->type]; @@ -1041,6 +1034,12 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) ts->expire_time = expire_time; ts->next = *pt; *pt = ts; + + /* Rearm if necessary */ + if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0 + && pt == &active_timers[ts->clock->type]) { + qemu_rearm_alarm_timer(alarm_timer); + } } int qemu_timer_pending(QEMUTimer *ts) @@ -1193,8 +1192,9 @@ static void host_alarm_handler(int host_signum) #endif CPUState *env = next_cpu; + alarm_timer->flags |= ALARM_FLAG_EXPIRED; + if (env) { - alarm_timer->flags |= ALARM_FLAG_MODIFIED; /* stop the currently executing cpu because a timer occured */ cpu_interrupt(env, CPU_INTERRUPT_EXIT); #ifdef USE_KQEMU @@ -7396,7 +7396,10 @@ void main_loop_wait(int timeout) qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], qemu_get_clock(rt_clock)); - qemu_rearm_alarm_timer(alarm_timer); + if (alarm_timer->flags & ALARM_FLAG_EXPIRED) { + alarm_timer->flags &= ~(ALARM_FLAG_EXPIRED); + qemu_rearm_alarm_timer(alarm_timer); + } /* Check bottom-halves last in case any of the earlier events triggered them. */