From 688eb3896b0b0d005271ded092dab5cb9281d8d5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 13 Sep 2011 11:42:26 +0200 Subject: qemu-timer: remove active_timers array Embed the list in the QEMUClock instead. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- qemu-timer.c | 59 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) (limited to 'qemu-timer.c') diff --git a/qemu-timer.c b/qemu-timer.c index ad1fc8b..acf7a15 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -134,6 +134,7 @@ struct QEMUClock { int enabled; QEMUTimer *warp_timer; + QEMUTimer *active_timers; NotifierList reset_notifiers; int64_t last; @@ -352,14 +353,10 @@ next: } } -#define QEMU_NUM_CLOCKS 3 - QEMUClock *rt_clock; QEMUClock *vm_clock; QEMUClock *host_clock; -static QEMUTimer *active_timers[QEMU_NUM_CLOCKS]; - static QEMUClock *qemu_new_clock(int type) { QEMUClock *clock; @@ -403,7 +400,7 @@ static void icount_warp_rt(void *opaque) int64_t delta = cur_time - cur_icount; qemu_icount_bias += MIN(warp_delta, delta); } - if (qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL], + if (qemu_timer_expired(vm_clock->active_timers, qemu_get_clock_ns(vm_clock))) { qemu_notify_event(); } @@ -434,7 +431,7 @@ void qemu_clock_warp(QEMUClock *clock) * the earliest vm_clock timer. */ icount_warp_rt(NULL); - if (!all_cpu_threads_idle() || !active_timers[clock->type]) { + if (!all_cpu_threads_idle() || !clock->active_timers) { qemu_del_timer(clock->warp_timer); return; } @@ -489,7 +486,7 @@ void qemu_del_timer(QEMUTimer *ts) /* NOTE: this code must be signal safe because qemu_timer_expired() can be called from a signal. */ - pt = &active_timers[ts->clock->type]; + pt = &ts->clock->active_timers; for(;;) { t = *pt; if (!t) @@ -513,7 +510,7 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) /* add the timer in the sorted list */ /* NOTE: this code must be signal safe because qemu_timer_expired() can be called from a signal. */ - pt = &active_timers[ts->clock->type]; + pt = &ts->clock->active_timers; for(;;) { t = *pt; if (!qemu_timer_expired_ns(t, expire_time)) { @@ -526,7 +523,7 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) *pt = ts; /* Rearm if necessary */ - if (pt == &active_timers[ts->clock->type]) { + if (pt == &ts->clock->active_timers) { if (!alarm_timer->pending) { qemu_rearm_alarm_timer(alarm_timer); } @@ -548,7 +545,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) int qemu_timer_pending(QEMUTimer *ts) { QEMUTimer *t; - for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) { + for (t = ts->clock->active_timers; t != NULL; t = t->next) { if (t == ts) return 1; } @@ -569,7 +566,7 @@ static void qemu_run_timers(QEMUClock *clock) return; current_time = qemu_get_clock_ns(clock); - ptimer_head = &active_timers[clock->type]; + ptimer_head = &clock->active_timers; for(;;) { ts = *ptimer_head; if (!qemu_timer_expired_ns(ts, current_time)) { @@ -773,8 +770,8 @@ int64_t qemu_next_icount_deadline(void) int64_t delta = INT32_MAX; assert(use_icount); - if (active_timers[QEMU_CLOCK_VIRTUAL]) { - delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time - + if (vm_clock->active_timers) { + delta = vm_clock->active_timers->expire_time - qemu_get_clock_ns(vm_clock); } @@ -789,20 +786,20 @@ static int64_t qemu_next_alarm_deadline(void) int64_t delta; int64_t rtdelta; - if (!use_icount && active_timers[QEMU_CLOCK_VIRTUAL]) { - delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time - + if (!use_icount && vm_clock->active_timers) { + delta = vm_clock->active_timers->expire_time - qemu_get_clock_ns(vm_clock); } else { delta = INT32_MAX; } - if (active_timers[QEMU_CLOCK_HOST]) { - int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time - + if (host_clock->active_timers) { + int64_t hdelta = host_clock->active_timers->expire_time - qemu_get_clock_ns(host_clock); if (hdelta < delta) delta = hdelta; } - if (active_timers[QEMU_CLOCK_REALTIME]) { - rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time - + if (rt_clock->active_timers) { + rtdelta = (rt_clock->active_timers->expire_time - qemu_get_clock_ns(rt_clock)); if (rtdelta < delta) delta = rtdelta; @@ -871,9 +868,9 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t) int64_t current_ns; assert(alarm_has_dynticks(t)); - if (!active_timers[QEMU_CLOCK_REALTIME] && - !active_timers[QEMU_CLOCK_VIRTUAL] && - !active_timers[QEMU_CLOCK_HOST]) + if (!rt_clock->active_timers && + !vm_clock->active_timers && + !host_clock->active_timers) return; nearest_delta_ns = qemu_next_alarm_deadline(); @@ -925,9 +922,9 @@ static void unix_rearm_timer(struct qemu_alarm_timer *t) int err; assert(alarm_has_dynticks(t)); - if (!active_timers[QEMU_CLOCK_REALTIME] && - !active_timers[QEMU_CLOCK_VIRTUAL] && - !active_timers[QEMU_CLOCK_HOST]) + if (!rt_clock->active_timers && + !vm_clock->active_timers && + !host_clock->active_timers) return; nearest_delta_ns = qemu_next_alarm_deadline(); @@ -1022,9 +1019,9 @@ static void mm_rearm_timer(struct qemu_alarm_timer *t) int nearest_delta_ms; assert(alarm_has_dynticks(t)); - if (!active_timers[QEMU_CLOCK_REALTIME] && - !active_timers[QEMU_CLOCK_VIRTUAL] && - !active_timers[QEMU_CLOCK_HOST]) { + if (!rt_clock->active_timers && + !vm_clock->active_timers && + !host_clock->active_timers) { return; } @@ -1092,9 +1089,9 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t) BOOLEAN success; assert(alarm_has_dynticks(t)); - if (!active_timers[QEMU_CLOCK_REALTIME] && - !active_timers[QEMU_CLOCK_VIRTUAL] && - !active_timers[QEMU_CLOCK_HOST]) + if (!rt_clock->active_timers && + !vm_clock->active_timers && + !host_clock->active_timers) return; nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000; -- cgit v1.1 From f3fc6e2e9613d33e715624e6dd60f525f49446d1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 14 Mar 2011 09:45:38 +0100 Subject: qemu-timer: move common code to qemu_rearm_alarm_timer Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- qemu-timer.c | 129 ++++++++++++++++++++++++----------------------------------- 1 file changed, 53 insertions(+), 76 deletions(-) (limited to 'qemu-timer.c') diff --git a/qemu-timer.c b/qemu-timer.c index acf7a15..e2551f3 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -153,7 +153,7 @@ struct qemu_alarm_timer { char const *name; int (*start)(struct qemu_alarm_timer *t); void (*stop)(struct qemu_alarm_timer *t); - void (*rearm)(struct qemu_alarm_timer *t); + void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns); #if defined(__linux__) int fd; timer_t timer; @@ -181,12 +181,46 @@ static inline int alarm_has_dynticks(struct qemu_alarm_timer *t) return !!t->rearm; } +static int64_t qemu_next_alarm_deadline(void) +{ + int64_t delta; + int64_t rtdelta; + + if (!use_icount && vm_clock->active_timers) { + delta = vm_clock->active_timers->expire_time - + qemu_get_clock_ns(vm_clock); + } else { + delta = INT32_MAX; + } + if (host_clock->active_timers) { + int64_t hdelta = host_clock->active_timers->expire_time - + qemu_get_clock_ns(host_clock); + if (hdelta < delta) { + delta = hdelta; + } + } + if (rt_clock->active_timers) { + rtdelta = (rt_clock->active_timers->expire_time - + qemu_get_clock_ns(rt_clock)); + if (rtdelta < delta) { + delta = rtdelta; + } + } + + return delta; +} + static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t) { - if (!alarm_has_dynticks(t)) + int64_t nearest_delta_ns; + assert(alarm_has_dynticks(t)); + if (!rt_clock->active_timers && + !vm_clock->active_timers && + !host_clock->active_timers) { return; - - t->rearm(t); + } + nearest_delta_ns = qemu_next_alarm_deadline(); + t->rearm(t, nearest_delta_ns); } /* TODO: MIN_TIMER_REARM_NS should be optimized */ @@ -196,23 +230,23 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t) static int mm_start_timer(struct qemu_alarm_timer *t); static void mm_stop_timer(struct qemu_alarm_timer *t); -static void mm_rearm_timer(struct qemu_alarm_timer *t); +static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); static int win32_start_timer(struct qemu_alarm_timer *t); static void win32_stop_timer(struct qemu_alarm_timer *t); -static void win32_rearm_timer(struct qemu_alarm_timer *t); +static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); #else static int unix_start_timer(struct qemu_alarm_timer *t); static void unix_stop_timer(struct qemu_alarm_timer *t); -static void unix_rearm_timer(struct qemu_alarm_timer *t); +static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); #ifdef __linux__ static int dynticks_start_timer(struct qemu_alarm_timer *t); static void dynticks_stop_timer(struct qemu_alarm_timer *t); -static void dynticks_rearm_timer(struct qemu_alarm_timer *t); +static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); #endif /* __linux__ */ @@ -715,8 +749,6 @@ void qemu_run_all_timers(void) qemu_run_timers(host_clock); } -static int64_t qemu_next_alarm_deadline(void); - #ifdef _WIN32 static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused) #else @@ -781,33 +813,6 @@ int64_t qemu_next_icount_deadline(void) return delta; } -static int64_t qemu_next_alarm_deadline(void) -{ - int64_t delta; - int64_t rtdelta; - - if (!use_icount && vm_clock->active_timers) { - delta = vm_clock->active_timers->expire_time - - qemu_get_clock_ns(vm_clock); - } else { - delta = INT32_MAX; - } - if (host_clock->active_timers) { - int64_t hdelta = host_clock->active_timers->expire_time - - qemu_get_clock_ns(host_clock); - if (hdelta < delta) - delta = hdelta; - } - if (rt_clock->active_timers) { - rtdelta = (rt_clock->active_timers->expire_time - - qemu_get_clock_ns(rt_clock)); - if (rtdelta < delta) - delta = rtdelta; - } - - return delta; -} - #if defined(__linux__) #include "compatfd.h" @@ -860,20 +865,13 @@ static void dynticks_stop_timer(struct qemu_alarm_timer *t) timer_delete(host_timer); } -static void dynticks_rearm_timer(struct qemu_alarm_timer *t) +static void dynticks_rearm_timer(struct qemu_alarm_timer *t, + int64_t nearest_delta_ns) { timer_t host_timer = t->timer; struct itimerspec timeout; - int64_t nearest_delta_ns = INT64_MAX; int64_t current_ns; - assert(alarm_has_dynticks(t)); - if (!rt_clock->active_timers && - !vm_clock->active_timers && - !host_clock->active_timers) - return; - - nearest_delta_ns = qemu_next_alarm_deadline(); if (nearest_delta_ns < MIN_TIMER_REARM_NS) nearest_delta_ns = MIN_TIMER_REARM_NS; @@ -915,19 +913,12 @@ static int unix_start_timer(struct qemu_alarm_timer *t) return 0; } -static void unix_rearm_timer(struct qemu_alarm_timer *t) +static void unix_rearm_timer(struct qemu_alarm_timer *t, + int64_t nearest_delta_ns) { struct itimerval itv; - int64_t nearest_delta_ns = INT64_MAX; int err; - assert(alarm_has_dynticks(t)); - if (!rt_clock->active_timers && - !vm_clock->active_timers && - !host_clock->active_timers) - return; - - nearest_delta_ns = qemu_next_alarm_deadline(); if (nearest_delta_ns < MIN_TIMER_REARM_NS) nearest_delta_ns = MIN_TIMER_REARM_NS; @@ -1014,23 +1005,14 @@ static void mm_stop_timer(struct qemu_alarm_timer *t) timeEndPeriod(mm_period); } -static void mm_rearm_timer(struct qemu_alarm_timer *t) +static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta) { - int nearest_delta_ms; - - assert(alarm_has_dynticks(t)); - if (!rt_clock->active_timers && - !vm_clock->active_timers && - !host_clock->active_timers) { - return; - } - - timeKillEvent(mm_timer); - - nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000; + int nearest_delta_ms = (delta + 999999) / 1000000; if (nearest_delta_ms < 1) { nearest_delta_ms = 1; } + + timeKillEvent(mm_timer); mm_timer = timeSetEvent(nearest_delta_ms, mm_period, mm_alarm_handler, @@ -1082,19 +1064,14 @@ static void win32_stop_timer(struct qemu_alarm_timer *t) } } -static void win32_rearm_timer(struct qemu_alarm_timer *t) +static void win32_rearm_timer(struct qemu_alarm_timer *t, + int64_t nearest_delta_ns) { HANDLE hTimer = t->timer; int nearest_delta_ms; BOOLEAN success; - assert(alarm_has_dynticks(t)); - if (!rt_clock->active_timers && - !vm_clock->active_timers && - !host_clock->active_timers) - return; - - nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000; + nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000; if (nearest_delta_ms < 1) { nearest_delta_ms = 1; } -- cgit v1.1 From dc2dfcf0002b4e6be494959a1ed2589dd109def0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 12 Sep 2011 15:50:16 +0200 Subject: qemu-timer: more clock functions These will be used when moving icount accounting to cpus.c. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- qemu-timer.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'qemu-timer.c') diff --git a/qemu-timer.c b/qemu-timer.c index e2551f3..ebb5089 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -495,6 +495,31 @@ void qemu_clock_warp(QEMUClock *clock) } } +int64_t qemu_clock_has_timers(QEMUClock *clock) +{ + return !!clock->active_timers; +} + +int64_t qemu_clock_expired(QEMUClock *clock) +{ + return (clock->active_timers && + clock->active_timers->expire_time < qemu_get_clock_ns(clock)); +} + +int64_t qemu_clock_deadline(QEMUClock *clock) +{ + /* To avoid problems with overflow limit this to 2^32. */ + int64_t delta = INT32_MAX; + + if (clock->active_timers) { + delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock); + } + if (delta < 0) { + delta = 0; + } + return delta; +} + QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale, QEMUTimerCB *cb, void *opaque) { -- cgit v1.1 From 946fb27c1dc158f10a6e3ce0374a161dce04c27b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 12 Sep 2011 13:57:37 +0200 Subject: qemu-timer: move icount to cpus.c None of this is needed by tools, and most of it can even be made static inside cpus.c. Signed-off-by: Paolo Bonzini --- qemu-timer.c | 279 ----------------------------------------------------------- 1 file changed, 279 deletions(-) (limited to 'qemu-timer.c') diff --git a/qemu-timer.c b/qemu-timer.c index ebb5089..8129af6 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -46,82 +46,6 @@ #include "qemu-timer.h" -/* Conversion factor from emulated instructions to virtual clock ticks. */ -int icount_time_shift; -/* Arbitrarily pick 1MIPS as the minimum allowable speed. */ -#define MAX_ICOUNT_SHIFT 10 -/* Compensate for varying guest execution speed. */ -int64_t qemu_icount_bias; -static QEMUTimer *icount_rt_timer; -static QEMUTimer *icount_vm_timer; - -/***********************************************************/ -/* guest cycle counter */ - -typedef struct TimersState { - int64_t cpu_ticks_prev; - int64_t cpu_ticks_offset; - int64_t cpu_clock_offset; - int32_t cpu_ticks_enabled; - int64_t dummy; -} TimersState; - -TimersState timers_state; - -/* return the host CPU cycle counter and handle stop/restart */ -int64_t cpu_get_ticks(void) -{ - if (use_icount) { - return cpu_get_icount(); - } - if (!timers_state.cpu_ticks_enabled) { - return timers_state.cpu_ticks_offset; - } else { - int64_t ticks; - ticks = cpu_get_real_ticks(); - if (timers_state.cpu_ticks_prev > ticks) { - /* Note: non increasing ticks may happen if the host uses - software suspend */ - timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks; - } - timers_state.cpu_ticks_prev = ticks; - return ticks + timers_state.cpu_ticks_offset; - } -} - -/* return the host CPU monotonic timer and handle stop/restart */ -static int64_t cpu_get_clock(void) -{ - int64_t ti; - if (!timers_state.cpu_ticks_enabled) { - return timers_state.cpu_clock_offset; - } else { - ti = get_clock(); - return ti + timers_state.cpu_clock_offset; - } -} - -/* enable cpu_get_ticks() */ -void cpu_enable_ticks(void) -{ - if (!timers_state.cpu_ticks_enabled) { - timers_state.cpu_ticks_offset -= cpu_get_real_ticks(); - timers_state.cpu_clock_offset -= get_clock(); - timers_state.cpu_ticks_enabled = 1; - } -} - -/* disable cpu_get_ticks() : the clock is stopped. You must not call - cpu_get_ticks() after that. */ -void cpu_disable_ticks(void) -{ - if (timers_state.cpu_ticks_enabled) { - timers_state.cpu_ticks_offset = cpu_get_ticks(); - timers_state.cpu_clock_offset = cpu_get_clock(); - timers_state.cpu_ticks_enabled = 0; - } -} - /***********************************************************/ /* timers */ @@ -133,7 +57,6 @@ struct QEMUClock { int type; int enabled; - QEMUTimer *warp_timer; QEMUTimer *active_timers; NotifierList reset_notifiers; @@ -252,61 +175,6 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); #endif /* _WIN32 */ -/* Correlation between real and virtual time is always going to be - fairly approximate, so ignore small variation. - When the guest is idle real and virtual time will be aligned in - the IO wait loop. */ -#define ICOUNT_WOBBLE (get_ticks_per_sec() / 10) - -static void icount_adjust(void) -{ - int64_t cur_time; - int64_t cur_icount; - int64_t delta; - static int64_t last_delta; - /* If the VM is not running, then do nothing. */ - if (!runstate_is_running()) - return; - - cur_time = cpu_get_clock(); - cur_icount = qemu_get_clock_ns(vm_clock); - delta = cur_icount - cur_time; - /* FIXME: This is a very crude algorithm, somewhat prone to oscillation. */ - if (delta > 0 - && last_delta + ICOUNT_WOBBLE < delta * 2 - && icount_time_shift > 0) { - /* The guest is getting too far ahead. Slow time down. */ - icount_time_shift--; - } - if (delta < 0 - && last_delta - ICOUNT_WOBBLE > delta * 2 - && icount_time_shift < MAX_ICOUNT_SHIFT) { - /* The guest is getting too far behind. Speed time up. */ - icount_time_shift++; - } - last_delta = delta; - qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift); -} - -static void icount_adjust_rt(void * opaque) -{ - qemu_mod_timer(icount_rt_timer, - qemu_get_clock_ms(rt_clock) + 1000); - icount_adjust(); -} - -static void icount_adjust_vm(void * opaque) -{ - qemu_mod_timer(icount_vm_timer, - qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10); - icount_adjust(); -} - -int64_t qemu_icount_round(int64_t count) -{ - return (count + (1 << icount_time_shift) - 1) >> icount_time_shift; -} - static struct qemu_alarm_timer alarm_timers[] = { #ifndef _WIN32 #ifdef __linux__ @@ -411,90 +279,6 @@ void qemu_clock_enable(QEMUClock *clock, int enabled) clock->enabled = enabled; } -static int64_t vm_clock_warp_start; - -static void icount_warp_rt(void *opaque) -{ - if (vm_clock_warp_start == -1) { - return; - } - - if (runstate_is_running()) { - int64_t clock = qemu_get_clock_ns(rt_clock); - int64_t warp_delta = clock - vm_clock_warp_start; - if (use_icount == 1) { - qemu_icount_bias += warp_delta; - } else { - /* - * In adaptive mode, do not let the vm_clock run too - * far ahead of real time. - */ - int64_t cur_time = cpu_get_clock(); - int64_t cur_icount = qemu_get_clock_ns(vm_clock); - int64_t delta = cur_time - cur_icount; - qemu_icount_bias += MIN(warp_delta, delta); - } - if (qemu_timer_expired(vm_clock->active_timers, - qemu_get_clock_ns(vm_clock))) { - qemu_notify_event(); - } - } - vm_clock_warp_start = -1; -} - -void qemu_clock_warp(QEMUClock *clock) -{ - int64_t deadline; - - if (!clock->warp_timer) { - return; - } - - /* - * There are too many global variables to make the "warp" behavior - * applicable to other clocks. But a clock argument removes the - * need for if statements all over the place. - */ - assert(clock == vm_clock); - - /* - * If the CPUs have been sleeping, advance the vm_clock timer now. This - * ensures that the deadline for the timer is computed correctly below. - * This also makes sure that the insn counter is synchronized before the - * CPU starts running, in case the CPU is woken by an event other than - * the earliest vm_clock timer. - */ - icount_warp_rt(NULL); - if (!all_cpu_threads_idle() || !clock->active_timers) { - qemu_del_timer(clock->warp_timer); - return; - } - - vm_clock_warp_start = qemu_get_clock_ns(rt_clock); - deadline = qemu_next_icount_deadline(); - if (deadline > 0) { - /* - * Ensure the vm_clock proceeds even when the virtual CPU goes to - * sleep. Otherwise, the CPU might be waiting for a future timer - * interrupt to wake it up, but the interrupt never comes because - * the vCPU isn't running any insns and thus doesn't advance the - * vm_clock. - * - * An extreme solution for this problem would be to never let VCPUs - * sleep in icount mode if there is a pending vm_clock timer; rather - * time could just advance to the next vm_clock event. Instead, we - * do stop VCPUs and only advance vm_clock after some "real" time, - * (related to the time left until the next event) has passed. This - * rt_clock timer will do this. This avoids that the warps are too - * visible externally---for example, you will not be sending network - * packets continously instead of every 100ms. - */ - qemu_mod_timer(clock->warp_timer, vm_clock_warp_start + deadline); - } else { - qemu_notify_event(); - } -} - int64_t qemu_clock_has_timers(QEMUClock *clock) { return !!clock->active_timers; @@ -709,52 +493,6 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) } } -static const VMStateDescription vmstate_timers = { - .name = "timer", - .version_id = 2, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { - VMSTATE_INT64(cpu_ticks_offset, TimersState), - VMSTATE_INT64(dummy, TimersState), - VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2), - VMSTATE_END_OF_LIST() - } -}; - -void configure_icount(const char *option) -{ - vmstate_register(NULL, 0, &vmstate_timers, &timers_state); - if (!option) - return; - - vm_clock->warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL); - - if (strcmp(option, "auto") != 0) { - icount_time_shift = strtol(option, NULL, 0); - use_icount = 1; - return; - } - - use_icount = 2; - - /* 125MIPS seems a reasonable initial guess at the guest speed. - It will be corrected fairly quickly anyway. */ - icount_time_shift = 3; - - /* Have both realtime and virtual time triggers for speed adjustment. - The realtime trigger catches emulated time passing too slowly, - the virtual time trigger catches emulated time passing too fast. - Realtime triggers occur even when idle, so use them less frequently - than VM triggers. */ - icount_rt_timer = qemu_new_timer_ms(rt_clock, icount_adjust_rt, NULL); - qemu_mod_timer(icount_rt_timer, - qemu_get_clock_ms(rt_clock) + 1000); - icount_vm_timer = qemu_new_timer_ns(vm_clock, icount_adjust_vm, NULL); - qemu_mod_timer(icount_vm_timer, - qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10); -} - void qemu_run_all_timers(void) { alarm_timer->pending = 0; @@ -821,23 +559,6 @@ static void host_alarm_handler(int host_signum) } } -int64_t qemu_next_icount_deadline(void) -{ - /* To avoid problems with overflow limit this to 2^32. */ - int64_t delta = INT32_MAX; - - assert(use_icount); - if (vm_clock->active_timers) { - delta = vm_clock->active_timers->expire_time - - qemu_get_clock_ns(vm_clock); - } - - if (delta < 0) - delta = 0; - - return delta; -} - #if defined(__linux__) #include "compatfd.h" -- cgit v1.1 From a5c57d64aa61b700db444c4864a1da11f1165db6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 12 Sep 2011 14:40:36 +0200 Subject: qemu-timer: do not refer to runstate_is_running() Signed-off-by: Paolo Bonzini --- qemu-timer.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'qemu-timer.c') diff --git a/qemu-timer.c b/qemu-timer.c index 8129af6..d8507e3 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -504,10 +504,7 @@ void qemu_run_all_timers(void) } /* vm time timers */ - if (runstate_is_running()) { - qemu_run_timers(vm_clock); - } - + qemu_run_timers(vm_clock); qemu_run_timers(rt_clock); qemu_run_timers(host_clock); } -- cgit v1.1 From 4260a7391190d2d01fac50ee3d738a15bab6b98e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 19 Sep 2011 10:18:51 +0200 Subject: qemu-timer: use atexit for quit_timers Signed-off-by: Paolo Bonzini --- qemu-timer.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'qemu-timer.c') diff --git a/qemu-timer.c b/qemu-timer.c index d8507e3..7fa81e1 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -840,6 +840,13 @@ static void alarm_timer_on_change_state_rearm(void *opaque, int running, qemu_rearm_alarm_timer((struct qemu_alarm_timer *) opaque); } +static void quit_timers(void) +{ + struct qemu_alarm_timer *t = alarm_timer; + alarm_timer = NULL; + t->stop(t); +} + int init_timer_alarm(void) { struct qemu_alarm_timer *t = NULL; @@ -859,6 +866,7 @@ int init_timer_alarm(void) } /* first event is at time 0 */ + atexit(quit_timers); t->pending = 1; alarm_timer = t; qemu_add_vm_change_state_handler(alarm_timer_on_change_state_rearm, t); @@ -869,13 +877,6 @@ fail: return err; } -void quit_timers(void) -{ - struct qemu_alarm_timer *t = alarm_timer; - alarm_timer = NULL; - t->stop(t); -} - int qemu_calculate_timeout(void) { return 1000; -- cgit v1.1 From 2ff68d0738768643e796ab39f007c1f3858e67f1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 12 Sep 2011 16:21:44 +0200 Subject: qemu-timer: move more stuff out of qemu-timer.c Signed-off-by: Paolo Bonzini --- qemu-timer.c | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) (limited to 'qemu-timer.c') diff --git a/qemu-timer.c b/qemu-timer.c index 7fa81e1..58926dd 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -266,11 +266,8 @@ static QEMUClock *qemu_new_clock(int type) clock = g_malloc0(sizeof(QEMUClock)); clock->type = type; clock->enabled = 1; + clock->last = INT64_MIN; notifier_list_init(&clock->reset_notifiers); - /* required to detect & report backward jumps */ - if (type == QEMU_CLOCK_HOST) { - clock->last = get_clock_realtime(); - } return clock; } @@ -344,7 +341,7 @@ void qemu_del_timer(QEMUTimer *ts) /* modify the current timer so that it will be fired when current_time >= expire_time. The corresponding callback will be called. */ -static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) +void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) { QEMUTimer **pt, *t; @@ -378,8 +375,6 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) } } -/* modify the current timer so that it will be fired when current_time - >= expire_time. The corresponding callback will be called. */ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) { qemu_mod_timer_ns(ts, expire_time * ts->scale); @@ -464,33 +459,11 @@ void init_clocks(void) rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME); vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL); host_clock = qemu_new_clock(QEMU_CLOCK_HOST); - - rtc_clock = host_clock; } -/* save a timer */ -void qemu_put_timer(QEMUFile *f, QEMUTimer *ts) +uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts) { - uint64_t expire_time; - - if (qemu_timer_pending(ts)) { - expire_time = ts->expire_time; - } else { - expire_time = -1; - } - qemu_put_be64(f, expire_time); -} - -void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) -{ - uint64_t expire_time; - - expire_time = qemu_get_be64(f); - if (expire_time != -1) { - qemu_mod_timer_ns(ts, expire_time); - } else { - qemu_del_timer(ts); - } + return qemu_timer_pending(ts) ? ts->expire_time : -1; } void qemu_run_all_timers(void) -- cgit v1.1 From fbdc14ebf8d16f00a87b6f4cdb4799ccfb6469be Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Sep 2011 18:23:14 +0200 Subject: qemu-timer: do not use RunState change handlers Signed-off-by: Paolo Bonzini --- qemu-timer.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'qemu-timer.c') diff --git a/qemu-timer.c b/qemu-timer.c index 58926dd..f11a28d 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -273,7 +273,11 @@ static QEMUClock *qemu_new_clock(int type) void qemu_clock_enable(QEMUClock *clock, int enabled) { + bool old = clock->enabled; clock->enabled = enabled; + if (enabled && !old) { + qemu_rearm_alarm_timer(alarm_timer); + } } int64_t qemu_clock_has_timers(QEMUClock *clock) @@ -806,13 +810,6 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t, #endif /* _WIN32 */ -static void alarm_timer_on_change_state_rearm(void *opaque, int running, - RunState state) -{ - if (running) - qemu_rearm_alarm_timer((struct qemu_alarm_timer *) opaque); -} - static void quit_timers(void) { struct qemu_alarm_timer *t = alarm_timer; @@ -842,7 +839,6 @@ int init_timer_alarm(void) atexit(quit_timers); t->pending = 1; alarm_timer = t; - qemu_add_vm_change_state_handler(alarm_timer_on_change_state_rearm, t); return 0; -- cgit v1.1