aio / timers: Add QEMUTimerListGroup and helper functions
[qemu/ar7.git] / qemu-timer.c
blobc5e456e0b14687e250f1350a27547b9d02c2f407
1 /*
2 * QEMU System Emulator
4 * Copyright (c) 2003-2008 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "sysemu/sysemu.h"
26 #include "monitor/monitor.h"
27 #include "ui/console.h"
29 #include "hw/hw.h"
31 #include "qemu/timer.h"
32 #ifdef CONFIG_POSIX
33 #include <pthread.h>
34 #endif
36 #ifdef _WIN32
37 #include <mmsystem.h>
38 #endif
40 #ifdef CONFIG_PPOLL
41 #include <poll.h>
42 #endif
44 #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
45 #include <sys/prctl.h>
46 #endif
48 /***********************************************************/
49 /* timers */
51 struct QEMUClock {
52 QEMUTimerList *main_loop_timerlist;
53 QLIST_HEAD(, QEMUTimerList) timerlists;
55 NotifierList reset_notifiers;
56 int64_t last;
58 QEMUClockType type;
59 bool enabled;
62 QEMUTimerListGroup main_loop_tlg;
63 QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
65 /* A QEMUTimerList is a list of timers attached to a clock. More
66 * than one QEMUTimerList can be attached to each clock, for instance
67 * used by different AioContexts / threads. Each clock also has
68 * a list of the QEMUTimerLists associated with it, in order that
69 * reenabling the clock can call all the notifiers.
72 struct QEMUTimerList {
73 QEMUClock *clock;
74 QEMUTimer *active_timers;
75 QLIST_ENTRY(QEMUTimerList) list;
78 struct qemu_alarm_timer {
79 char const *name;
80 int (*start)(struct qemu_alarm_timer *t);
81 void (*stop)(struct qemu_alarm_timer *t);
82 void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
83 #if defined(__linux__)
84 timer_t timer;
85 int fd;
86 #elif defined(_WIN32)
87 HANDLE timer;
88 #endif
89 bool expired;
90 bool pending;
93 static struct qemu_alarm_timer *alarm_timer;
95 static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
97 return timer_head && (timer_head->expire_time <= current_time);
100 static int64_t qemu_next_alarm_deadline(void)
102 int64_t delta = INT64_MAX;
103 int64_t rtdelta;
104 int64_t hdelta;
106 if (!use_icount && vm_clock->enabled &&
107 vm_clock->main_loop_timerlist->active_timers) {
108 delta = vm_clock->main_loop_timerlist->active_timers->expire_time -
109 qemu_get_clock_ns(vm_clock);
111 if (host_clock->enabled &&
112 host_clock->main_loop_timerlist->active_timers) {
113 hdelta = host_clock->main_loop_timerlist->active_timers->expire_time -
114 qemu_get_clock_ns(host_clock);
115 if (hdelta < delta) {
116 delta = hdelta;
119 if (rt_clock->enabled &&
120 rt_clock->main_loop_timerlist->active_timers) {
121 rtdelta = (rt_clock->main_loop_timerlist->active_timers->expire_time -
122 qemu_get_clock_ns(rt_clock));
123 if (rtdelta < delta) {
124 delta = rtdelta;
128 return delta;
131 static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
133 int64_t nearest_delta_ns = qemu_next_alarm_deadline();
134 if (nearest_delta_ns < INT64_MAX) {
135 t->rearm(t, nearest_delta_ns);
139 /* TODO: MIN_TIMER_REARM_NS should be optimized */
140 #define MIN_TIMER_REARM_NS 250000
142 #ifdef _WIN32
144 static int mm_start_timer(struct qemu_alarm_timer *t);
145 static void mm_stop_timer(struct qemu_alarm_timer *t);
146 static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
148 static int win32_start_timer(struct qemu_alarm_timer *t);
149 static void win32_stop_timer(struct qemu_alarm_timer *t);
150 static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
152 #else
154 static int unix_start_timer(struct qemu_alarm_timer *t);
155 static void unix_stop_timer(struct qemu_alarm_timer *t);
156 static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
158 #ifdef __linux__
160 static int dynticks_start_timer(struct qemu_alarm_timer *t);
161 static void dynticks_stop_timer(struct qemu_alarm_timer *t);
162 static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
164 #endif /* __linux__ */
166 #endif /* _WIN32 */
168 static struct qemu_alarm_timer alarm_timers[] = {
169 #ifndef _WIN32
170 #ifdef __linux__
171 {"dynticks", dynticks_start_timer,
172 dynticks_stop_timer, dynticks_rearm_timer},
173 #endif
174 {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer},
175 #else
176 {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer},
177 {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
178 #endif
179 {NULL, }
182 static void show_available_alarms(void)
184 int i;
186 printf("Available alarm timers, in order of precedence:\n");
187 for (i = 0; alarm_timers[i].name; i++)
188 printf("%s\n", alarm_timers[i].name);
191 void configure_alarms(char const *opt)
193 int i;
194 int cur = 0;
195 int count = ARRAY_SIZE(alarm_timers) - 1;
196 char *arg;
197 char *name;
198 struct qemu_alarm_timer tmp;
200 if (is_help_option(opt)) {
201 show_available_alarms();
202 exit(0);
205 arg = g_strdup(opt);
207 /* Reorder the array */
208 name = strtok(arg, ",");
209 while (name) {
210 for (i = 0; i < count && alarm_timers[i].name; i++) {
211 if (!strcmp(alarm_timers[i].name, name))
212 break;
215 if (i == count) {
216 fprintf(stderr, "Unknown clock %s\n", name);
217 goto next;
220 if (i < cur)
221 /* Ignore */
222 goto next;
224 /* Swap */
225 tmp = alarm_timers[i];
226 alarm_timers[i] = alarm_timers[cur];
227 alarm_timers[cur] = tmp;
229 cur++;
230 next:
231 name = strtok(NULL, ",");
234 g_free(arg);
236 if (cur) {
237 /* Disable remaining timers */
238 for (i = cur; i < count; i++)
239 alarm_timers[i].name = NULL;
240 } else {
241 show_available_alarms();
242 exit(1);
246 static QEMUTimerList *timerlist_new_from_clock(QEMUClock *clock)
248 QEMUTimerList *timer_list;
250 /* Assert if we do not have a clock. If you see this
251 * assertion in means that the clocks have not been
252 * initialised before a timerlist is needed. This
253 * normally happens if an AioContext is used before
254 * init_clocks() is called within main().
256 assert(clock);
258 timer_list = g_malloc0(sizeof(QEMUTimerList));
259 timer_list->clock = clock;
260 QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
261 return timer_list;
264 QEMUTimerList *timerlist_new(QEMUClockType type)
266 return timerlist_new_from_clock(qemu_clock_ptr(type));
269 void timerlist_free(QEMUTimerList *timer_list)
271 assert(!timerlist_has_timers(timer_list));
272 if (timer_list->clock) {
273 QLIST_REMOVE(timer_list, list);
274 if (timer_list->clock->main_loop_timerlist == timer_list) {
275 timer_list->clock->main_loop_timerlist = NULL;
278 g_free(timer_list);
281 static QEMUClock *qemu_clock_new(QEMUClockType type)
283 QEMUClock *clock;
285 clock = g_malloc0(sizeof(QEMUClock));
286 clock->type = type;
287 clock->enabled = true;
288 clock->last = INT64_MIN;
289 QLIST_INIT(&clock->timerlists);
290 notifier_list_init(&clock->reset_notifiers);
291 clock->main_loop_timerlist = timerlist_new_from_clock(clock);
292 return clock;
295 bool qemu_clock_use_for_deadline(QEMUClock *clock)
297 return !(use_icount && (clock->type == QEMU_CLOCK_VIRTUAL));
300 void qemu_clock_enable(QEMUClock *clock, bool enabled)
302 bool old = clock->enabled;
303 clock->enabled = enabled;
304 if (enabled && !old) {
305 qemu_rearm_alarm_timer(alarm_timer);
309 bool timerlist_has_timers(QEMUTimerList *timer_list)
311 return !!timer_list->active_timers;
314 bool qemu_clock_has_timers(QEMUClock *clock)
316 return timerlist_has_timers(clock->main_loop_timerlist);
319 bool timerlist_expired(QEMUTimerList *timer_list)
321 return (timer_list->active_timers &&
322 timer_list->active_timers->expire_time <
323 qemu_get_clock_ns(timer_list->clock));
326 bool qemu_clock_expired(QEMUClock *clock)
328 return timerlist_expired(clock->main_loop_timerlist);
331 int64_t timerlist_deadline(QEMUTimerList *timer_list)
333 /* To avoid problems with overflow limit this to 2^32. */
334 int64_t delta = INT32_MAX;
336 if (timer_list->clock->enabled && timer_list->active_timers) {
337 delta = timer_list->active_timers->expire_time -
338 qemu_get_clock_ns(timer_list->clock);
340 if (delta < 0) {
341 delta = 0;
343 return delta;
346 int64_t qemu_clock_deadline(QEMUClock *clock)
348 return timerlist_deadline(clock->main_loop_timerlist);
352 * As above, but return -1 for no deadline, and do not cap to 2^32
353 * as we know the result is always positive.
356 int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
358 int64_t delta;
360 if (!timer_list->clock->enabled || !timer_list->active_timers) {
361 return -1;
364 delta = timer_list->active_timers->expire_time -
365 qemu_get_clock_ns(timer_list->clock);
367 if (delta <= 0) {
368 return 0;
371 return delta;
374 int64_t qemu_clock_deadline_ns(QEMUClock *clock)
376 return timerlist_deadline_ns(clock->main_loop_timerlist);
379 QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list)
381 return timer_list->clock;
384 QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClock *clock)
386 return clock->main_loop_timerlist;
389 /* Transition function to convert a nanosecond timeout to ms
390 * This is used where a system does not support ppoll
392 int qemu_timeout_ns_to_ms(int64_t ns)
394 int64_t ms;
395 if (ns < 0) {
396 return -1;
399 if (!ns) {
400 return 0;
403 /* Always round up, because it's better to wait too long than to wait too
404 * little and effectively busy-wait
406 ms = (ns + SCALE_MS - 1) / SCALE_MS;
408 /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
409 if (ms > (int64_t) INT32_MAX) {
410 ms = INT32_MAX;
413 return (int) ms;
417 /* qemu implementation of g_poll which uses a nanosecond timeout but is
418 * otherwise identical to g_poll
420 int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout)
422 #ifdef CONFIG_PPOLL
423 if (timeout < 0) {
424 return ppoll((struct pollfd *)fds, nfds, NULL, NULL);
425 } else {
426 struct timespec ts;
427 ts.tv_sec = timeout / 1000000000LL;
428 ts.tv_nsec = timeout % 1000000000LL;
429 return ppoll((struct pollfd *)fds, nfds, &ts, NULL);
431 #else
432 return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout));
433 #endif
437 void timer_init(QEMUTimer *ts,
438 QEMUTimerList *timer_list, int scale,
439 QEMUTimerCB *cb, void *opaque)
441 ts->timer_list = timer_list;
442 ts->cb = cb;
443 ts->opaque = opaque;
444 ts->scale = scale;
447 QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
448 QEMUTimerCB *cb, void *opaque)
450 return timer_new_tl(clock->main_loop_timerlist,
451 scale, cb, opaque);
454 void qemu_free_timer(QEMUTimer *ts)
456 g_free(ts);
459 /* stop a timer, but do not dealloc it */
460 void qemu_del_timer(QEMUTimer *ts)
462 QEMUTimer **pt, *t;
464 /* NOTE: this code must be signal safe because
465 timer_expired() can be called from a signal. */
466 pt = &ts->timer_list->active_timers;
467 for(;;) {
468 t = *pt;
469 if (!t)
470 break;
471 if (t == ts) {
472 *pt = t->next;
473 break;
475 pt = &t->next;
479 /* modify the current timer so that it will be fired when current_time
480 >= expire_time. The corresponding callback will be called. */
481 void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
483 QEMUTimer **pt, *t;
485 qemu_del_timer(ts);
487 /* add the timer in the sorted list */
488 /* NOTE: this code must be signal safe because
489 timer_expired() can be called from a signal. */
490 pt = &ts->timer_list->active_timers;
491 for(;;) {
492 t = *pt;
493 if (!timer_expired_ns(t, expire_time)) {
494 break;
496 pt = &t->next;
498 ts->expire_time = expire_time;
499 ts->next = *pt;
500 *pt = ts;
502 /* Rearm if necessary */
503 if (pt == &ts->timer_list->active_timers) {
504 if (!alarm_timer->pending) {
505 qemu_rearm_alarm_timer(alarm_timer);
507 /* Interrupt execution to force deadline recalculation. */
508 qemu_clock_warp(ts->timer_list->clock);
509 if (use_icount) {
510 qemu_notify_event();
515 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
517 qemu_mod_timer_ns(ts, expire_time * ts->scale);
520 bool timer_pending(QEMUTimer *ts)
522 QEMUTimer *t;
523 for (t = ts->timer_list->active_timers; t != NULL; t = t->next) {
524 if (t == ts) {
525 return true;
528 return false;
531 bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
533 return timer_expired_ns(timer_head, current_time * timer_head->scale);
536 bool timerlist_run_timers(QEMUTimerList *timer_list)
538 QEMUTimer *ts;
539 int64_t current_time;
540 bool progress = false;
542 if (!timer_list->clock->enabled) {
543 return progress;
546 current_time = qemu_get_clock_ns(timer_list->clock);
547 for(;;) {
548 ts = timer_list->active_timers;
549 if (!timer_expired_ns(ts, current_time)) {
550 break;
552 /* remove timer from the list before calling the callback */
553 timer_list->active_timers = ts->next;
554 ts->next = NULL;
556 /* run the callback (the timer list can be modified) */
557 ts->cb(ts->opaque);
558 progress = true;
560 return progress;
563 bool qemu_run_timers(QEMUClock *clock)
565 return timerlist_run_timers(clock->main_loop_timerlist);
568 void timerlistgroup_init(QEMUTimerListGroup *tlg)
570 QEMUClockType type;
571 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
572 tlg->tl[type] = timerlist_new(type);
576 void timerlistgroup_deinit(QEMUTimerListGroup *tlg)
578 QEMUClockType type;
579 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
580 timerlist_free(tlg->tl[type]);
584 bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg)
586 QEMUClockType type;
587 bool progress = false;
588 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
589 progress |= timerlist_run_timers(tlg->tl[type]);
591 return progress;
594 int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg)
596 int64_t deadline = -1;
597 QEMUClockType type;
598 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
599 if (qemu_clock_use_for_deadline(tlg->tl[type]->clock)) {
600 deadline = qemu_soonest_timeout(deadline,
601 timerlist_deadline_ns(
602 tlg->tl[type]));
605 return deadline;
608 int64_t qemu_get_clock_ns(QEMUClock *clock)
610 int64_t now, last;
612 switch(clock->type) {
613 case QEMU_CLOCK_REALTIME:
614 return get_clock();
615 default:
616 case QEMU_CLOCK_VIRTUAL:
617 if (use_icount) {
618 return cpu_get_icount();
619 } else {
620 return cpu_get_clock();
622 case QEMU_CLOCK_HOST:
623 now = get_clock_realtime();
624 last = clock->last;
625 clock->last = now;
626 if (now < last) {
627 notifier_list_notify(&clock->reset_notifiers, &now);
629 return now;
633 void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
635 notifier_list_add(&clock->reset_notifiers, notifier);
638 void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
640 notifier_remove(notifier);
643 void init_clocks(void)
645 QEMUClockType type;
646 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
647 if (!qemu_clocks[type]) {
648 qemu_clocks[type] = qemu_clock_new(type);
649 main_loop_tlg.tl[type] = qemu_clocks[type]->main_loop_timerlist;
653 #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
654 prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
655 #endif
658 uint64_t timer_expire_time_ns(QEMUTimer *ts)
660 return timer_pending(ts) ? ts->expire_time : -1;
663 bool qemu_run_all_timers(void)
665 bool progress = false;
666 alarm_timer->pending = false;
668 /* vm time timers */
669 QEMUClockType type;
670 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
671 progress |= qemu_run_timers(qemu_clock_ptr(type));
674 /* rearm timer, if not periodic */
675 if (alarm_timer->expired) {
676 alarm_timer->expired = false;
677 qemu_rearm_alarm_timer(alarm_timer);
680 return progress;
683 #ifdef _WIN32
684 static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
685 #else
686 static void host_alarm_handler(int host_signum)
687 #endif
689 struct qemu_alarm_timer *t = alarm_timer;
690 if (!t)
691 return;
693 t->expired = true;
694 t->pending = true;
695 qemu_notify_event();
698 #if defined(__linux__)
700 #include "qemu/compatfd.h"
702 static int dynticks_start_timer(struct qemu_alarm_timer *t)
704 struct sigevent ev;
705 timer_t host_timer;
706 struct sigaction act;
708 sigfillset(&act.sa_mask);
709 act.sa_flags = 0;
710 act.sa_handler = host_alarm_handler;
712 sigaction(SIGALRM, &act, NULL);
715 * Initialize ev struct to 0 to avoid valgrind complaining
716 * about uninitialized data in timer_create call
718 memset(&ev, 0, sizeof(ev));
719 ev.sigev_value.sival_int = 0;
720 ev.sigev_notify = SIGEV_SIGNAL;
721 #ifdef CONFIG_SIGEV_THREAD_ID
722 if (qemu_signalfd_available()) {
723 ev.sigev_notify = SIGEV_THREAD_ID;
724 ev._sigev_un._tid = qemu_get_thread_id();
726 #endif /* CONFIG_SIGEV_THREAD_ID */
727 ev.sigev_signo = SIGALRM;
729 if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
730 perror("timer_create");
731 return -1;
734 t->timer = host_timer;
736 return 0;
739 static void dynticks_stop_timer(struct qemu_alarm_timer *t)
741 timer_t host_timer = t->timer;
743 timer_delete(host_timer);
746 static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
747 int64_t nearest_delta_ns)
749 timer_t host_timer = t->timer;
750 struct itimerspec timeout;
751 int64_t current_ns;
753 if (nearest_delta_ns < MIN_TIMER_REARM_NS)
754 nearest_delta_ns = MIN_TIMER_REARM_NS;
756 /* check whether a timer is already running */
757 if (timer_gettime(host_timer, &timeout)) {
758 perror("gettime");
759 fprintf(stderr, "Internal timer error: aborting\n");
760 exit(1);
762 current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
763 if (current_ns && current_ns <= nearest_delta_ns)
764 return;
766 timeout.it_interval.tv_sec = 0;
767 timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
768 timeout.it_value.tv_sec = nearest_delta_ns / 1000000000;
769 timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
770 if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
771 perror("settime");
772 fprintf(stderr, "Internal timer error: aborting\n");
773 exit(1);
777 #endif /* defined(__linux__) */
779 #if !defined(_WIN32)
781 static int unix_start_timer(struct qemu_alarm_timer *t)
783 struct sigaction act;
785 /* timer signal */
786 sigfillset(&act.sa_mask);
787 act.sa_flags = 0;
788 act.sa_handler = host_alarm_handler;
790 sigaction(SIGALRM, &act, NULL);
791 return 0;
794 static void unix_rearm_timer(struct qemu_alarm_timer *t,
795 int64_t nearest_delta_ns)
797 struct itimerval itv;
798 int err;
800 if (nearest_delta_ns < MIN_TIMER_REARM_NS)
801 nearest_delta_ns = MIN_TIMER_REARM_NS;
803 itv.it_interval.tv_sec = 0;
804 itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
805 itv.it_value.tv_sec = nearest_delta_ns / 1000000000;
806 itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
807 err = setitimer(ITIMER_REAL, &itv, NULL);
808 if (err) {
809 perror("setitimer");
810 fprintf(stderr, "Internal timer error: aborting\n");
811 exit(1);
815 static void unix_stop_timer(struct qemu_alarm_timer *t)
817 struct itimerval itv;
819 memset(&itv, 0, sizeof(itv));
820 setitimer(ITIMER_REAL, &itv, NULL);
823 #endif /* !defined(_WIN32) */
826 #ifdef _WIN32
828 static MMRESULT mm_timer;
829 static TIMECAPS mm_tc;
831 static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
832 DWORD_PTR dwUser, DWORD_PTR dw1,
833 DWORD_PTR dw2)
835 struct qemu_alarm_timer *t = alarm_timer;
836 if (!t) {
837 return;
839 t->expired = true;
840 t->pending = true;
841 qemu_notify_event();
844 static int mm_start_timer(struct qemu_alarm_timer *t)
846 timeGetDevCaps(&mm_tc, sizeof(mm_tc));
847 return 0;
850 static void mm_stop_timer(struct qemu_alarm_timer *t)
852 if (mm_timer) {
853 timeKillEvent(mm_timer);
857 static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
859 int64_t nearest_delta_ms = delta / 1000000;
860 if (nearest_delta_ms < mm_tc.wPeriodMin) {
861 nearest_delta_ms = mm_tc.wPeriodMin;
862 } else if (nearest_delta_ms > mm_tc.wPeriodMax) {
863 nearest_delta_ms = mm_tc.wPeriodMax;
866 if (mm_timer) {
867 timeKillEvent(mm_timer);
869 mm_timer = timeSetEvent((UINT)nearest_delta_ms,
870 mm_tc.wPeriodMin,
871 mm_alarm_handler,
872 (DWORD_PTR)t,
873 TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
875 if (!mm_timer) {
876 fprintf(stderr, "Failed to re-arm win32 alarm timer\n");
877 timeEndPeriod(mm_tc.wPeriodMin);
878 exit(1);
882 static int win32_start_timer(struct qemu_alarm_timer *t)
884 HANDLE hTimer;
885 BOOLEAN success;
887 /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
888 is zero) that has already expired, the timer is not updated. Since
889 creating a new timer is relatively expensive, set a bogus one-hour
890 interval in the dynticks case. */
891 success = CreateTimerQueueTimer(&hTimer,
892 NULL,
893 host_alarm_handler,
896 3600000,
897 WT_EXECUTEINTIMERTHREAD);
899 if (!success) {
900 fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
901 GetLastError());
902 return -1;
905 t->timer = hTimer;
906 return 0;
909 static void win32_stop_timer(struct qemu_alarm_timer *t)
911 HANDLE hTimer = t->timer;
913 if (hTimer) {
914 DeleteTimerQueueTimer(NULL, hTimer, NULL);
918 static void win32_rearm_timer(struct qemu_alarm_timer *t,
919 int64_t nearest_delta_ns)
921 HANDLE hTimer = t->timer;
922 int64_t nearest_delta_ms;
923 BOOLEAN success;
925 nearest_delta_ms = nearest_delta_ns / 1000000;
926 if (nearest_delta_ms < 1) {
927 nearest_delta_ms = 1;
929 /* ULONG_MAX can be 32 bit */
930 if (nearest_delta_ms > ULONG_MAX) {
931 nearest_delta_ms = ULONG_MAX;
933 success = ChangeTimerQueueTimer(NULL,
934 hTimer,
935 (unsigned long) nearest_delta_ms,
936 3600000);
938 if (!success) {
939 fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
940 GetLastError());
941 exit(-1);
946 #endif /* _WIN32 */
948 static void quit_timers(void)
950 struct qemu_alarm_timer *t = alarm_timer;
951 alarm_timer = NULL;
952 t->stop(t);
955 #ifdef CONFIG_POSIX
956 static void reinit_timers(void)
958 struct qemu_alarm_timer *t = alarm_timer;
959 t->stop(t);
960 if (t->start(t)) {
961 fprintf(stderr, "Internal timer error: aborting\n");
962 exit(1);
964 qemu_rearm_alarm_timer(t);
966 #endif /* CONFIG_POSIX */
968 int init_timer_alarm(void)
970 struct qemu_alarm_timer *t = NULL;
971 int i, err = -1;
973 if (alarm_timer) {
974 return 0;
977 for (i = 0; alarm_timers[i].name; i++) {
978 t = &alarm_timers[i];
980 err = t->start(t);
981 if (!err)
982 break;
985 if (err) {
986 err = -ENOENT;
987 goto fail;
990 atexit(quit_timers);
991 #ifdef CONFIG_POSIX
992 pthread_atfork(NULL, NULL, reinit_timers);
993 #endif
994 alarm_timer = t;
995 return 0;
997 fail:
998 return err;