]> Git Repo - qemu.git/blob - qemu-timer.c
qemu-timer: use atexit for quit_timers
[qemu.git] / qemu-timer.c
1 /*
2  * QEMU System Emulator
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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.
23  */
24
25 #include "sysemu.h"
26 #include "net.h"
27 #include "monitor.h"
28 #include "console.h"
29
30 #include "hw/hw.h"
31
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <time.h>
35 #include <errno.h>
36 #include <sys/time.h>
37 #include <signal.h>
38 #ifdef __FreeBSD__
39 #include <sys/param.h>
40 #endif
41
42 #ifdef _WIN32
43 #include <windows.h>
44 #include <mmsystem.h>
45 #endif
46
47 #include "qemu-timer.h"
48
49 /***********************************************************/
50 /* timers */
51
52 #define QEMU_CLOCK_REALTIME 0
53 #define QEMU_CLOCK_VIRTUAL  1
54 #define QEMU_CLOCK_HOST     2
55
56 struct QEMUClock {
57     int type;
58     int enabled;
59
60     QEMUTimer *active_timers;
61
62     NotifierList reset_notifiers;
63     int64_t last;
64 };
65
66 struct QEMUTimer {
67     QEMUClock *clock;
68     int64_t expire_time;        /* in nanoseconds */
69     int scale;
70     QEMUTimerCB *cb;
71     void *opaque;
72     struct QEMUTimer *next;
73 };
74
75 struct qemu_alarm_timer {
76     char const *name;
77     int (*start)(struct qemu_alarm_timer *t);
78     void (*stop)(struct qemu_alarm_timer *t);
79     void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
80 #if defined(__linux__)
81     int fd;
82     timer_t timer;
83 #elif defined(_WIN32)
84     HANDLE timer;
85 #endif
86     char expired;
87     char pending;
88 };
89
90 static struct qemu_alarm_timer *alarm_timer;
91
92 static bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
93 {
94     return timer_head && (timer_head->expire_time <= current_time);
95 }
96
97 int qemu_alarm_pending(void)
98 {
99     return alarm_timer->pending;
100 }
101
102 static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
103 {
104     return !!t->rearm;
105 }
106
107 static int64_t qemu_next_alarm_deadline(void)
108 {
109     int64_t delta;
110     int64_t rtdelta;
111
112     if (!use_icount && vm_clock->active_timers) {
113         delta = vm_clock->active_timers->expire_time -
114                      qemu_get_clock_ns(vm_clock);
115     } else {
116         delta = INT32_MAX;
117     }
118     if (host_clock->active_timers) {
119         int64_t hdelta = host_clock->active_timers->expire_time -
120                  qemu_get_clock_ns(host_clock);
121         if (hdelta < delta) {
122             delta = hdelta;
123         }
124     }
125     if (rt_clock->active_timers) {
126         rtdelta = (rt_clock->active_timers->expire_time -
127                  qemu_get_clock_ns(rt_clock));
128         if (rtdelta < delta) {
129             delta = rtdelta;
130         }
131     }
132
133     return delta;
134 }
135
136 static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
137 {
138     int64_t nearest_delta_ns;
139     assert(alarm_has_dynticks(t));
140     if (!rt_clock->active_timers &&
141         !vm_clock->active_timers &&
142         !host_clock->active_timers) {
143         return;
144     }
145     nearest_delta_ns = qemu_next_alarm_deadline();
146     t->rearm(t, nearest_delta_ns);
147 }
148
149 /* TODO: MIN_TIMER_REARM_NS should be optimized */
150 #define MIN_TIMER_REARM_NS 250000
151
152 #ifdef _WIN32
153
154 static int mm_start_timer(struct qemu_alarm_timer *t);
155 static void mm_stop_timer(struct qemu_alarm_timer *t);
156 static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
157
158 static int win32_start_timer(struct qemu_alarm_timer *t);
159 static void win32_stop_timer(struct qemu_alarm_timer *t);
160 static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
161
162 #else
163
164 static int unix_start_timer(struct qemu_alarm_timer *t);
165 static void unix_stop_timer(struct qemu_alarm_timer *t);
166 static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
167
168 #ifdef __linux__
169
170 static int dynticks_start_timer(struct qemu_alarm_timer *t);
171 static void dynticks_stop_timer(struct qemu_alarm_timer *t);
172 static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
173
174 #endif /* __linux__ */
175
176 #endif /* _WIN32 */
177
178 static struct qemu_alarm_timer alarm_timers[] = {
179 #ifndef _WIN32
180 #ifdef __linux__
181     {"dynticks", dynticks_start_timer,
182      dynticks_stop_timer, dynticks_rearm_timer},
183 #endif
184     {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer},
185 #else
186     {"mmtimer", mm_start_timer, mm_stop_timer, NULL},
187     {"mmtimer2", mm_start_timer, mm_stop_timer, mm_rearm_timer},
188     {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
189     {"win32", win32_start_timer, win32_stop_timer, NULL},
190 #endif
191     {NULL, }
192 };
193
194 static void show_available_alarms(void)
195 {
196     int i;
197
198     printf("Available alarm timers, in order of precedence:\n");
199     for (i = 0; alarm_timers[i].name; i++)
200         printf("%s\n", alarm_timers[i].name);
201 }
202
203 void configure_alarms(char const *opt)
204 {
205     int i;
206     int cur = 0;
207     int count = ARRAY_SIZE(alarm_timers) - 1;
208     char *arg;
209     char *name;
210     struct qemu_alarm_timer tmp;
211
212     if (!strcmp(opt, "?")) {
213         show_available_alarms();
214         exit(0);
215     }
216
217     arg = g_strdup(opt);
218
219     /* Reorder the array */
220     name = strtok(arg, ",");
221     while (name) {
222         for (i = 0; i < count && alarm_timers[i].name; i++) {
223             if (!strcmp(alarm_timers[i].name, name))
224                 break;
225         }
226
227         if (i == count) {
228             fprintf(stderr, "Unknown clock %s\n", name);
229             goto next;
230         }
231
232         if (i < cur)
233             /* Ignore */
234             goto next;
235
236         /* Swap */
237         tmp = alarm_timers[i];
238         alarm_timers[i] = alarm_timers[cur];
239         alarm_timers[cur] = tmp;
240
241         cur++;
242 next:
243         name = strtok(NULL, ",");
244     }
245
246     g_free(arg);
247
248     if (cur) {
249         /* Disable remaining timers */
250         for (i = cur; i < count; i++)
251             alarm_timers[i].name = NULL;
252     } else {
253         show_available_alarms();
254         exit(1);
255     }
256 }
257
258 QEMUClock *rt_clock;
259 QEMUClock *vm_clock;
260 QEMUClock *host_clock;
261
262 static QEMUClock *qemu_new_clock(int type)
263 {
264     QEMUClock *clock;
265
266     clock = g_malloc0(sizeof(QEMUClock));
267     clock->type = type;
268     clock->enabled = 1;
269     notifier_list_init(&clock->reset_notifiers);
270     /* required to detect & report backward jumps */
271     if (type == QEMU_CLOCK_HOST) {
272         clock->last = get_clock_realtime();
273     }
274     return clock;
275 }
276
277 void qemu_clock_enable(QEMUClock *clock, int enabled)
278 {
279     clock->enabled = enabled;
280 }
281
282 int64_t qemu_clock_has_timers(QEMUClock *clock)
283 {
284     return !!clock->active_timers;
285 }
286
287 int64_t qemu_clock_expired(QEMUClock *clock)
288 {
289     return (clock->active_timers &&
290             clock->active_timers->expire_time < qemu_get_clock_ns(clock));
291 }
292
293 int64_t qemu_clock_deadline(QEMUClock *clock)
294 {
295     /* To avoid problems with overflow limit this to 2^32.  */
296     int64_t delta = INT32_MAX;
297
298     if (clock->active_timers) {
299         delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
300     }
301     if (delta < 0) {
302         delta = 0;
303     }
304     return delta;
305 }
306
307 QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
308                           QEMUTimerCB *cb, void *opaque)
309 {
310     QEMUTimer *ts;
311
312     ts = g_malloc0(sizeof(QEMUTimer));
313     ts->clock = clock;
314     ts->cb = cb;
315     ts->opaque = opaque;
316     ts->scale = scale;
317     return ts;
318 }
319
320 void qemu_free_timer(QEMUTimer *ts)
321 {
322     g_free(ts);
323 }
324
325 /* stop a timer, but do not dealloc it */
326 void qemu_del_timer(QEMUTimer *ts)
327 {
328     QEMUTimer **pt, *t;
329
330     /* NOTE: this code must be signal safe because
331        qemu_timer_expired() can be called from a signal. */
332     pt = &ts->clock->active_timers;
333     for(;;) {
334         t = *pt;
335         if (!t)
336             break;
337         if (t == ts) {
338             *pt = t->next;
339             break;
340         }
341         pt = &t->next;
342     }
343 }
344
345 /* modify the current timer so that it will be fired when current_time
346    >= expire_time. The corresponding callback will be called. */
347 static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
348 {
349     QEMUTimer **pt, *t;
350
351     qemu_del_timer(ts);
352
353     /* add the timer in the sorted list */
354     /* NOTE: this code must be signal safe because
355        qemu_timer_expired() can be called from a signal. */
356     pt = &ts->clock->active_timers;
357     for(;;) {
358         t = *pt;
359         if (!qemu_timer_expired_ns(t, expire_time)) {
360             break;
361         }
362         pt = &t->next;
363     }
364     ts->expire_time = expire_time;
365     ts->next = *pt;
366     *pt = ts;
367
368     /* Rearm if necessary  */
369     if (pt == &ts->clock->active_timers) {
370         if (!alarm_timer->pending) {
371             qemu_rearm_alarm_timer(alarm_timer);
372         }
373         /* Interrupt execution to force deadline recalculation.  */
374         qemu_clock_warp(ts->clock);
375         if (use_icount) {
376             qemu_notify_event();
377         }
378     }
379 }
380
381 /* modify the current timer so that it will be fired when current_time
382    >= expire_time. The corresponding callback will be called. */
383 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
384 {
385     qemu_mod_timer_ns(ts, expire_time * ts->scale);
386 }
387
388 int qemu_timer_pending(QEMUTimer *ts)
389 {
390     QEMUTimer *t;
391     for (t = ts->clock->active_timers; t != NULL; t = t->next) {
392         if (t == ts)
393             return 1;
394     }
395     return 0;
396 }
397
398 int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
399 {
400     return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
401 }
402
403 static void qemu_run_timers(QEMUClock *clock)
404 {
405     QEMUTimer **ptimer_head, *ts;
406     int64_t current_time;
407    
408     if (!clock->enabled)
409         return;
410
411     current_time = qemu_get_clock_ns(clock);
412     ptimer_head = &clock->active_timers;
413     for(;;) {
414         ts = *ptimer_head;
415         if (!qemu_timer_expired_ns(ts, current_time)) {
416             break;
417         }
418         /* remove timer from the list before calling the callback */
419         *ptimer_head = ts->next;
420         ts->next = NULL;
421
422         /* run the callback (the timer list can be modified) */
423         ts->cb(ts->opaque);
424     }
425 }
426
427 int64_t qemu_get_clock_ns(QEMUClock *clock)
428 {
429     int64_t now, last;
430
431     switch(clock->type) {
432     case QEMU_CLOCK_REALTIME:
433         return get_clock();
434     default:
435     case QEMU_CLOCK_VIRTUAL:
436         if (use_icount) {
437             return cpu_get_icount();
438         } else {
439             return cpu_get_clock();
440         }
441     case QEMU_CLOCK_HOST:
442         now = get_clock_realtime();
443         last = clock->last;
444         clock->last = now;
445         if (now < last) {
446             notifier_list_notify(&clock->reset_notifiers, &now);
447         }
448         return now;
449     }
450 }
451
452 void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
453 {
454     notifier_list_add(&clock->reset_notifiers, notifier);
455 }
456
457 void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
458 {
459     notifier_list_remove(&clock->reset_notifiers, notifier);
460 }
461
462 void init_clocks(void)
463 {
464     rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
465     vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
466     host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
467
468     rtc_clock = host_clock;
469 }
470
471 /* save a timer */
472 void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
473 {
474     uint64_t expire_time;
475
476     if (qemu_timer_pending(ts)) {
477         expire_time = ts->expire_time;
478     } else {
479         expire_time = -1;
480     }
481     qemu_put_be64(f, expire_time);
482 }
483
484 void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
485 {
486     uint64_t expire_time;
487
488     expire_time = qemu_get_be64(f);
489     if (expire_time != -1) {
490         qemu_mod_timer_ns(ts, expire_time);
491     } else {
492         qemu_del_timer(ts);
493     }
494 }
495
496 void qemu_run_all_timers(void)
497 {
498     alarm_timer->pending = 0;
499
500     /* rearm timer, if not periodic */
501     if (alarm_timer->expired) {
502         alarm_timer->expired = 0;
503         qemu_rearm_alarm_timer(alarm_timer);
504     }
505
506     /* vm time timers */
507     qemu_run_timers(vm_clock);
508     qemu_run_timers(rt_clock);
509     qemu_run_timers(host_clock);
510 }
511
512 #ifdef _WIN32
513 static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
514 #else
515 static void host_alarm_handler(int host_signum)
516 #endif
517 {
518     struct qemu_alarm_timer *t = alarm_timer;
519     if (!t)
520         return;
521
522 #if 0
523 #define DISP_FREQ 1000
524     {
525         static int64_t delta_min = INT64_MAX;
526         static int64_t delta_max, delta_cum, last_clock, delta, ti;
527         static int count;
528         ti = qemu_get_clock_ns(vm_clock);
529         if (last_clock != 0) {
530             delta = ti - last_clock;
531             if (delta < delta_min)
532                 delta_min = delta;
533             if (delta > delta_max)
534                 delta_max = delta;
535             delta_cum += delta;
536             if (++count == DISP_FREQ) {
537                 printf("timer: min=%" PRId64 " us max=%" PRId64 " us avg=%" PRId64 " us avg_freq=%0.3f Hz\n",
538                        muldiv64(delta_min, 1000000, get_ticks_per_sec()),
539                        muldiv64(delta_max, 1000000, get_ticks_per_sec()),
540                        muldiv64(delta_cum, 1000000 / DISP_FREQ, get_ticks_per_sec()),
541                        (double)get_ticks_per_sec() / ((double)delta_cum / DISP_FREQ));
542                 count = 0;
543                 delta_min = INT64_MAX;
544                 delta_max = 0;
545                 delta_cum = 0;
546             }
547         }
548         last_clock = ti;
549     }
550 #endif
551     if (alarm_has_dynticks(t) ||
552         qemu_next_alarm_deadline () <= 0) {
553         t->expired = alarm_has_dynticks(t);
554         t->pending = 1;
555         qemu_notify_event();
556     }
557 }
558
559 #if defined(__linux__)
560
561 #include "compatfd.h"
562
563 static int dynticks_start_timer(struct qemu_alarm_timer *t)
564 {
565     struct sigevent ev;
566     timer_t host_timer;
567     struct sigaction act;
568
569     sigfillset(&act.sa_mask);
570     act.sa_flags = 0;
571     act.sa_handler = host_alarm_handler;
572
573     sigaction(SIGALRM, &act, NULL);
574
575     /* 
576      * Initialize ev struct to 0 to avoid valgrind complaining
577      * about uninitialized data in timer_create call
578      */
579     memset(&ev, 0, sizeof(ev));
580     ev.sigev_value.sival_int = 0;
581     ev.sigev_notify = SIGEV_SIGNAL;
582 #ifdef SIGEV_THREAD_ID
583     if (qemu_signalfd_available()) {
584         ev.sigev_notify = SIGEV_THREAD_ID;
585         ev._sigev_un._tid = qemu_get_thread_id();
586     }
587 #endif /* SIGEV_THREAD_ID */
588     ev.sigev_signo = SIGALRM;
589
590     if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
591         perror("timer_create");
592
593         /* disable dynticks */
594         fprintf(stderr, "Dynamic Ticks disabled\n");
595
596         return -1;
597     }
598
599     t->timer = host_timer;
600
601     return 0;
602 }
603
604 static void dynticks_stop_timer(struct qemu_alarm_timer *t)
605 {
606     timer_t host_timer = t->timer;
607
608     timer_delete(host_timer);
609 }
610
611 static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
612                                  int64_t nearest_delta_ns)
613 {
614     timer_t host_timer = t->timer;
615     struct itimerspec timeout;
616     int64_t current_ns;
617
618     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
619         nearest_delta_ns = MIN_TIMER_REARM_NS;
620
621     /* check whether a timer is already running */
622     if (timer_gettime(host_timer, &timeout)) {
623         perror("gettime");
624         fprintf(stderr, "Internal timer error: aborting\n");
625         exit(1);
626     }
627     current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
628     if (current_ns && current_ns <= nearest_delta_ns)
629         return;
630
631     timeout.it_interval.tv_sec = 0;
632     timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
633     timeout.it_value.tv_sec =  nearest_delta_ns / 1000000000;
634     timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
635     if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
636         perror("settime");
637         fprintf(stderr, "Internal timer error: aborting\n");
638         exit(1);
639     }
640 }
641
642 #endif /* defined(__linux__) */
643
644 #if !defined(_WIN32)
645
646 static int unix_start_timer(struct qemu_alarm_timer *t)
647 {
648     struct sigaction act;
649
650     /* timer signal */
651     sigfillset(&act.sa_mask);
652     act.sa_flags = 0;
653     act.sa_handler = host_alarm_handler;
654
655     sigaction(SIGALRM, &act, NULL);
656     return 0;
657 }
658
659 static void unix_rearm_timer(struct qemu_alarm_timer *t,
660                              int64_t nearest_delta_ns)
661 {
662     struct itimerval itv;
663     int err;
664
665     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
666         nearest_delta_ns = MIN_TIMER_REARM_NS;
667
668     itv.it_interval.tv_sec = 0;
669     itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
670     itv.it_value.tv_sec =  nearest_delta_ns / 1000000000;
671     itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
672     err = setitimer(ITIMER_REAL, &itv, NULL);
673     if (err) {
674         perror("setitimer");
675         fprintf(stderr, "Internal timer error: aborting\n");
676         exit(1);
677     }
678 }
679
680 static void unix_stop_timer(struct qemu_alarm_timer *t)
681 {
682     struct itimerval itv;
683
684     memset(&itv, 0, sizeof(itv));
685     setitimer(ITIMER_REAL, &itv, NULL);
686 }
687
688 #endif /* !defined(_WIN32) */
689
690
691 #ifdef _WIN32
692
693 static MMRESULT mm_timer;
694 static unsigned mm_period;
695
696 static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
697                                       DWORD_PTR dwUser, DWORD_PTR dw1,
698                                       DWORD_PTR dw2)
699 {
700     struct qemu_alarm_timer *t = alarm_timer;
701     if (!t) {
702         return;
703     }
704     if (alarm_has_dynticks(t) || qemu_next_alarm_deadline() <= 0) {
705         t->expired = alarm_has_dynticks(t);
706         t->pending = 1;
707         qemu_notify_event();
708     }
709 }
710
711 static int mm_start_timer(struct qemu_alarm_timer *t)
712 {
713     TIMECAPS tc;
714     UINT flags;
715
716     memset(&tc, 0, sizeof(tc));
717     timeGetDevCaps(&tc, sizeof(tc));
718
719     mm_period = tc.wPeriodMin;
720     timeBeginPeriod(mm_period);
721
722     flags = TIME_CALLBACK_FUNCTION;
723     if (alarm_has_dynticks(t)) {
724         flags |= TIME_ONESHOT;
725     } else {
726         flags |= TIME_PERIODIC;
727     }
728
729     mm_timer = timeSetEvent(1,                  /* interval (ms) */
730                             mm_period,          /* resolution */
731                             mm_alarm_handler,   /* function */
732                             (DWORD_PTR)t,       /* parameter */
733                             flags);
734
735     if (!mm_timer) {
736         fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
737                 GetLastError());
738         timeEndPeriod(mm_period);
739         return -1;
740     }
741
742     return 0;
743 }
744
745 static void mm_stop_timer(struct qemu_alarm_timer *t)
746 {
747     timeKillEvent(mm_timer);
748     timeEndPeriod(mm_period);
749 }
750
751 static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
752 {
753     int nearest_delta_ms = (delta + 999999) / 1000000;
754     if (nearest_delta_ms < 1) {
755         nearest_delta_ms = 1;
756     }
757
758     timeKillEvent(mm_timer);
759     mm_timer = timeSetEvent(nearest_delta_ms,
760                             mm_period,
761                             mm_alarm_handler,
762                             (DWORD_PTR)t,
763                             TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
764
765     if (!mm_timer) {
766         fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n",
767                 GetLastError());
768
769         timeEndPeriod(mm_period);
770         exit(1);
771     }
772 }
773
774 static int win32_start_timer(struct qemu_alarm_timer *t)
775 {
776     HANDLE hTimer;
777     BOOLEAN success;
778
779     /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
780        is zero) that has already expired, the timer is not updated.  Since
781        creating a new timer is relatively expensive, set a bogus one-hour
782        interval in the dynticks case.  */
783     success = CreateTimerQueueTimer(&hTimer,
784                           NULL,
785                           host_alarm_handler,
786                           t,
787                           1,
788                           alarm_has_dynticks(t) ? 3600000 : 1,
789                           WT_EXECUTEINTIMERTHREAD);
790
791     if (!success) {
792         fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
793                 GetLastError());
794         return -1;
795     }
796
797     t->timer = hTimer;
798     return 0;
799 }
800
801 static void win32_stop_timer(struct qemu_alarm_timer *t)
802 {
803     HANDLE hTimer = t->timer;
804
805     if (hTimer) {
806         DeleteTimerQueueTimer(NULL, hTimer, NULL);
807     }
808 }
809
810 static void win32_rearm_timer(struct qemu_alarm_timer *t,
811                               int64_t nearest_delta_ns)
812 {
813     HANDLE hTimer = t->timer;
814     int nearest_delta_ms;
815     BOOLEAN success;
816
817     nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000;
818     if (nearest_delta_ms < 1) {
819         nearest_delta_ms = 1;
820     }
821     success = ChangeTimerQueueTimer(NULL,
822                                     hTimer,
823                                     nearest_delta_ms,
824                                     3600000);
825
826     if (!success) {
827         fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
828                 GetLastError());
829         exit(-1);
830     }
831
832 }
833
834 #endif /* _WIN32 */
835
836 static void alarm_timer_on_change_state_rearm(void *opaque, int running,
837                                               RunState state)
838 {
839     if (running)
840         qemu_rearm_alarm_timer((struct qemu_alarm_timer *) opaque);
841 }
842
843 static void quit_timers(void)
844 {
845     struct qemu_alarm_timer *t = alarm_timer;
846     alarm_timer = NULL;
847     t->stop(t);
848 }
849
850 int init_timer_alarm(void)
851 {
852     struct qemu_alarm_timer *t = NULL;
853     int i, err = -1;
854
855     for (i = 0; alarm_timers[i].name; i++) {
856         t = &alarm_timers[i];
857
858         err = t->start(t);
859         if (!err)
860             break;
861     }
862
863     if (err) {
864         err = -ENOENT;
865         goto fail;
866     }
867
868     /* first event is at time 0 */
869     atexit(quit_timers);
870     t->pending = 1;
871     alarm_timer = t;
872     qemu_add_vm_change_state_handler(alarm_timer_on_change_state_rearm, t);
873
874     return 0;
875
876 fail:
877     return err;
878 }
879
880 int qemu_calculate_timeout(void)
881 {
882     return 1000;
883 }
884
This page took 0.06956 seconds and 4 git commands to generate.