From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55518) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V0bYc-000408-QF for qemu-devel@nongnu.org; Sat, 20 Jul 2013 14:07:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V0bYX-000834-BZ for qemu-devel@nongnu.org; Sat, 20 Jul 2013 14:07:02 -0400 Received: from mail.avalus.com ([2001:41c8:10:1dd::10]:49399) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V0bYW-00082D-VW for qemu-devel@nongnu.org; Sat, 20 Jul 2013 14:06:57 -0400 From: Alex Bligh Date: Sat, 20 Jul 2013 19:06:37 +0100 Message-Id: <1374343603-29183-2-git-send-email-alex@alex.org.uk> In-Reply-To: <1374343603-29183-1-git-send-email-alex@alex.org.uk> References: <1E8E204.8000201@redhat.com> <1374343603-29183-1-git-send-email-alex@alex.org.uk> Subject: [Qemu-devel] [PATCHv2] [RFC 1/7] aio / timers: Remove alarm timers List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , Anthony Liguori , Alex Bligh , Stefan Hajnoczi , Paolo Bonzini , rth@twiddle.net Remove alarm timers from qemu-timers.c in anticipation of using timeouts for g_poll / p_poll instead. Signed-off-by: Alex Bligh --- include/qemu/timer.h | 2 - main-loop.c | 4 - qemu-timer.c | 501 +------------------------------------------------- vl.c | 5 +- 4 files changed, 7 insertions(+), 505 deletions(-) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 9dd206c..8638d36 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -55,9 +55,7 @@ uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts); void qemu_run_timers(QEMUClock *clock); void qemu_run_all_timers(void); -void configure_alarms(char const *opt); void init_clocks(void); -int init_timer_alarm(void); int64_t cpu_get_ticks(void); void cpu_enable_ticks(void); diff --git a/main-loop.c b/main-loop.c index a44fff6..8918dd1 100644 --- a/main-loop.c +++ b/main-loop.c @@ -131,10 +131,6 @@ int qemu_init_main_loop(void) GSource *src; init_clocks(); - if (init_timer_alarm() < 0) { - fprintf(stderr, "could not initialize alarm timer\n"); - exit(1); - } ret = qemu_signal_init(); if (ret) { diff --git a/qemu-timer.c b/qemu-timer.c index b2d95e2..062af38 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -33,10 +33,6 @@ #include #endif -#ifdef _WIN32 -#include -#endif - /***********************************************************/ /* timers */ @@ -63,170 +59,11 @@ struct QEMUTimer { int scale; }; -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, int64_t nearest_delta_ns); -#if defined(__linux__) - timer_t timer; - int fd; -#elif defined(_WIN32) - HANDLE timer; -#endif - bool expired; - bool pending; -}; - -static struct qemu_alarm_timer *alarm_timer; - static bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time) { return timer_head && (timer_head->expire_time <= current_time); } -static int64_t qemu_next_alarm_deadline(void) -{ - int64_t delta = INT64_MAX; - int64_t rtdelta; - - if (!use_icount && vm_clock->enabled && vm_clock->active_timers) { - delta = vm_clock->active_timers->expire_time - - qemu_get_clock_ns(vm_clock); - } - 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->enabled && 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) -{ - int64_t nearest_delta_ns = qemu_next_alarm_deadline(); - if (nearest_delta_ns < INT64_MAX) { - t->rearm(t, nearest_delta_ns); - } -} - -/* TODO: MIN_TIMER_REARM_NS should be optimized */ -#define MIN_TIMER_REARM_NS 250000 - -#ifdef _WIN32 - -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, 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, 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, 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, int64_t delta); - -#endif /* __linux__ */ - -#endif /* _WIN32 */ - -static struct qemu_alarm_timer alarm_timers[] = { -#ifndef _WIN32 -#ifdef __linux__ - {"dynticks", dynticks_start_timer, - dynticks_stop_timer, dynticks_rearm_timer}, -#endif - {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer}, -#else - {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer}, - {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer}, -#endif - {NULL, } -}; - -static void show_available_alarms(void) -{ - int i; - - printf("Available alarm timers, in order of precedence:\n"); - for (i = 0; alarm_timers[i].name; i++) - printf("%s\n", alarm_timers[i].name); -} - -void configure_alarms(char const *opt) -{ - int i; - int cur = 0; - int count = ARRAY_SIZE(alarm_timers) - 1; - char *arg; - char *name; - struct qemu_alarm_timer tmp; - - if (is_help_option(opt)) { - show_available_alarms(); - exit(0); - } - - arg = g_strdup(opt); - - /* Reorder the array */ - name = strtok(arg, ","); - while (name) { - for (i = 0; i < count && alarm_timers[i].name; i++) { - if (!strcmp(alarm_timers[i].name, name)) - break; - } - - if (i == count) { - fprintf(stderr, "Unknown clock %s\n", name); - goto next; - } - - if (i < cur) - /* Ignore */ - goto next; - - /* Swap */ - tmp = alarm_timers[i]; - alarm_timers[i] = alarm_timers[cur]; - alarm_timers[cur] = tmp; - - cur++; -next: - name = strtok(NULL, ","); - } - - g_free(arg); - - if (cur) { - /* Disable remaining timers */ - for (i = cur; i < count; i++) - alarm_timers[i].name = NULL; - } else { - show_available_alarms(); - exit(1); - } -} - QEMUClock *rt_clock; QEMUClock *vm_clock; QEMUClock *host_clock; @@ -245,11 +82,7 @@ static QEMUClock *qemu_new_clock(int type) void qemu_clock_enable(QEMUClock *clock, bool 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) @@ -340,10 +173,9 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) /* Rearm if necessary */ if (pt == &ts->clock->active_timers) { - if (!alarm_timer->pending) { - qemu_rearm_alarm_timer(alarm_timer); - } - /* Interrupt execution to force deadline recalculation. */ + /* Interrupt execution to force deadline recalculation. + * FIXME: Do we need to do this now? + */ qemu_clock_warp(ts->clock); if (use_icount) { qemu_notify_event(); @@ -446,335 +278,8 @@ uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts) void qemu_run_all_timers(void) { - 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 -static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused) -#else -static void host_alarm_handler(int host_signum) -#endif -{ - struct qemu_alarm_timer *t = alarm_timer; - if (!t) - return; - - t->expired = true; - t->pending = true; - qemu_notify_event(); } - -#if defined(__linux__) - -#include "qemu/compatfd.h" - -static int dynticks_start_timer(struct qemu_alarm_timer *t) -{ - struct sigevent ev; - timer_t host_timer; - struct sigaction act; - - sigfillset(&act.sa_mask); - act.sa_flags = 0; - act.sa_handler = host_alarm_handler; - - sigaction(SIGALRM, &act, NULL); - - /* - * Initialize ev struct to 0 to avoid valgrind complaining - * about uninitialized data in timer_create call - */ - memset(&ev, 0, sizeof(ev)); - ev.sigev_value.sival_int = 0; - ev.sigev_notify = SIGEV_SIGNAL; -#ifdef CONFIG_SIGEV_THREAD_ID - if (qemu_signalfd_available()) { - ev.sigev_notify = SIGEV_THREAD_ID; - ev._sigev_un._tid = qemu_get_thread_id(); - } -#endif /* CONFIG_SIGEV_THREAD_ID */ - ev.sigev_signo = SIGALRM; - - if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) { - perror("timer_create"); - return -1; - } - - t->timer = host_timer; - - return 0; -} - -static void dynticks_stop_timer(struct qemu_alarm_timer *t) -{ - timer_t host_timer = t->timer; - - timer_delete(host_timer); -} - -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 current_ns; - - 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); - } -} - -#endif /* defined(__linux__) */ - -#if !defined(_WIN32) - -static int unix_start_timer(struct qemu_alarm_timer *t) -{ - struct sigaction act; - - /* timer signal */ - sigfillset(&act.sa_mask); - act.sa_flags = 0; - act.sa_handler = host_alarm_handler; - - sigaction(SIGALRM, &act, NULL); - return 0; -} - -static void unix_rearm_timer(struct qemu_alarm_timer *t, - int64_t nearest_delta_ns) -{ - struct itimerval itv; - int err; - - 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 unix_stop_timer(struct qemu_alarm_timer *t) -{ - struct itimerval itv; - - memset(&itv, 0, sizeof(itv)); - setitimer(ITIMER_REAL, &itv, NULL); -} - -#endif /* !defined(_WIN32) */ - - -#ifdef _WIN32 - -static MMRESULT mm_timer; -static TIMECAPS mm_tc; - -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; - } - t->expired = true; - t->pending = true; - qemu_notify_event(); -} - -static int mm_start_timer(struct qemu_alarm_timer *t) -{ - timeGetDevCaps(&mm_tc, sizeof(mm_tc)); - return 0; -} - -static void mm_stop_timer(struct qemu_alarm_timer *t) -{ - if (mm_timer) { - timeKillEvent(mm_timer); - } -} - -static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta) -{ - 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; - } - - 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\n"); - timeEndPeriod(mm_tc.wPeriodMin); - 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, - 3600000, - WT_EXECUTEINTIMERTHREAD); - - if (!success) { - fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", - GetLastError()); - return -1; - } - - t->timer = hTimer; - return 0; -} - -static void win32_stop_timer(struct qemu_alarm_timer *t) -{ - HANDLE hTimer = t->timer; - - if (hTimer) { - DeleteTimerQueueTimer(NULL, hTimer, NULL); - } -} - -static void win32_rearm_timer(struct qemu_alarm_timer *t, - int64_t nearest_delta_ns) -{ - HANDLE hTimer = t->timer; - int64_t nearest_delta_ms; - BOOLEAN success; - - 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, - (unsigned long) nearest_delta_ms, - 3600000); - - if (!success) { - fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n", - GetLastError()); - exit(-1); - } - -} - -#endif /* _WIN32 */ - -static void quit_timers(void) -{ - struct qemu_alarm_timer *t = alarm_timer; - alarm_timer = NULL; - 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]; - - err = t->start(t); - if (!err) - break; - } - - if (err) { - err = -ENOENT; - goto fail; - } - - atexit(quit_timers); -#ifdef CONFIG_POSIX - pthread_atfork(NULL, NULL, reinit_timers); -#endif - alarm_timer = t; - return 0; - -fail: - return err; -} - diff --git a/vl.c b/vl.c index 25b8f2f..612c609 100644 --- a/vl.c +++ b/vl.c @@ -3714,7 +3714,10 @@ int main(int argc, char **argv, char **envp) old_param = 1; break; case QEMU_OPTION_clock: - configure_alarms(optarg); + /* Once upon a time we did: + * configure_alarms(optarg); + * here. This is stubbed out for compatibility. + */ break; case QEMU_OPTION_startdate: configure_rtc_date_offset(optarg, 1); -- 1.7.9.5