]> Git Repo - qemu.git/blob - qemu-timer.c
arm_gic: handle banked enable bits for per-cpu interrupts
[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     clock->last = INT64_MIN;
270     notifier_list_init(&clock->reset_notifiers);
271     return clock;
272 }
273
274 void qemu_clock_enable(QEMUClock *clock, int enabled)
275 {
276     bool old = clock->enabled;
277     clock->enabled = enabled;
278     if (enabled && !old) {
279         qemu_rearm_alarm_timer(alarm_timer);
280     }
281 }
282
283 int64_t qemu_clock_has_timers(QEMUClock *clock)
284 {
285     return !!clock->active_timers;
286 }
287
288 int64_t qemu_clock_expired(QEMUClock *clock)
289 {
290     return (clock->active_timers &&
291             clock->active_timers->expire_time < qemu_get_clock_ns(clock));
292 }
293
294 int64_t qemu_clock_deadline(QEMUClock *clock)
295 {
296     /* To avoid problems with overflow limit this to 2^32.  */
297     int64_t delta = INT32_MAX;
298
299     if (clock->active_timers) {
300         delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
301     }
302     if (delta < 0) {
303         delta = 0;
304     }
305     return delta;
306 }
307
308 QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
309                           QEMUTimerCB *cb, void *opaque)
310 {
311     QEMUTimer *ts;
312
313     ts = g_malloc0(sizeof(QEMUTimer));
314     ts->clock = clock;
315     ts->cb = cb;
316     ts->opaque = opaque;
317     ts->scale = scale;
318     return ts;
319 }
320
321 void qemu_free_timer(QEMUTimer *ts)
322 {
323     g_free(ts);
324 }
325
326 /* stop a timer, but do not dealloc it */
327 void qemu_del_timer(QEMUTimer *ts)
328 {
329     QEMUTimer **pt, *t;
330
331     /* NOTE: this code must be signal safe because
332        qemu_timer_expired() can be called from a signal. */
333     pt = &ts->clock->active_timers;
334     for(;;) {
335         t = *pt;
336         if (!t)
337             break;
338         if (t == ts) {
339             *pt = t->next;
340             break;
341         }
342         pt = &t->next;
343     }
344 }
345
346 /* modify the current timer so that it will be fired when current_time
347    >= expire_time. The corresponding callback will be called. */
348 void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
349 {
350     QEMUTimer **pt, *t;
351
352     qemu_del_timer(ts);
353
354     /* add the timer in the sorted list */
355     /* NOTE: this code must be signal safe because
356        qemu_timer_expired() can be called from a signal. */
357     pt = &ts->clock->active_timers;
358     for(;;) {
359         t = *pt;
360         if (!qemu_timer_expired_ns(t, expire_time)) {
361             break;
362         }
363         pt = &t->next;
364     }
365     ts->expire_time = expire_time;
366     ts->next = *pt;
367     *pt = ts;
368
369     /* Rearm if necessary  */
370     if (pt == &ts->clock->active_timers) {
371         if (!alarm_timer->pending) {
372             qemu_rearm_alarm_timer(alarm_timer);
373         }
374         /* Interrupt execution to force deadline recalculation.  */
375         qemu_clock_warp(ts->clock);
376         if (use_icount) {
377             qemu_notify_event();
378         }
379     }
380 }
381
382 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
383 {
384     qemu_mod_timer_ns(ts, expire_time * ts->scale);
385 }
386
387 int qemu_timer_pending(QEMUTimer *ts)
388 {
389     QEMUTimer *t;
390     for (t = ts->clock->active_timers; t != NULL; t = t->next) {
391         if (t == ts)
392             return 1;
393     }
394     return 0;
395 }
396
397 int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
398 {
399     return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
400 }
401
402 static void qemu_run_timers(QEMUClock *clock)
403 {
404     QEMUTimer **ptimer_head, *ts;
405     int64_t current_time;
406    
407     if (!clock->enabled)
408         return;
409
410     current_time = qemu_get_clock_ns(clock);
411     ptimer_head = &clock->active_timers;
412     for(;;) {
413         ts = *ptimer_head;
414         if (!qemu_timer_expired_ns(ts, current_time)) {
415             break;
416         }
417         /* remove timer from the list before calling the callback */
418         *ptimer_head = ts->next;
419         ts->next = NULL;
420
421         /* run the callback (the timer list can be modified) */
422         ts->cb(ts->opaque);
423     }
424 }
425
426 int64_t qemu_get_clock_ns(QEMUClock *clock)
427 {
428     int64_t now, last;
429
430     switch(clock->type) {
431     case QEMU_CLOCK_REALTIME:
432         return get_clock();
433     default:
434     case QEMU_CLOCK_VIRTUAL:
435         if (use_icount) {
436             return cpu_get_icount();
437         } else {
438             return cpu_get_clock();
439         }
440     case QEMU_CLOCK_HOST:
441         now = get_clock_realtime();
442         last = clock->last;
443         clock->last = now;
444         if (now < last) {
445             notifier_list_notify(&clock->reset_notifiers, &now);
446         }
447         return now;
448     }
449 }
450
451 void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
452 {
453     notifier_list_add(&clock->reset_notifiers, notifier);
454 }
455
456 void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
457 {
458     notifier_list_remove(&clock->reset_notifiers, notifier);
459 }
460
461 void init_clocks(void)
462 {
463     rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
464     vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
465     host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
466 }
467
468 uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
469 {
470     return qemu_timer_pending(ts) ? ts->expire_time : -1;
471 }
472
473 void qemu_run_all_timers(void)
474 {
475     alarm_timer->pending = 0;
476
477     /* rearm timer, if not periodic */
478     if (alarm_timer->expired) {
479         alarm_timer->expired = 0;
480         qemu_rearm_alarm_timer(alarm_timer);
481     }
482
483     /* vm time timers */
484     qemu_run_timers(vm_clock);
485     qemu_run_timers(rt_clock);
486     qemu_run_timers(host_clock);
487 }
488
489 #ifdef _WIN32
490 static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
491 #else
492 static void host_alarm_handler(int host_signum)
493 #endif
494 {
495     struct qemu_alarm_timer *t = alarm_timer;
496     if (!t)
497         return;
498
499 #if 0
500 #define DISP_FREQ 1000
501     {
502         static int64_t delta_min = INT64_MAX;
503         static int64_t delta_max, delta_cum, last_clock, delta, ti;
504         static int count;
505         ti = qemu_get_clock_ns(vm_clock);
506         if (last_clock != 0) {
507             delta = ti - last_clock;
508             if (delta < delta_min)
509                 delta_min = delta;
510             if (delta > delta_max)
511                 delta_max = delta;
512             delta_cum += delta;
513             if (++count == DISP_FREQ) {
514                 printf("timer: min=%" PRId64 " us max=%" PRId64 " us avg=%" PRId64 " us avg_freq=%0.3f Hz\n",
515                        muldiv64(delta_min, 1000000, get_ticks_per_sec()),
516                        muldiv64(delta_max, 1000000, get_ticks_per_sec()),
517                        muldiv64(delta_cum, 1000000 / DISP_FREQ, get_ticks_per_sec()),
518                        (double)get_ticks_per_sec() / ((double)delta_cum / DISP_FREQ));
519                 count = 0;
520                 delta_min = INT64_MAX;
521                 delta_max = 0;
522                 delta_cum = 0;
523             }
524         }
525         last_clock = ti;
526     }
527 #endif
528     if (alarm_has_dynticks(t) ||
529         qemu_next_alarm_deadline () <= 0) {
530         t->expired = alarm_has_dynticks(t);
531         t->pending = 1;
532         qemu_notify_event();
533     }
534 }
535
536 #if defined(__linux__)
537
538 #include "compatfd.h"
539
540 static int dynticks_start_timer(struct qemu_alarm_timer *t)
541 {
542     struct sigevent ev;
543     timer_t host_timer;
544     struct sigaction act;
545
546     sigfillset(&act.sa_mask);
547     act.sa_flags = 0;
548     act.sa_handler = host_alarm_handler;
549
550     sigaction(SIGALRM, &act, NULL);
551
552     /* 
553      * Initialize ev struct to 0 to avoid valgrind complaining
554      * about uninitialized data in timer_create call
555      */
556     memset(&ev, 0, sizeof(ev));
557     ev.sigev_value.sival_int = 0;
558     ev.sigev_notify = SIGEV_SIGNAL;
559 #ifdef SIGEV_THREAD_ID
560     if (qemu_signalfd_available()) {
561         ev.sigev_notify = SIGEV_THREAD_ID;
562         ev._sigev_un._tid = qemu_get_thread_id();
563     }
564 #endif /* SIGEV_THREAD_ID */
565     ev.sigev_signo = SIGALRM;
566
567     if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
568         perror("timer_create");
569
570         /* disable dynticks */
571         fprintf(stderr, "Dynamic Ticks disabled\n");
572
573         return -1;
574     }
575
576     t->timer = host_timer;
577
578     return 0;
579 }
580
581 static void dynticks_stop_timer(struct qemu_alarm_timer *t)
582 {
583     timer_t host_timer = t->timer;
584
585     timer_delete(host_timer);
586 }
587
588 static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
589                                  int64_t nearest_delta_ns)
590 {
591     timer_t host_timer = t->timer;
592     struct itimerspec timeout;
593     int64_t current_ns;
594
595     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
596         nearest_delta_ns = MIN_TIMER_REARM_NS;
597
598     /* check whether a timer is already running */
599     if (timer_gettime(host_timer, &timeout)) {
600         perror("gettime");
601         fprintf(stderr, "Internal timer error: aborting\n");
602         exit(1);
603     }
604     current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
605     if (current_ns && current_ns <= nearest_delta_ns)
606         return;
607
608     timeout.it_interval.tv_sec = 0;
609     timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
610     timeout.it_value.tv_sec =  nearest_delta_ns / 1000000000;
611     timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
612     if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
613         perror("settime");
614         fprintf(stderr, "Internal timer error: aborting\n");
615         exit(1);
616     }
617 }
618
619 #endif /* defined(__linux__) */
620
621 #if !defined(_WIN32)
622
623 static int unix_start_timer(struct qemu_alarm_timer *t)
624 {
625     struct sigaction act;
626
627     /* timer signal */
628     sigfillset(&act.sa_mask);
629     act.sa_flags = 0;
630     act.sa_handler = host_alarm_handler;
631
632     sigaction(SIGALRM, &act, NULL);
633     return 0;
634 }
635
636 static void unix_rearm_timer(struct qemu_alarm_timer *t,
637                              int64_t nearest_delta_ns)
638 {
639     struct itimerval itv;
640     int err;
641
642     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
643         nearest_delta_ns = MIN_TIMER_REARM_NS;
644
645     itv.it_interval.tv_sec = 0;
646     itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
647     itv.it_value.tv_sec =  nearest_delta_ns / 1000000000;
648     itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
649     err = setitimer(ITIMER_REAL, &itv, NULL);
650     if (err) {
651         perror("setitimer");
652         fprintf(stderr, "Internal timer error: aborting\n");
653         exit(1);
654     }
655 }
656
657 static void unix_stop_timer(struct qemu_alarm_timer *t)
658 {
659     struct itimerval itv;
660
661     memset(&itv, 0, sizeof(itv));
662     setitimer(ITIMER_REAL, &itv, NULL);
663 }
664
665 #endif /* !defined(_WIN32) */
666
667
668 #ifdef _WIN32
669
670 static MMRESULT mm_timer;
671 static unsigned mm_period;
672
673 static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
674                                       DWORD_PTR dwUser, DWORD_PTR dw1,
675                                       DWORD_PTR dw2)
676 {
677     struct qemu_alarm_timer *t = alarm_timer;
678     if (!t) {
679         return;
680     }
681     if (alarm_has_dynticks(t) || qemu_next_alarm_deadline() <= 0) {
682         t->expired = alarm_has_dynticks(t);
683         t->pending = 1;
684         qemu_notify_event();
685     }
686 }
687
688 static int mm_start_timer(struct qemu_alarm_timer *t)
689 {
690     TIMECAPS tc;
691     UINT flags;
692
693     memset(&tc, 0, sizeof(tc));
694     timeGetDevCaps(&tc, sizeof(tc));
695
696     mm_period = tc.wPeriodMin;
697     timeBeginPeriod(mm_period);
698
699     flags = TIME_CALLBACK_FUNCTION;
700     if (alarm_has_dynticks(t)) {
701         flags |= TIME_ONESHOT;
702     } else {
703         flags |= TIME_PERIODIC;
704     }
705
706     mm_timer = timeSetEvent(1,                  /* interval (ms) */
707                             mm_period,          /* resolution */
708                             mm_alarm_handler,   /* function */
709                             (DWORD_PTR)t,       /* parameter */
710                             flags);
711
712     if (!mm_timer) {
713         fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
714                 GetLastError());
715         timeEndPeriod(mm_period);
716         return -1;
717     }
718
719     return 0;
720 }
721
722 static void mm_stop_timer(struct qemu_alarm_timer *t)
723 {
724     timeKillEvent(mm_timer);
725     timeEndPeriod(mm_period);
726 }
727
728 static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
729 {
730     int nearest_delta_ms = (delta + 999999) / 1000000;
731     if (nearest_delta_ms < 1) {
732         nearest_delta_ms = 1;
733     }
734
735     timeKillEvent(mm_timer);
736     mm_timer = timeSetEvent(nearest_delta_ms,
737                             mm_period,
738                             mm_alarm_handler,
739                             (DWORD_PTR)t,
740                             TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
741
742     if (!mm_timer) {
743         fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n",
744                 GetLastError());
745
746         timeEndPeriod(mm_period);
747         exit(1);
748     }
749 }
750
751 static int win32_start_timer(struct qemu_alarm_timer *t)
752 {
753     HANDLE hTimer;
754     BOOLEAN success;
755
756     /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
757        is zero) that has already expired, the timer is not updated.  Since
758        creating a new timer is relatively expensive, set a bogus one-hour
759        interval in the dynticks case.  */
760     success = CreateTimerQueueTimer(&hTimer,
761                           NULL,
762                           host_alarm_handler,
763                           t,
764                           1,
765                           alarm_has_dynticks(t) ? 3600000 : 1,
766                           WT_EXECUTEINTIMERTHREAD);
767
768     if (!success) {
769         fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
770                 GetLastError());
771         return -1;
772     }
773
774     t->timer = hTimer;
775     return 0;
776 }
777
778 static void win32_stop_timer(struct qemu_alarm_timer *t)
779 {
780     HANDLE hTimer = t->timer;
781
782     if (hTimer) {
783         DeleteTimerQueueTimer(NULL, hTimer, NULL);
784     }
785 }
786
787 static void win32_rearm_timer(struct qemu_alarm_timer *t,
788                               int64_t nearest_delta_ns)
789 {
790     HANDLE hTimer = t->timer;
791     int nearest_delta_ms;
792     BOOLEAN success;
793
794     nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000;
795     if (nearest_delta_ms < 1) {
796         nearest_delta_ms = 1;
797     }
798     success = ChangeTimerQueueTimer(NULL,
799                                     hTimer,
800                                     nearest_delta_ms,
801                                     3600000);
802
803     if (!success) {
804         fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
805                 GetLastError());
806         exit(-1);
807     }
808
809 }
810
811 #endif /* _WIN32 */
812
813 static void quit_timers(void)
814 {
815     struct qemu_alarm_timer *t = alarm_timer;
816     alarm_timer = NULL;
817     t->stop(t);
818 }
819
820 int init_timer_alarm(void)
821 {
822     struct qemu_alarm_timer *t = NULL;
823     int i, err = -1;
824
825     for (i = 0; alarm_timers[i].name; i++) {
826         t = &alarm_timers[i];
827
828         err = t->start(t);
829         if (!err)
830             break;
831     }
832
833     if (err) {
834         err = -ENOENT;
835         goto fail;
836     }
837
838     /* first event is at time 0 */
839     atexit(quit_timers);
840     t->pending = 1;
841     alarm_timer = t;
842
843     return 0;
844
845 fail:
846     return err;
847 }
848
849 int qemu_calculate_timeout(void)
850 {
851     return 1000;
852 }
853
This page took 0.071427 seconds and 4 git commands to generate.