static void host_alarm_handler(int host_signum) #endif { //printf("host_alarm_handler\n"); coremu_assert_hw_thr("Host_alarm_handler should be called by hw thr\n"); struct qemu_alarm_timer *t = alarm_timer; if (!t) return; #if 0 #define DISP_FREQ 1000 { static int64_t delta_min = INT64_MAX; static int64_t delta_max, delta_cum, last_clock, delta, ti; static int count; ti = qemu_get_clock(vm_clock); if (last_clock != 0) { delta = ti - last_clock; if (delta < delta_min) delta_min = delta; if (delta > delta_max) delta_max = delta; delta_cum += delta; if (++count == DISP_FREQ) { printf("timer: min=%" PRId64 " us max=%" PRId64 " us avg=%" PRId64 " us avg_freq=%0.3f Hz\n", muldiv64(delta_min, 1000000, get_ticks_per_sec()), muldiv64(delta_max, 1000000, get_ticks_per_sec()), muldiv64(delta_cum, 1000000 / DISP_FREQ, get_ticks_per_sec()), (double)get_ticks_per_sec() / ((double)delta_cum / DISP_FREQ)); count = 0; delta_min = INT64_MAX; delta_max = 0; delta_cum = 0; } } last_clock = ti; } #endif if (alarm_has_dynticks(t) || (!use_icount && qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL], qemu_get_clock(vm_clock))) || qemu_timer_expired(active_timers[QEMU_CLOCK_REALTIME], qemu_get_clock(rt_clock)) || qemu_timer_expired(active_timers[QEMU_CLOCK_HOST], qemu_get_clock(host_clock))) { t->expired = alarm_has_dynticks(t); t->pending = 1; qemu_notify_event(); } }
static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { struct qemu_alarm_timer *t = alarm_timer; if (!t) { return; } if (alarm_has_dynticks(t) || qemu_next_alarm_deadline() <= 0) { t->expired = alarm_has_dynticks(t); t->pending = 1; qemu_notify_event(); } }
static void host_alarm_handler(int host_signum) #endif { struct qemu_alarm_timer *t = alarm_timer; if (!t) return; if (alarm_has_dynticks(t) || qemu_next_alarm_deadline () <= 0) { t->expired = alarm_has_dynticks(t); t->pending = 1; qemu_notify_event(); } }
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]) { return; } timeKillEvent(mm_timer); nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000; if (nearest_delta_ms < 1) { nearest_delta_ms = 1; } mm_timer = timeSetEvent(nearest_delta_ms, mm_period, mm_alarm_handler, (DWORD_PTR)t, TIME_ONESHOT | TIME_CALLBACK_FUNCTION); if (!mm_timer) { fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n", GetLastError()); timeEndPeriod(mm_period); exit(1); } }
static int mm_start_timer(struct qemu_alarm_timer *t) { TIMECAPS tc; UINT flags; memset(&tc, 0, sizeof(tc)); timeGetDevCaps(&tc, sizeof(tc)); mm_period = tc.wPeriodMin; timeBeginPeriod(mm_period); flags = TIME_CALLBACK_FUNCTION; if (alarm_has_dynticks(t)) { flags |= TIME_ONESHOT; } else { flags |= TIME_PERIODIC; } mm_timer = timeSetEvent(1, /* interval (ms) */ mm_period, /* resolution */ mm_alarm_handler, /* function */ (DWORD_PTR)t, /* parameter */ flags); if (!mm_timer) { fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", GetLastError()); timeEndPeriod(mm_period); return -1; } return 0; }
static void win32_rearm_timer(struct qemu_alarm_timer *t) { HANDLE hTimer = t->timer; int nearest_delta_ms; BOOLEAN success; assert(alarm_has_dynticks(t)); if (!active_timers[QEMU_CLOCK_REALTIME] && !active_timers[QEMU_CLOCK_VIRTUAL] && !active_timers[QEMU_CLOCK_HOST]) return; nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000; if (nearest_delta_ms < 1) { nearest_delta_ms = 1; } success = ChangeTimerQueueTimer(NULL, hTimer, nearest_delta_ms, 3600000); if (!success) { fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n", GetLastError()); exit(-1); } }
static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t) { if (!alarm_has_dynticks(t)) return; t->rearm(t); }
static void dynticks_rearm_timer(struct qemu_alarm_timer *t) { timer_t host_timer = (timer_t)(long)t->priv; struct itimerspec timeout; int64_t nearest_delta_us = INT64_MAX; int64_t current_us; assert(alarm_has_dynticks(t)); if (!active_timers[QEMU_CLOCK_REALTIME] && !active_timers[QEMU_CLOCK_VIRTUAL] && !active_timers[QEMU_CLOCK_HOST]) return; nearest_delta_us = qemu_next_deadline_dyntick(); /* check whether a timer is already running */ if (timer_gettime(host_timer, &timeout)) { perror("gettime"); fprintf(stderr, "Internal timer error: aborting\n"); exit(1); } current_us = timeout.it_value.tv_sec * 1000000 + timeout.it_value.tv_nsec/1000; if (current_us && current_us <= nearest_delta_us) return; timeout.it_interval.tv_sec = 0; timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */ timeout.it_value.tv_sec = nearest_delta_us / 1000000; timeout.it_value.tv_nsec = (nearest_delta_us % 1000000) * 1000; if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) { perror("settime"); fprintf(stderr, "Internal timer error: aborting\n"); exit(1); } }
static int win32_start_timer(struct qemu_alarm_timer *t) { HANDLE hTimer; BOOLEAN success; /* If you call ChangeTimerQueueTimer on a one-shot timer (its period is zero) that has already expired, the timer is not updated. Since creating a new timer is relatively expensive, set a bogus one-hour interval in the dynticks case. */ success = CreateTimerQueueTimer(&hTimer, NULL, host_alarm_handler, t, 1, alarm_has_dynticks(t) ? 3600000 : 1, WT_EXECUTEINTIMERTHREAD); if (!success) { fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", GetLastError()); return -1; } t->timer = hTimer; return 0; }
static void unix_rearm_timer(struct qemu_alarm_timer *t) { struct itimerval itv; int64_t nearest_delta_ns = INT64_MAX; int err; assert(alarm_has_dynticks(t)); if (!active_timers[QEMU_CLOCK_REALTIME] && !active_timers[QEMU_CLOCK_VIRTUAL] && !active_timers[QEMU_CLOCK_HOST]) return; nearest_delta_ns = qemu_next_alarm_deadline(); if (nearest_delta_ns < MIN_TIMER_REARM_NS) nearest_delta_ns = MIN_TIMER_REARM_NS; itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */ itv.it_value.tv_sec = nearest_delta_ns / 1000000000; itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000; err = setitimer(ITIMER_REAL, &itv, NULL); if (err) { perror("setitimer"); fprintf(stderr, "Internal timer error: aborting\n"); exit(1); } }
static void win32_rearm_timer(struct qemu_alarm_timer *t) { struct qemu_alarm_win32 *data = t->priv; assert(alarm_has_dynticks(t)); if (!active_timers[QEMU_CLOCK_REALTIME] && !active_timers[QEMU_CLOCK_VIRTUAL] && !active_timers[QEMU_CLOCK_HOST]) return; timeKillEvent(data->timerId); data->timerId = timeSetEvent(1, data->period, host_alarm_handler, (DWORD)t, TIME_ONESHOT | TIME_CALLBACK_FUNCTION); if (!data->timerId) { fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n", GetLastError()); timeEndPeriod(data->period); exit(1); } }
static int win32_start_timer(struct qemu_alarm_timer *t) { TIMECAPS tc; struct qemu_alarm_win32 *data = t->priv; UINT flags; memset(&tc, 0, sizeof(tc)); timeGetDevCaps(&tc, sizeof(tc)); data->period = tc.wPeriodMin; timeBeginPeriod(data->period); flags = TIME_CALLBACK_FUNCTION; if (alarm_has_dynticks(t)) flags |= TIME_ONESHOT; else flags |= TIME_PERIODIC; data->timerId = timeSetEvent(1, // interval (ms) data->period, // resolution host_alarm_handler, // function (DWORD)t, // parameter flags); if (!data->timerId) { fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", GetLastError()); timeEndPeriod(data->period); return -1; } return 0; }
static void host_alarm_handler(int host_signum) #endif { struct qemu_alarm_timer *t = alarm_timer; if (!t) return; #if 0 #define DISP_FREQ 1000 { static int64_t delta_min = INT64_MAX; static int64_t delta_max, delta_cum, last_clock, delta, ti; static int count; ti = qemu_get_clock_ns(vm_clock); if (last_clock != 0) { delta = ti - last_clock; if (delta < delta_min) delta_min = delta; if (delta > delta_max) delta_max = delta; delta_cum += delta; if (++count == DISP_FREQ) { printf("timer: min=%" PRId64 " us max=%" PRId64 " us avg=%" PRId64 " us avg_freq=%0.3f Hz\n", muldiv64(delta_min, 1000000, get_ticks_per_sec()), muldiv64(delta_max, 1000000, get_ticks_per_sec()), muldiv64(delta_cum, 1000000 / DISP_FREQ, get_ticks_per_sec()), (double)get_ticks_per_sec() / ((double)delta_cum / DISP_FREQ)); count = 0; delta_min = INT64_MAX; delta_max = 0; delta_cum = 0; } } last_clock = ti; } #endif if (alarm_has_dynticks(t) || qemu_next_alarm_deadline () <= 0) { t->expired = alarm_has_dynticks(t); t->pending = 1; qemu_notify_event(); } }
static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *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; } nearest_delta_ns = qemu_next_alarm_deadline(); t->rearm(t, nearest_delta_ns); }
static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { struct qemu_alarm_timer *t = alarm_timer; if (!t) { return; } // We can actually call qemu_next_alarm_deadline() here since this // doesn't run in a signal handler, but a different thread. if (alarm_has_dynticks(t) || qemu_next_alarm_deadline() <= 0) { t->expired = 1; timer_alarm_pending = 1; qemu_notify_event(); } }
static void host_alarm_handler(int host_signum) #endif { struct qemu_alarm_timer *t = alarm_timer; if (!t) return; // It's not possible to call qemu_next_alarm_deadline() to know // if a timer has really expired, in the case of non-dynamic alarms, // so just signal and let the main loop thread do the checks instead. timer_alarm_pending = 1; // Ensure a dynamic alarm will be properly rescheduled. if (alarm_has_dynticks(t)) t->expired = 1; // This forces a cpu_exit() call that will end the current CPU // execution ASAP. qemu_notify_event(); }
static void dynticks_rearm_timer(struct qemu_alarm_timer *t) { 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 (!qemu_clock_has_timers(QEMU_CLOCK_REALTIME) && !qemu_clock_has_timers(QEMU_CLOCK_VIRTUAL) && !qemu_clock_has_timers(QEMU_CLOCK_HOST)) return; nearest_delta_ns = qemu_next_alarm_deadline(); if (nearest_delta_ns < MIN_TIMER_REARM_NS) nearest_delta_ns = MIN_TIMER_REARM_NS; /* check whether a timer is already running */ if (timer_gettime(host_timer, &timeout)) { perror("gettime"); fprintf(stderr, "Internal timer error: aborting\n"); exit(1); } current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec; if (current_ns && current_ns <= nearest_delta_ns) return; timeout.it_interval.tv_sec = 0; timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */ timeout.it_value.tv_sec = nearest_delta_ns / 1000000000; timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000; if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) { perror("settime"); fprintf(stderr, "Internal timer error: aborting\n"); exit(1); } }