X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=qemu-timer.c;h=b2d95e2fec8ecf852dd6ebc0c329556da18244bb;hb=be17f18b8cd438be7f8f65000c0baecdd5b34634;hp=80bcc563e058ea7ee48fe945b4aa151b55868189;hpb=cefc898806e0346eef87d15ddaac9475b57b7d84;p=qemu.git diff --git a/qemu-timer.c b/qemu-timer.c index 80bcc563e..b2d95e2fe 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -22,30 +22,21 @@ * THE SOFTWARE. */ -#include "sysemu.h" -#include "net.h" -#include "monitor.h" -#include "console.h" +#include "sysemu/sysemu.h" +#include "monitor/monitor.h" +#include "ui/console.h" #include "hw/hw.h" -#include -#include -#include -#include -#include -#include -#ifdef __FreeBSD__ -#include +#include "qemu/timer.h" +#ifdef CONFIG_POSIX +#include #endif #ifdef _WIN32 -#include #include #endif -#include "qemu-timer.h" - /***********************************************************/ /* timers */ @@ -54,22 +45,22 @@ #define QEMU_CLOCK_HOST 2 struct QEMUClock { - int type; - int enabled; - QEMUTimer *active_timers; NotifierList reset_notifiers; int64_t last; + + int type; + bool enabled; }; struct QEMUTimer { - QEMUClock *clock; int64_t expire_time; /* in nanoseconds */ - int scale; + QEMUClock *clock; QEMUTimerCB *cb; void *opaque; - struct QEMUTimer *next; + QEMUTimer *next; + int scale; }; struct qemu_alarm_timer { @@ -78,13 +69,13 @@ struct qemu_alarm_timer { void (*stop)(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; + int fd; #elif defined(_WIN32) HANDLE timer; #endif - char expired; - char pending; + bool expired; + bool pending; }; static struct qemu_alarm_timer *alarm_timer; @@ -94,35 +85,23 @@ static bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time) return timer_head && (timer_head->expire_time <= current_time); } -int qemu_alarm_pending(void) -{ - return alarm_timer->pending; -} - -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 delta = INT64_MAX; int64_t rtdelta; - if (!use_icount && vm_clock->active_timers) { + if (!use_icount && vm_clock->enabled && 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) { + if (host_clock->enabled && 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) { + if (rt_clock->enabled && rt_clock->active_timers) { rtdelta = (rt_clock->active_timers->expire_time - qemu_get_clock_ns(rt_clock)); if (rtdelta < delta) { @@ -135,15 +114,10 @@ static int64_t qemu_next_alarm_deadline(void) 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; + int64_t nearest_delta_ns = qemu_next_alarm_deadline(); + if (nearest_delta_ns < INT64_MAX) { + t->rearm(t, nearest_delta_ns); } - nearest_delta_ns = qemu_next_alarm_deadline(); - t->rearm(t, nearest_delta_ns); } /* TODO: MIN_TIMER_REARM_NS should be optimized */ @@ -207,7 +181,7 @@ void configure_alarms(char const *opt) char *name; struct qemu_alarm_timer tmp; - if (!strcmp(opt, "?")) { + if (is_help_option(opt)) { show_available_alarms(); exit(0); } @@ -263,13 +237,13 @@ static QEMUClock *qemu_new_clock(int type) clock = g_malloc0(sizeof(QEMUClock)); clock->type = type; - clock->enabled = 1; + clock->enabled = true; clock->last = INT64_MIN; notifier_list_init(&clock->reset_notifiers); return clock; } -void qemu_clock_enable(QEMUClock *clock, int enabled) +void qemu_clock_enable(QEMUClock *clock, bool enabled) { bool old = clock->enabled; clock->enabled = enabled; @@ -382,38 +356,38 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) qemu_mod_timer_ns(ts, expire_time * ts->scale); } -int qemu_timer_pending(QEMUTimer *ts) +bool qemu_timer_pending(QEMUTimer *ts) { QEMUTimer *t; for (t = ts->clock->active_timers; t != NULL; t = t->next) { - if (t == ts) - return 1; + if (t == ts) { + return true; + } } - return 0; + return false; } -int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) +bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) { return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale); } void qemu_run_timers(QEMUClock *clock) { - QEMUTimer **ptimer_head, *ts; + QEMUTimer *ts; int64_t current_time; if (!clock->enabled) return; current_time = qemu_get_clock_ns(clock); - ptimer_head = &clock->active_timers; for(;;) { - ts = *ptimer_head; + ts = clock->active_timers; if (!qemu_timer_expired_ns(ts, current_time)) { break; } /* remove timer from the list before calling the callback */ - *ptimer_head = ts->next; + clock->active_timers = ts->next; ts->next = NULL; /* run the callback (the timer list can be modified) */ @@ -458,9 +432,11 @@ void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier) 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); + if (!rt_clock) { + rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME); + vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL); + host_clock = qemu_new_clock(QEMU_CLOCK_HOST); + } } uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts) @@ -470,18 +446,18 @@ uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts) void qemu_run_all_timers(void) { - alarm_timer->pending = 0; - - /* rearm timer, if not periodic */ - if (alarm_timer->expired) { - alarm_timer->expired = 0; - qemu_rearm_alarm_timer(alarm_timer); - } + alarm_timer->pending = false; /* vm time timers */ qemu_run_timers(vm_clock); qemu_run_timers(rt_clock); qemu_run_timers(host_clock); + + /* rearm timer, if not periodic */ + if (alarm_timer->expired) { + alarm_timer->expired = false; + qemu_rearm_alarm_timer(alarm_timer); + } } #ifdef _WIN32 @@ -494,17 +470,14 @@ static void host_alarm_handler(int host_signum) 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(); - } + t->expired = true; + t->pending = true; + qemu_notify_event(); } #if defined(__linux__) -#include "compatfd.h" +#include "qemu/compatfd.h" static int dynticks_start_timer(struct qemu_alarm_timer *t) { @@ -525,20 +498,16 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t) memset(&ev, 0, sizeof(ev)); ev.sigev_value.sival_int = 0; ev.sigev_notify = SIGEV_SIGNAL; -#ifdef SIGEV_THREAD_ID +#ifdef CONFIG_SIGEV_THREAD_ID if (qemu_signalfd_available()) { ev.sigev_notify = SIGEV_THREAD_ID; ev._sigev_un._tid = qemu_get_thread_id(); } -#endif /* SIGEV_THREAD_ID */ +#endif /* CONFIG_SIGEV_THREAD_ID */ ev.sigev_signo = SIGALRM; if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) { perror("timer_create"); - - /* disable dynticks */ - fprintf(stderr, "Dynamic Ticks disabled\n"); - return -1; } @@ -637,7 +606,7 @@ static void unix_stop_timer(struct qemu_alarm_timer *t) #ifdef _WIN32 static MMRESULT mm_timer; -static unsigned mm_period; +static TIMECAPS mm_tc; static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, @@ -647,72 +616,45 @@ static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg, 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(); - } + t->expired = true; + t->pending = true; + qemu_notify_event(); } 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; - } - + timeGetDevCaps(&mm_tc, sizeof(mm_tc)); return 0; } static void mm_stop_timer(struct qemu_alarm_timer *t) { - timeKillEvent(mm_timer); - timeEndPeriod(mm_period); + if (mm_timer) { + timeKillEvent(mm_timer); + } } static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta) { - int nearest_delta_ms = (delta + 999999) / 1000000; - if (nearest_delta_ms < 1) { - nearest_delta_ms = 1; + int64_t nearest_delta_ms = delta / 1000000; + if (nearest_delta_ms < mm_tc.wPeriodMin) { + nearest_delta_ms = mm_tc.wPeriodMin; + } else if (nearest_delta_ms > mm_tc.wPeriodMax) { + nearest_delta_ms = mm_tc.wPeriodMax; } - timeKillEvent(mm_timer); - mm_timer = timeSetEvent(nearest_delta_ms, - mm_period, + if (mm_timer) { + timeKillEvent(mm_timer); + } + mm_timer = timeSetEvent((UINT)nearest_delta_ms, + mm_tc.wPeriodMin, 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); + fprintf(stderr, "Failed to re-arm win32 alarm timer\n"); + timeEndPeriod(mm_tc.wPeriodMin); exit(1); } } @@ -731,7 +673,7 @@ static int win32_start_timer(struct qemu_alarm_timer *t) host_alarm_handler, t, 1, - alarm_has_dynticks(t) ? 3600000 : 1, + 3600000, WT_EXECUTEINTIMERTHREAD); if (!success) { @@ -757,16 +699,20 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t nearest_delta_ns) { HANDLE hTimer = t->timer; - int nearest_delta_ms; + int64_t nearest_delta_ms; BOOLEAN success; - nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000; + nearest_delta_ms = nearest_delta_ns / 1000000; if (nearest_delta_ms < 1) { nearest_delta_ms = 1; } + /* ULONG_MAX can be 32 bit */ + if (nearest_delta_ms > ULONG_MAX) { + nearest_delta_ms = ULONG_MAX; + } success = ChangeTimerQueueTimer(NULL, hTimer, - nearest_delta_ms, + (unsigned long) nearest_delta_ms, 3600000); if (!success) { @@ -786,11 +732,28 @@ static void quit_timers(void) t->stop(t); } +#ifdef CONFIG_POSIX +static void reinit_timers(void) +{ + struct qemu_alarm_timer *t = alarm_timer; + t->stop(t); + if (t->start(t)) { + fprintf(stderr, "Internal timer error: aborting\n"); + exit(1); + } + qemu_rearm_alarm_timer(t); +} +#endif /* CONFIG_POSIX */ + int init_timer_alarm(void) { struct qemu_alarm_timer *t = NULL; int i, err = -1; + if (alarm_timer) { + return 0; + } + for (i = 0; alarm_timers[i].name; i++) { t = &alarm_timers[i]; @@ -804,19 +767,14 @@ int init_timer_alarm(void) goto fail; } - /* first event is at time 0 */ atexit(quit_timers); - t->pending = 1; +#ifdef CONFIG_POSIX + pthread_atfork(NULL, NULL, reinit_timers); +#endif alarm_timer = t; - return 0; fail: return err; } -int qemu_calculate_timeout(void) -{ - return 1000; -} -