xref: /qemu/util/qemu-timer.c (revision 02a03a9f12ec2fe68c9fed84fa8607a5326e2b65)
1db1a4972SPaolo Bonzini /*
2db1a4972SPaolo Bonzini  * QEMU System Emulator
3db1a4972SPaolo Bonzini  *
4db1a4972SPaolo Bonzini  * Copyright (c) 2003-2008 Fabrice Bellard
5db1a4972SPaolo Bonzini  *
6db1a4972SPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
7db1a4972SPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
8db1a4972SPaolo Bonzini  * in the Software without restriction, including without limitation the rights
9db1a4972SPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10db1a4972SPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
11db1a4972SPaolo Bonzini  * furnished to do so, subject to the following conditions:
12db1a4972SPaolo Bonzini  *
13db1a4972SPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
14db1a4972SPaolo Bonzini  * all copies or substantial portions of the Software.
15db1a4972SPaolo Bonzini  *
16db1a4972SPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17db1a4972SPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18db1a4972SPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19db1a4972SPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20db1a4972SPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21db1a4972SPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22db1a4972SPaolo Bonzini  * THE SOFTWARE.
23db1a4972SPaolo Bonzini  */
24db1a4972SPaolo Bonzini 
259c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
2683c9089eSPaolo Bonzini #include "monitor/monitor.h"
2728ecbaeeSPaolo Bonzini #include "ui/console.h"
28db1a4972SPaolo Bonzini 
29db1a4972SPaolo Bonzini #include "hw/hw.h"
30db1a4972SPaolo Bonzini 
311de7afc9SPaolo Bonzini #include "qemu/timer.h"
3230ea8339SAnthony Liguori #ifdef CONFIG_POSIX
3330ea8339SAnthony Liguori #include <pthread.h>
3430ea8339SAnthony Liguori #endif
35bff9f8bfSStefan Weil 
36db1a4972SPaolo Bonzini #ifdef _WIN32
37db1a4972SPaolo Bonzini #include <mmsystem.h>
38db1a4972SPaolo Bonzini #endif
39db1a4972SPaolo Bonzini 
40db1a4972SPaolo Bonzini /***********************************************************/
41db1a4972SPaolo Bonzini /* timers */
42db1a4972SPaolo Bonzini 
43db1a4972SPaolo Bonzini struct QEMUClock {
44688eb389SPaolo Bonzini     QEMUTimer *active_timers;
45691a0c9cSJan Kiszka 
46691a0c9cSJan Kiszka     NotifierList reset_notifiers;
47691a0c9cSJan Kiszka     int64_t last;
489a14b298SStefan Weil 
499a14b298SStefan Weil     int type;
509a14b298SStefan Weil     bool enabled;
51db1a4972SPaolo Bonzini };
52db1a4972SPaolo Bonzini 
53db1a4972SPaolo Bonzini struct QEMUTimer {
544a998740SPaolo Bonzini     int64_t expire_time;	/* in nanoseconds */
559a14b298SStefan Weil     QEMUClock *clock;
56db1a4972SPaolo Bonzini     QEMUTimerCB *cb;
57db1a4972SPaolo Bonzini     void *opaque;
589a14b298SStefan Weil     QEMUTimer *next;
599a14b298SStefan Weil     int scale;
60db1a4972SPaolo Bonzini };
61db1a4972SPaolo Bonzini 
62db1a4972SPaolo Bonzini struct qemu_alarm_timer {
63db1a4972SPaolo Bonzini     char const *name;
64db1a4972SPaolo Bonzini     int (*start)(struct qemu_alarm_timer *t);
65db1a4972SPaolo Bonzini     void (*stop)(struct qemu_alarm_timer *t);
66f3fc6e2eSPaolo Bonzini     void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
67cd0544eeSStefan Weil #if defined(__linux__)
68cd0544eeSStefan Weil     timer_t timer;
699a14b298SStefan Weil     int fd;
70cd0544eeSStefan Weil #elif defined(_WIN32)
71cd0544eeSStefan Weil     HANDLE timer;
72cd0544eeSStefan Weil #endif
735e1ec7b2SStefan Weil     bool expired;
745e1ec7b2SStefan Weil     bool pending;
75db1a4972SPaolo Bonzini };
76db1a4972SPaolo Bonzini 
77db1a4972SPaolo Bonzini static struct qemu_alarm_timer *alarm_timer;
78db1a4972SPaolo Bonzini 
79e93379b0SAlex Bligh static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
8045c7b37fSStefan Weil {
8145c7b37fSStefan Weil     return timer_head && (timer_head->expire_time <= current_time);
8245c7b37fSStefan Weil }
8345c7b37fSStefan Weil 
84f3fc6e2eSPaolo Bonzini static int64_t qemu_next_alarm_deadline(void)
85f3fc6e2eSPaolo Bonzini {
864ffd16fcSStefano Stabellini     int64_t delta = INT64_MAX;
87f3fc6e2eSPaolo Bonzini     int64_t rtdelta;
88f3fc6e2eSPaolo Bonzini 
894ffd16fcSStefano Stabellini     if (!use_icount && vm_clock->enabled && vm_clock->active_timers) {
90f3fc6e2eSPaolo Bonzini         delta = vm_clock->active_timers->expire_time -
91f3fc6e2eSPaolo Bonzini                      qemu_get_clock_ns(vm_clock);
92f3fc6e2eSPaolo Bonzini     }
934ffd16fcSStefano Stabellini     if (host_clock->enabled && host_clock->active_timers) {
94f3fc6e2eSPaolo Bonzini         int64_t hdelta = host_clock->active_timers->expire_time -
95f3fc6e2eSPaolo Bonzini                  qemu_get_clock_ns(host_clock);
96f3fc6e2eSPaolo Bonzini         if (hdelta < delta) {
97f3fc6e2eSPaolo Bonzini             delta = hdelta;
98f3fc6e2eSPaolo Bonzini         }
99f3fc6e2eSPaolo Bonzini     }
1004ffd16fcSStefano Stabellini     if (rt_clock->enabled && rt_clock->active_timers) {
101f3fc6e2eSPaolo Bonzini         rtdelta = (rt_clock->active_timers->expire_time -
102f3fc6e2eSPaolo Bonzini                  qemu_get_clock_ns(rt_clock));
103f3fc6e2eSPaolo Bonzini         if (rtdelta < delta) {
104f3fc6e2eSPaolo Bonzini             delta = rtdelta;
105f3fc6e2eSPaolo Bonzini         }
106f3fc6e2eSPaolo Bonzini     }
107f3fc6e2eSPaolo Bonzini 
108f3fc6e2eSPaolo Bonzini     return delta;
109f3fc6e2eSPaolo Bonzini }
110f3fc6e2eSPaolo Bonzini 
111db1a4972SPaolo Bonzini static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
112db1a4972SPaolo Bonzini {
1138227421eSStefano Stabellini     int64_t nearest_delta_ns = qemu_next_alarm_deadline();
1148227421eSStefano Stabellini     if (nearest_delta_ns < INT64_MAX) {
115f3fc6e2eSPaolo Bonzini         t->rearm(t, nearest_delta_ns);
116db1a4972SPaolo Bonzini     }
1178227421eSStefano Stabellini }
118db1a4972SPaolo Bonzini 
1199c13246aSPaolo Bonzini /* TODO: MIN_TIMER_REARM_NS should be optimized */
1209c13246aSPaolo Bonzini #define MIN_TIMER_REARM_NS 250000
121db1a4972SPaolo Bonzini 
122db1a4972SPaolo Bonzini #ifdef _WIN32
123db1a4972SPaolo Bonzini 
1242f9cba0cSStefan Weil static int mm_start_timer(struct qemu_alarm_timer *t);
1252f9cba0cSStefan Weil static void mm_stop_timer(struct qemu_alarm_timer *t);
126f3fc6e2eSPaolo Bonzini static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
1272f9cba0cSStefan Weil 
128db1a4972SPaolo Bonzini static int win32_start_timer(struct qemu_alarm_timer *t);
129db1a4972SPaolo Bonzini static void win32_stop_timer(struct qemu_alarm_timer *t);
130f3fc6e2eSPaolo Bonzini static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
131db1a4972SPaolo Bonzini 
132db1a4972SPaolo Bonzini #else
133db1a4972SPaolo Bonzini 
134db1a4972SPaolo Bonzini static int unix_start_timer(struct qemu_alarm_timer *t);
135db1a4972SPaolo Bonzini static void unix_stop_timer(struct qemu_alarm_timer *t);
136f3fc6e2eSPaolo Bonzini static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
137db1a4972SPaolo Bonzini 
138db1a4972SPaolo Bonzini #ifdef __linux__
139db1a4972SPaolo Bonzini 
140db1a4972SPaolo Bonzini static int dynticks_start_timer(struct qemu_alarm_timer *t);
141db1a4972SPaolo Bonzini static void dynticks_stop_timer(struct qemu_alarm_timer *t);
142f3fc6e2eSPaolo Bonzini static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
143db1a4972SPaolo Bonzini 
144db1a4972SPaolo Bonzini #endif /* __linux__ */
145db1a4972SPaolo Bonzini 
146db1a4972SPaolo Bonzini #endif /* _WIN32 */
147db1a4972SPaolo Bonzini 
148db1a4972SPaolo Bonzini static struct qemu_alarm_timer alarm_timers[] = {
149db1a4972SPaolo Bonzini #ifndef _WIN32
150db1a4972SPaolo Bonzini #ifdef __linux__
151db1a4972SPaolo Bonzini     {"dynticks", dynticks_start_timer,
152cd0544eeSStefan Weil      dynticks_stop_timer, dynticks_rearm_timer},
153db1a4972SPaolo Bonzini #endif
15484682834SPaolo Bonzini     {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer},
155db1a4972SPaolo Bonzini #else
156cca5de73SPaolo Bonzini     {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer},
157cd0544eeSStefan Weil     {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
158db1a4972SPaolo Bonzini #endif
159db1a4972SPaolo Bonzini     {NULL, }
160db1a4972SPaolo Bonzini };
161db1a4972SPaolo Bonzini 
162db1a4972SPaolo Bonzini static void show_available_alarms(void)
163db1a4972SPaolo Bonzini {
164db1a4972SPaolo Bonzini     int i;
165db1a4972SPaolo Bonzini 
166db1a4972SPaolo Bonzini     printf("Available alarm timers, in order of precedence:\n");
167db1a4972SPaolo Bonzini     for (i = 0; alarm_timers[i].name; i++)
168db1a4972SPaolo Bonzini         printf("%s\n", alarm_timers[i].name);
169db1a4972SPaolo Bonzini }
170db1a4972SPaolo Bonzini 
171db1a4972SPaolo Bonzini void configure_alarms(char const *opt)
172db1a4972SPaolo Bonzini {
173db1a4972SPaolo Bonzini     int i;
174db1a4972SPaolo Bonzini     int cur = 0;
175db1a4972SPaolo Bonzini     int count = ARRAY_SIZE(alarm_timers) - 1;
176db1a4972SPaolo Bonzini     char *arg;
177db1a4972SPaolo Bonzini     char *name;
178db1a4972SPaolo Bonzini     struct qemu_alarm_timer tmp;
179db1a4972SPaolo Bonzini 
180c8057f95SPeter Maydell     if (is_help_option(opt)) {
181db1a4972SPaolo Bonzini         show_available_alarms();
182db1a4972SPaolo Bonzini         exit(0);
183db1a4972SPaolo Bonzini     }
184db1a4972SPaolo Bonzini 
1857267c094SAnthony Liguori     arg = g_strdup(opt);
186db1a4972SPaolo Bonzini 
187db1a4972SPaolo Bonzini     /* Reorder the array */
188db1a4972SPaolo Bonzini     name = strtok(arg, ",");
189db1a4972SPaolo Bonzini     while (name) {
190db1a4972SPaolo Bonzini         for (i = 0; i < count && alarm_timers[i].name; i++) {
191db1a4972SPaolo Bonzini             if (!strcmp(alarm_timers[i].name, name))
192db1a4972SPaolo Bonzini                 break;
193db1a4972SPaolo Bonzini         }
194db1a4972SPaolo Bonzini 
195db1a4972SPaolo Bonzini         if (i == count) {
196db1a4972SPaolo Bonzini             fprintf(stderr, "Unknown clock %s\n", name);
197db1a4972SPaolo Bonzini             goto next;
198db1a4972SPaolo Bonzini         }
199db1a4972SPaolo Bonzini 
200db1a4972SPaolo Bonzini         if (i < cur)
201db1a4972SPaolo Bonzini             /* Ignore */
202db1a4972SPaolo Bonzini             goto next;
203db1a4972SPaolo Bonzini 
204db1a4972SPaolo Bonzini 	/* Swap */
205db1a4972SPaolo Bonzini         tmp = alarm_timers[i];
206db1a4972SPaolo Bonzini         alarm_timers[i] = alarm_timers[cur];
207db1a4972SPaolo Bonzini         alarm_timers[cur] = tmp;
208db1a4972SPaolo Bonzini 
209db1a4972SPaolo Bonzini         cur++;
210db1a4972SPaolo Bonzini next:
211db1a4972SPaolo Bonzini         name = strtok(NULL, ",");
212db1a4972SPaolo Bonzini     }
213db1a4972SPaolo Bonzini 
2147267c094SAnthony Liguori     g_free(arg);
215db1a4972SPaolo Bonzini 
216db1a4972SPaolo Bonzini     if (cur) {
217db1a4972SPaolo Bonzini         /* Disable remaining timers */
218db1a4972SPaolo Bonzini         for (i = cur; i < count; i++)
219db1a4972SPaolo Bonzini             alarm_timers[i].name = NULL;
220db1a4972SPaolo Bonzini     } else {
221db1a4972SPaolo Bonzini         show_available_alarms();
222db1a4972SPaolo Bonzini         exit(1);
223db1a4972SPaolo Bonzini     }
224db1a4972SPaolo Bonzini }
225db1a4972SPaolo Bonzini 
226db1a4972SPaolo Bonzini QEMUClock *rt_clock;
227db1a4972SPaolo Bonzini QEMUClock *vm_clock;
228db1a4972SPaolo Bonzini QEMUClock *host_clock;
229db1a4972SPaolo Bonzini 
23058ac56b9SAlex Bligh static QEMUClock *qemu_clock_new(int type)
231db1a4972SPaolo Bonzini {
232db1a4972SPaolo Bonzini     QEMUClock *clock;
233691a0c9cSJan Kiszka 
2347267c094SAnthony Liguori     clock = g_malloc0(sizeof(QEMUClock));
235db1a4972SPaolo Bonzini     clock->type = type;
2365e1ec7b2SStefan Weil     clock->enabled = true;
2372ff68d07SPaolo Bonzini     clock->last = INT64_MIN;
238691a0c9cSJan Kiszka     notifier_list_init(&clock->reset_notifiers);
239db1a4972SPaolo Bonzini     return clock;
240db1a4972SPaolo Bonzini }
241db1a4972SPaolo Bonzini 
2425e1ec7b2SStefan Weil void qemu_clock_enable(QEMUClock *clock, bool enabled)
243db1a4972SPaolo Bonzini {
244fbdc14ebSPaolo Bonzini     bool old = clock->enabled;
245db1a4972SPaolo Bonzini     clock->enabled = enabled;
246fbdc14ebSPaolo Bonzini     if (enabled && !old) {
247fbdc14ebSPaolo Bonzini         qemu_rearm_alarm_timer(alarm_timer);
248fbdc14ebSPaolo Bonzini     }
249db1a4972SPaolo Bonzini }
250db1a4972SPaolo Bonzini 
251dc2dfcf0SPaolo Bonzini int64_t qemu_clock_has_timers(QEMUClock *clock)
252dc2dfcf0SPaolo Bonzini {
253dc2dfcf0SPaolo Bonzini     return !!clock->active_timers;
254dc2dfcf0SPaolo Bonzini }
255dc2dfcf0SPaolo Bonzini 
256dc2dfcf0SPaolo Bonzini int64_t qemu_clock_expired(QEMUClock *clock)
257dc2dfcf0SPaolo Bonzini {
258dc2dfcf0SPaolo Bonzini     return (clock->active_timers &&
259dc2dfcf0SPaolo Bonzini             clock->active_timers->expire_time < qemu_get_clock_ns(clock));
260dc2dfcf0SPaolo Bonzini }
261dc2dfcf0SPaolo Bonzini 
262dc2dfcf0SPaolo Bonzini int64_t qemu_clock_deadline(QEMUClock *clock)
263dc2dfcf0SPaolo Bonzini {
264dc2dfcf0SPaolo Bonzini     /* To avoid problems with overflow limit this to 2^32.  */
265dc2dfcf0SPaolo Bonzini     int64_t delta = INT32_MAX;
266dc2dfcf0SPaolo Bonzini 
267dc2dfcf0SPaolo Bonzini     if (clock->active_timers) {
268dc2dfcf0SPaolo Bonzini         delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
269dc2dfcf0SPaolo Bonzini     }
270dc2dfcf0SPaolo Bonzini     if (delta < 0) {
271dc2dfcf0SPaolo Bonzini         delta = 0;
272dc2dfcf0SPaolo Bonzini     }
273dc2dfcf0SPaolo Bonzini     return delta;
274dc2dfcf0SPaolo Bonzini }
275dc2dfcf0SPaolo Bonzini 
276*02a03a9fSAlex Bligh /*
277*02a03a9fSAlex Bligh  * As above, but return -1 for no deadline, and do not cap to 2^32
278*02a03a9fSAlex Bligh  * as we know the result is always positive.
279*02a03a9fSAlex Bligh  */
280*02a03a9fSAlex Bligh 
281*02a03a9fSAlex Bligh int64_t qemu_clock_deadline_ns(QEMUClock *clock)
282*02a03a9fSAlex Bligh {
283*02a03a9fSAlex Bligh     int64_t delta;
284*02a03a9fSAlex Bligh 
285*02a03a9fSAlex Bligh     if (!clock->enabled || !clock->active_timers) {
286*02a03a9fSAlex Bligh         return -1;
287*02a03a9fSAlex Bligh     }
288*02a03a9fSAlex Bligh 
289*02a03a9fSAlex Bligh     delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
290*02a03a9fSAlex Bligh 
291*02a03a9fSAlex Bligh     if (delta <= 0) {
292*02a03a9fSAlex Bligh         return 0;
293*02a03a9fSAlex Bligh     }
294*02a03a9fSAlex Bligh 
295*02a03a9fSAlex Bligh     return delta;
296*02a03a9fSAlex Bligh }
297*02a03a9fSAlex Bligh 
298*02a03a9fSAlex Bligh /* Transition function to convert a nanosecond timeout to ms
299*02a03a9fSAlex Bligh  * This is used where a system does not support ppoll
300*02a03a9fSAlex Bligh  */
301*02a03a9fSAlex Bligh int qemu_timeout_ns_to_ms(int64_t ns)
302*02a03a9fSAlex Bligh {
303*02a03a9fSAlex Bligh     int64_t ms;
304*02a03a9fSAlex Bligh     if (ns < 0) {
305*02a03a9fSAlex Bligh         return -1;
306*02a03a9fSAlex Bligh     }
307*02a03a9fSAlex Bligh 
308*02a03a9fSAlex Bligh     if (!ns) {
309*02a03a9fSAlex Bligh         return 0;
310*02a03a9fSAlex Bligh     }
311*02a03a9fSAlex Bligh 
312*02a03a9fSAlex Bligh     /* Always round up, because it's better to wait too long than to wait too
313*02a03a9fSAlex Bligh      * little and effectively busy-wait
314*02a03a9fSAlex Bligh      */
315*02a03a9fSAlex Bligh     ms = (ns + SCALE_MS - 1) / SCALE_MS;
316*02a03a9fSAlex Bligh 
317*02a03a9fSAlex Bligh     /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
318*02a03a9fSAlex Bligh     if (ms > (int64_t) INT32_MAX) {
319*02a03a9fSAlex Bligh         ms = INT32_MAX;
320*02a03a9fSAlex Bligh     }
321*02a03a9fSAlex Bligh 
322*02a03a9fSAlex Bligh     return (int) ms;
323*02a03a9fSAlex Bligh }
324*02a03a9fSAlex Bligh 
325*02a03a9fSAlex Bligh 
3264a998740SPaolo Bonzini QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
3274a998740SPaolo Bonzini                           QEMUTimerCB *cb, void *opaque)
328db1a4972SPaolo Bonzini {
329db1a4972SPaolo Bonzini     QEMUTimer *ts;
330db1a4972SPaolo Bonzini 
3317267c094SAnthony Liguori     ts = g_malloc0(sizeof(QEMUTimer));
332db1a4972SPaolo Bonzini     ts->clock = clock;
333db1a4972SPaolo Bonzini     ts->cb = cb;
334db1a4972SPaolo Bonzini     ts->opaque = opaque;
3354a998740SPaolo Bonzini     ts->scale = scale;
336db1a4972SPaolo Bonzini     return ts;
337db1a4972SPaolo Bonzini }
338db1a4972SPaolo Bonzini 
339db1a4972SPaolo Bonzini void qemu_free_timer(QEMUTimer *ts)
340db1a4972SPaolo Bonzini {
3417267c094SAnthony Liguori     g_free(ts);
342db1a4972SPaolo Bonzini }
343db1a4972SPaolo Bonzini 
344db1a4972SPaolo Bonzini /* stop a timer, but do not dealloc it */
345db1a4972SPaolo Bonzini void qemu_del_timer(QEMUTimer *ts)
346db1a4972SPaolo Bonzini {
347db1a4972SPaolo Bonzini     QEMUTimer **pt, *t;
348db1a4972SPaolo Bonzini 
349db1a4972SPaolo Bonzini     /* NOTE: this code must be signal safe because
350e93379b0SAlex Bligh        timer_expired() can be called from a signal. */
351688eb389SPaolo Bonzini     pt = &ts->clock->active_timers;
352db1a4972SPaolo Bonzini     for(;;) {
353db1a4972SPaolo Bonzini         t = *pt;
354db1a4972SPaolo Bonzini         if (!t)
355db1a4972SPaolo Bonzini             break;
356db1a4972SPaolo Bonzini         if (t == ts) {
357db1a4972SPaolo Bonzini             *pt = t->next;
358db1a4972SPaolo Bonzini             break;
359db1a4972SPaolo Bonzini         }
360db1a4972SPaolo Bonzini         pt = &t->next;
361db1a4972SPaolo Bonzini     }
362db1a4972SPaolo Bonzini }
363db1a4972SPaolo Bonzini 
364db1a4972SPaolo Bonzini /* modify the current timer so that it will be fired when current_time
365db1a4972SPaolo Bonzini    >= expire_time. The corresponding callback will be called. */
3662ff68d07SPaolo Bonzini void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
367db1a4972SPaolo Bonzini {
368db1a4972SPaolo Bonzini     QEMUTimer **pt, *t;
369db1a4972SPaolo Bonzini 
370db1a4972SPaolo Bonzini     qemu_del_timer(ts);
371db1a4972SPaolo Bonzini 
372db1a4972SPaolo Bonzini     /* add the timer in the sorted list */
373db1a4972SPaolo Bonzini     /* NOTE: this code must be signal safe because
374e93379b0SAlex Bligh        timer_expired() can be called from a signal. */
375688eb389SPaolo Bonzini     pt = &ts->clock->active_timers;
376db1a4972SPaolo Bonzini     for(;;) {
377db1a4972SPaolo Bonzini         t = *pt;
378e93379b0SAlex Bligh         if (!timer_expired_ns(t, expire_time)) {
379db1a4972SPaolo Bonzini             break;
38045c7b37fSStefan Weil         }
381db1a4972SPaolo Bonzini         pt = &t->next;
382db1a4972SPaolo Bonzini     }
383db1a4972SPaolo Bonzini     ts->expire_time = expire_time;
384db1a4972SPaolo Bonzini     ts->next = *pt;
385db1a4972SPaolo Bonzini     *pt = ts;
386db1a4972SPaolo Bonzini 
387db1a4972SPaolo Bonzini     /* Rearm if necessary  */
388688eb389SPaolo Bonzini     if (pt == &ts->clock->active_timers) {
389db1a4972SPaolo Bonzini         if (!alarm_timer->pending) {
390db1a4972SPaolo Bonzini             qemu_rearm_alarm_timer(alarm_timer);
391db1a4972SPaolo Bonzini         }
392db1a4972SPaolo Bonzini         /* Interrupt execution to force deadline recalculation.  */
393ab33fcdaSPaolo Bonzini         qemu_clock_warp(ts->clock);
394ab33fcdaSPaolo Bonzini         if (use_icount) {
395db1a4972SPaolo Bonzini             qemu_notify_event();
396db1a4972SPaolo Bonzini         }
397db1a4972SPaolo Bonzini     }
398ab33fcdaSPaolo Bonzini }
399db1a4972SPaolo Bonzini 
4004a998740SPaolo Bonzini void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
4014a998740SPaolo Bonzini {
4024a998740SPaolo Bonzini     qemu_mod_timer_ns(ts, expire_time * ts->scale);
4034a998740SPaolo Bonzini }
4044a998740SPaolo Bonzini 
405e93379b0SAlex Bligh bool timer_pending(QEMUTimer *ts)
406db1a4972SPaolo Bonzini {
407db1a4972SPaolo Bonzini     QEMUTimer *t;
408688eb389SPaolo Bonzini     for (t = ts->clock->active_timers; t != NULL; t = t->next) {
4095e1ec7b2SStefan Weil         if (t == ts) {
4105e1ec7b2SStefan Weil             return true;
411db1a4972SPaolo Bonzini         }
4125e1ec7b2SStefan Weil     }
4135e1ec7b2SStefan Weil     return false;
414db1a4972SPaolo Bonzini }
415db1a4972SPaolo Bonzini 
416e93379b0SAlex Bligh bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
417db1a4972SPaolo Bonzini {
418e93379b0SAlex Bligh     return timer_expired_ns(timer_head, current_time * timer_head->scale);
419db1a4972SPaolo Bonzini }
420db1a4972SPaolo Bonzini 
4218156be56SPaolo Bonzini void qemu_run_timers(QEMUClock *clock)
422db1a4972SPaolo Bonzini {
423144b97c2SPaolo Bonzini     QEMUTimer *ts;
424db1a4972SPaolo Bonzini     int64_t current_time;
425db1a4972SPaolo Bonzini 
426db1a4972SPaolo Bonzini     if (!clock->enabled)
427db1a4972SPaolo Bonzini         return;
428db1a4972SPaolo Bonzini 
4294a998740SPaolo Bonzini     current_time = qemu_get_clock_ns(clock);
430db1a4972SPaolo Bonzini     for(;;) {
431144b97c2SPaolo Bonzini         ts = clock->active_timers;
432e93379b0SAlex Bligh         if (!timer_expired_ns(ts, current_time)) {
433db1a4972SPaolo Bonzini             break;
43445c7b37fSStefan Weil         }
435db1a4972SPaolo Bonzini         /* remove timer from the list before calling the callback */
436144b97c2SPaolo Bonzini         clock->active_timers = ts->next;
437db1a4972SPaolo Bonzini         ts->next = NULL;
438db1a4972SPaolo Bonzini 
439db1a4972SPaolo Bonzini         /* run the callback (the timer list can be modified) */
440db1a4972SPaolo Bonzini         ts->cb(ts->opaque);
441db1a4972SPaolo Bonzini     }
442db1a4972SPaolo Bonzini }
443db1a4972SPaolo Bonzini 
444db1a4972SPaolo Bonzini int64_t qemu_get_clock_ns(QEMUClock *clock)
445db1a4972SPaolo Bonzini {
446691a0c9cSJan Kiszka     int64_t now, last;
447691a0c9cSJan Kiszka 
448db1a4972SPaolo Bonzini     switch(clock->type) {
449db1a4972SPaolo Bonzini     case QEMU_CLOCK_REALTIME:
450db1a4972SPaolo Bonzini         return get_clock();
451db1a4972SPaolo Bonzini     default:
452db1a4972SPaolo Bonzini     case QEMU_CLOCK_VIRTUAL:
453db1a4972SPaolo Bonzini         if (use_icount) {
454db1a4972SPaolo Bonzini             return cpu_get_icount();
455db1a4972SPaolo Bonzini         } else {
456db1a4972SPaolo Bonzini             return cpu_get_clock();
457db1a4972SPaolo Bonzini         }
458db1a4972SPaolo Bonzini     case QEMU_CLOCK_HOST:
459691a0c9cSJan Kiszka         now = get_clock_realtime();
460691a0c9cSJan Kiszka         last = clock->last;
461691a0c9cSJan Kiszka         clock->last = now;
462691a0c9cSJan Kiszka         if (now < last) {
463691a0c9cSJan Kiszka             notifier_list_notify(&clock->reset_notifiers, &now);
464db1a4972SPaolo Bonzini         }
465691a0c9cSJan Kiszka         return now;
466691a0c9cSJan Kiszka     }
467691a0c9cSJan Kiszka }
468691a0c9cSJan Kiszka 
469691a0c9cSJan Kiszka void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
470691a0c9cSJan Kiszka {
471691a0c9cSJan Kiszka     notifier_list_add(&clock->reset_notifiers, notifier);
472691a0c9cSJan Kiszka }
473691a0c9cSJan Kiszka 
474691a0c9cSJan Kiszka void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
475691a0c9cSJan Kiszka {
47631552529SPaolo Bonzini     notifier_remove(notifier);
477db1a4972SPaolo Bonzini }
478db1a4972SPaolo Bonzini 
479db1a4972SPaolo Bonzini void init_clocks(void)
480db1a4972SPaolo Bonzini {
481744ca8e3SPaolo Bonzini     if (!rt_clock) {
48258ac56b9SAlex Bligh         rt_clock = qemu_clock_new(QEMU_CLOCK_REALTIME);
48358ac56b9SAlex Bligh         vm_clock = qemu_clock_new(QEMU_CLOCK_VIRTUAL);
48458ac56b9SAlex Bligh         host_clock = qemu_clock_new(QEMU_CLOCK_HOST);
485db1a4972SPaolo Bonzini     }
486744ca8e3SPaolo Bonzini }
487db1a4972SPaolo Bonzini 
488e93379b0SAlex Bligh uint64_t timer_expire_time_ns(QEMUTimer *ts)
489db1a4972SPaolo Bonzini {
490e93379b0SAlex Bligh     return timer_pending(ts) ? ts->expire_time : -1;
491db1a4972SPaolo Bonzini }
492db1a4972SPaolo Bonzini 
493db1a4972SPaolo Bonzini void qemu_run_all_timers(void)
494db1a4972SPaolo Bonzini {
4955e1ec7b2SStefan Weil     alarm_timer->pending = false;
496ca5a2a4bSPaolo Bonzini 
497158fd3ceSPeter Portante     /* vm time timers */
498158fd3ceSPeter Portante     qemu_run_timers(vm_clock);
499158fd3ceSPeter Portante     qemu_run_timers(rt_clock);
500158fd3ceSPeter Portante     qemu_run_timers(host_clock);
501158fd3ceSPeter Portante 
502db1a4972SPaolo Bonzini     /* rearm timer, if not periodic */
503db1a4972SPaolo Bonzini     if (alarm_timer->expired) {
5045e1ec7b2SStefan Weil         alarm_timer->expired = false;
505db1a4972SPaolo Bonzini         qemu_rearm_alarm_timer(alarm_timer);
506db1a4972SPaolo Bonzini     }
507db1a4972SPaolo Bonzini }
508db1a4972SPaolo Bonzini 
509db1a4972SPaolo Bonzini #ifdef _WIN32
51068c23e55SPaolo Bonzini static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
511db1a4972SPaolo Bonzini #else
512db1a4972SPaolo Bonzini static void host_alarm_handler(int host_signum)
513db1a4972SPaolo Bonzini #endif
514db1a4972SPaolo Bonzini {
515db1a4972SPaolo Bonzini     struct qemu_alarm_timer *t = alarm_timer;
516db1a4972SPaolo Bonzini     if (!t)
517db1a4972SPaolo Bonzini 	return;
518db1a4972SPaolo Bonzini 
5198205199dSStefan Weil     t->expired = true;
5205e1ec7b2SStefan Weil     t->pending = true;
521db1a4972SPaolo Bonzini     qemu_notify_event();
522db1a4972SPaolo Bonzini }
523db1a4972SPaolo Bonzini 
5244c3d45ebSPaolo Bonzini #if defined(__linux__)
5254c3d45ebSPaolo Bonzini 
5261de7afc9SPaolo Bonzini #include "qemu/compatfd.h"
527d25f89c9SJan Kiszka 
528db1a4972SPaolo Bonzini static int dynticks_start_timer(struct qemu_alarm_timer *t)
529db1a4972SPaolo Bonzini {
530db1a4972SPaolo Bonzini     struct sigevent ev;
531db1a4972SPaolo Bonzini     timer_t host_timer;
532db1a4972SPaolo Bonzini     struct sigaction act;
533db1a4972SPaolo Bonzini 
534db1a4972SPaolo Bonzini     sigfillset(&act.sa_mask);
535db1a4972SPaolo Bonzini     act.sa_flags = 0;
536db1a4972SPaolo Bonzini     act.sa_handler = host_alarm_handler;
537db1a4972SPaolo Bonzini 
538db1a4972SPaolo Bonzini     sigaction(SIGALRM, &act, NULL);
539db1a4972SPaolo Bonzini 
540db1a4972SPaolo Bonzini     /*
541db1a4972SPaolo Bonzini      * Initialize ev struct to 0 to avoid valgrind complaining
542db1a4972SPaolo Bonzini      * about uninitialized data in timer_create call
543db1a4972SPaolo Bonzini      */
544db1a4972SPaolo Bonzini     memset(&ev, 0, sizeof(ev));
545db1a4972SPaolo Bonzini     ev.sigev_value.sival_int = 0;
546db1a4972SPaolo Bonzini     ev.sigev_notify = SIGEV_SIGNAL;
5471e9737daSRichard Henderson #ifdef CONFIG_SIGEV_THREAD_ID
548d25f89c9SJan Kiszka     if (qemu_signalfd_available()) {
549d25f89c9SJan Kiszka         ev.sigev_notify = SIGEV_THREAD_ID;
550d25f89c9SJan Kiszka         ev._sigev_un._tid = qemu_get_thread_id();
551d25f89c9SJan Kiszka     }
5521e9737daSRichard Henderson #endif /* CONFIG_SIGEV_THREAD_ID */
553db1a4972SPaolo Bonzini     ev.sigev_signo = SIGALRM;
554db1a4972SPaolo Bonzini 
555db1a4972SPaolo Bonzini     if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
556db1a4972SPaolo Bonzini         perror("timer_create");
557db1a4972SPaolo Bonzini         return -1;
558db1a4972SPaolo Bonzini     }
559db1a4972SPaolo Bonzini 
560cd0544eeSStefan Weil     t->timer = host_timer;
561db1a4972SPaolo Bonzini 
562db1a4972SPaolo Bonzini     return 0;
563db1a4972SPaolo Bonzini }
564db1a4972SPaolo Bonzini 
565db1a4972SPaolo Bonzini static void dynticks_stop_timer(struct qemu_alarm_timer *t)
566db1a4972SPaolo Bonzini {
567cd0544eeSStefan Weil     timer_t host_timer = t->timer;
568db1a4972SPaolo Bonzini 
569db1a4972SPaolo Bonzini     timer_delete(host_timer);
570db1a4972SPaolo Bonzini }
571db1a4972SPaolo Bonzini 
572f3fc6e2eSPaolo Bonzini static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
573f3fc6e2eSPaolo Bonzini                                  int64_t nearest_delta_ns)
574db1a4972SPaolo Bonzini {
575cd0544eeSStefan Weil     timer_t host_timer = t->timer;
576db1a4972SPaolo Bonzini     struct itimerspec timeout;
5779c13246aSPaolo Bonzini     int64_t current_ns;
578db1a4972SPaolo Bonzini 
5794c3d45ebSPaolo Bonzini     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
5804c3d45ebSPaolo Bonzini         nearest_delta_ns = MIN_TIMER_REARM_NS;
581db1a4972SPaolo Bonzini 
582db1a4972SPaolo Bonzini     /* check whether a timer is already running */
583db1a4972SPaolo Bonzini     if (timer_gettime(host_timer, &timeout)) {
584db1a4972SPaolo Bonzini         perror("gettime");
585db1a4972SPaolo Bonzini         fprintf(stderr, "Internal timer error: aborting\n");
586db1a4972SPaolo Bonzini         exit(1);
587db1a4972SPaolo Bonzini     }
5889c13246aSPaolo Bonzini     current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
5899c13246aSPaolo Bonzini     if (current_ns && current_ns <= nearest_delta_ns)
590db1a4972SPaolo Bonzini         return;
591db1a4972SPaolo Bonzini 
592db1a4972SPaolo Bonzini     timeout.it_interval.tv_sec = 0;
593db1a4972SPaolo Bonzini     timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
5949c13246aSPaolo Bonzini     timeout.it_value.tv_sec =  nearest_delta_ns / 1000000000;
5959c13246aSPaolo Bonzini     timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
596db1a4972SPaolo Bonzini     if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
597db1a4972SPaolo Bonzini         perror("settime");
598db1a4972SPaolo Bonzini         fprintf(stderr, "Internal timer error: aborting\n");
599db1a4972SPaolo Bonzini         exit(1);
600db1a4972SPaolo Bonzini     }
601db1a4972SPaolo Bonzini }
602db1a4972SPaolo Bonzini 
603db1a4972SPaolo Bonzini #endif /* defined(__linux__) */
604db1a4972SPaolo Bonzini 
605f26e5a54SStefan Weil #if !defined(_WIN32)
606f26e5a54SStefan Weil 
607db1a4972SPaolo Bonzini static int unix_start_timer(struct qemu_alarm_timer *t)
608db1a4972SPaolo Bonzini {
609db1a4972SPaolo Bonzini     struct sigaction act;
610db1a4972SPaolo Bonzini 
611db1a4972SPaolo Bonzini     /* timer signal */
612db1a4972SPaolo Bonzini     sigfillset(&act.sa_mask);
613db1a4972SPaolo Bonzini     act.sa_flags = 0;
614db1a4972SPaolo Bonzini     act.sa_handler = host_alarm_handler;
615db1a4972SPaolo Bonzini 
616db1a4972SPaolo Bonzini     sigaction(SIGALRM, &act, NULL);
61784682834SPaolo Bonzini     return 0;
61884682834SPaolo Bonzini }
61984682834SPaolo Bonzini 
620f3fc6e2eSPaolo Bonzini static void unix_rearm_timer(struct qemu_alarm_timer *t,
621f3fc6e2eSPaolo Bonzini                              int64_t nearest_delta_ns)
62284682834SPaolo Bonzini {
62384682834SPaolo Bonzini     struct itimerval itv;
62484682834SPaolo Bonzini     int err;
62584682834SPaolo Bonzini 
62684682834SPaolo Bonzini     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
62784682834SPaolo Bonzini         nearest_delta_ns = MIN_TIMER_REARM_NS;
628db1a4972SPaolo Bonzini 
629db1a4972SPaolo Bonzini     itv.it_interval.tv_sec = 0;
63084682834SPaolo Bonzini     itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
63184682834SPaolo Bonzini     itv.it_value.tv_sec =  nearest_delta_ns / 1000000000;
63284682834SPaolo Bonzini     itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
633db1a4972SPaolo Bonzini     err = setitimer(ITIMER_REAL, &itv, NULL);
63484682834SPaolo Bonzini     if (err) {
63584682834SPaolo Bonzini         perror("setitimer");
63684682834SPaolo Bonzini         fprintf(stderr, "Internal timer error: aborting\n");
63784682834SPaolo Bonzini         exit(1);
63884682834SPaolo Bonzini     }
639db1a4972SPaolo Bonzini }
640db1a4972SPaolo Bonzini 
641db1a4972SPaolo Bonzini static void unix_stop_timer(struct qemu_alarm_timer *t)
642db1a4972SPaolo Bonzini {
643db1a4972SPaolo Bonzini     struct itimerval itv;
644db1a4972SPaolo Bonzini 
645db1a4972SPaolo Bonzini     memset(&itv, 0, sizeof(itv));
646db1a4972SPaolo Bonzini     setitimer(ITIMER_REAL, &itv, NULL);
647db1a4972SPaolo Bonzini }
648db1a4972SPaolo Bonzini 
649db1a4972SPaolo Bonzini #endif /* !defined(_WIN32) */
650db1a4972SPaolo Bonzini 
651db1a4972SPaolo Bonzini 
652db1a4972SPaolo Bonzini #ifdef _WIN32
653db1a4972SPaolo Bonzini 
6542f9cba0cSStefan Weil static MMRESULT mm_timer;
65540f08e87SStefan Weil static TIMECAPS mm_tc;
6562f9cba0cSStefan Weil 
6572f9cba0cSStefan Weil static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
6582f9cba0cSStefan Weil                                       DWORD_PTR dwUser, DWORD_PTR dw1,
6592f9cba0cSStefan Weil                                       DWORD_PTR dw2)
6602f9cba0cSStefan Weil {
6612f9cba0cSStefan Weil     struct qemu_alarm_timer *t = alarm_timer;
6622f9cba0cSStefan Weil     if (!t) {
6632f9cba0cSStefan Weil         return;
6642f9cba0cSStefan Weil     }
6658205199dSStefan Weil     t->expired = true;
6665e1ec7b2SStefan Weil     t->pending = true;
6672f9cba0cSStefan Weil     qemu_notify_event();
6682f9cba0cSStefan Weil }
6692f9cba0cSStefan Weil 
6702f9cba0cSStefan Weil static int mm_start_timer(struct qemu_alarm_timer *t)
6712f9cba0cSStefan Weil {
67240f08e87SStefan Weil     timeGetDevCaps(&mm_tc, sizeof(mm_tc));
6732f9cba0cSStefan Weil     return 0;
6742f9cba0cSStefan Weil }
6752f9cba0cSStefan Weil 
6762f9cba0cSStefan Weil static void mm_stop_timer(struct qemu_alarm_timer *t)
6772f9cba0cSStefan Weil {
6780727b867SPaolo Bonzini     if (mm_timer) {
6792f9cba0cSStefan Weil         timeKillEvent(mm_timer);
6800727b867SPaolo Bonzini     }
6812f9cba0cSStefan Weil }
6822f9cba0cSStefan Weil 
683f3fc6e2eSPaolo Bonzini static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
6842f9cba0cSStefan Weil {
6855bfb723fSStefano Stabellini     int64_t nearest_delta_ms = delta / 1000000;
68640f08e87SStefan Weil     if (nearest_delta_ms < mm_tc.wPeriodMin) {
68740f08e87SStefan Weil         nearest_delta_ms = mm_tc.wPeriodMin;
68840f08e87SStefan Weil     } else if (nearest_delta_ms > mm_tc.wPeriodMax) {
68940f08e87SStefan Weil         nearest_delta_ms = mm_tc.wPeriodMax;
6905bfb723fSStefano Stabellini     }
691f3fc6e2eSPaolo Bonzini 
6920727b867SPaolo Bonzini     if (mm_timer) {
693f3fc6e2eSPaolo Bonzini         timeKillEvent(mm_timer);
6940727b867SPaolo Bonzini     }
69540f08e87SStefan Weil     mm_timer = timeSetEvent((UINT)nearest_delta_ms,
69640f08e87SStefan Weil                             mm_tc.wPeriodMin,
6972f9cba0cSStefan Weil                             mm_alarm_handler,
6982f9cba0cSStefan Weil                             (DWORD_PTR)t,
6992f9cba0cSStefan Weil                             TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
7002f9cba0cSStefan Weil 
7012f9cba0cSStefan Weil     if (!mm_timer) {
70252ef651fSStefan Weil         fprintf(stderr, "Failed to re-arm win32 alarm timer\n");
70340f08e87SStefan Weil         timeEndPeriod(mm_tc.wPeriodMin);
7042f9cba0cSStefan Weil         exit(1);
7052f9cba0cSStefan Weil     }
7062f9cba0cSStefan Weil }
7072f9cba0cSStefan Weil 
708db1a4972SPaolo Bonzini static int win32_start_timer(struct qemu_alarm_timer *t)
709db1a4972SPaolo Bonzini {
71068c23e55SPaolo Bonzini     HANDLE hTimer;
71168c23e55SPaolo Bonzini     BOOLEAN success;
712db1a4972SPaolo Bonzini 
71368c23e55SPaolo Bonzini     /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
71468c23e55SPaolo Bonzini        is zero) that has already expired, the timer is not updated.  Since
71568c23e55SPaolo Bonzini        creating a new timer is relatively expensive, set a bogus one-hour
71668c23e55SPaolo Bonzini        interval in the dynticks case.  */
71768c23e55SPaolo Bonzini     success = CreateTimerQueueTimer(&hTimer,
71868c23e55SPaolo Bonzini                           NULL,
71968c23e55SPaolo Bonzini                           host_alarm_handler,
72068c23e55SPaolo Bonzini                           t,
72168c23e55SPaolo Bonzini                           1,
7228205199dSStefan Weil                           3600000,
72368c23e55SPaolo Bonzini                           WT_EXECUTEINTIMERTHREAD);
724db1a4972SPaolo Bonzini 
72568c23e55SPaolo Bonzini     if (!success) {
726db1a4972SPaolo Bonzini         fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
727db1a4972SPaolo Bonzini                 GetLastError());
728db1a4972SPaolo Bonzini         return -1;
729db1a4972SPaolo Bonzini     }
730db1a4972SPaolo Bonzini 
731cd0544eeSStefan Weil     t->timer = hTimer;
732db1a4972SPaolo Bonzini     return 0;
733db1a4972SPaolo Bonzini }
734db1a4972SPaolo Bonzini 
735db1a4972SPaolo Bonzini static void win32_stop_timer(struct qemu_alarm_timer *t)
736db1a4972SPaolo Bonzini {
737cd0544eeSStefan Weil     HANDLE hTimer = t->timer;
738db1a4972SPaolo Bonzini 
73968c23e55SPaolo Bonzini     if (hTimer) {
74068c23e55SPaolo Bonzini         DeleteTimerQueueTimer(NULL, hTimer, NULL);
74168c23e55SPaolo Bonzini     }
742db1a4972SPaolo Bonzini }
743db1a4972SPaolo Bonzini 
744f3fc6e2eSPaolo Bonzini static void win32_rearm_timer(struct qemu_alarm_timer *t,
745f3fc6e2eSPaolo Bonzini                               int64_t nearest_delta_ns)
746db1a4972SPaolo Bonzini {
747cd0544eeSStefan Weil     HANDLE hTimer = t->timer;
7485bfb723fSStefano Stabellini     int64_t nearest_delta_ms;
74968c23e55SPaolo Bonzini     BOOLEAN success;
750db1a4972SPaolo Bonzini 
7515bfb723fSStefano Stabellini     nearest_delta_ms = nearest_delta_ns / 1000000;
752cfced5b2SPaolo Bonzini     if (nearest_delta_ms < 1) {
753cfced5b2SPaolo Bonzini         nearest_delta_ms = 1;
754cfced5b2SPaolo Bonzini     }
7555bfb723fSStefano Stabellini     /* ULONG_MAX can be 32 bit */
7565bfb723fSStefano Stabellini     if (nearest_delta_ms > ULONG_MAX) {
7575bfb723fSStefano Stabellini         nearest_delta_ms = ULONG_MAX;
7585bfb723fSStefano Stabellini     }
75968c23e55SPaolo Bonzini     success = ChangeTimerQueueTimer(NULL,
76068c23e55SPaolo Bonzini                                     hTimer,
7615bfb723fSStefano Stabellini                                     (unsigned long) nearest_delta_ms,
76268c23e55SPaolo Bonzini                                     3600000);
763db1a4972SPaolo Bonzini 
76468c23e55SPaolo Bonzini     if (!success) {
76568c23e55SPaolo Bonzini         fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
766db1a4972SPaolo Bonzini                 GetLastError());
76768c23e55SPaolo Bonzini         exit(-1);
768db1a4972SPaolo Bonzini     }
76968c23e55SPaolo Bonzini 
770db1a4972SPaolo Bonzini }
771db1a4972SPaolo Bonzini 
772db1a4972SPaolo Bonzini #endif /* _WIN32 */
773db1a4972SPaolo Bonzini 
7744260a739SPaolo Bonzini static void quit_timers(void)
7754260a739SPaolo Bonzini {
7764260a739SPaolo Bonzini     struct qemu_alarm_timer *t = alarm_timer;
7774260a739SPaolo Bonzini     alarm_timer = NULL;
7784260a739SPaolo Bonzini     t->stop(t);
7794260a739SPaolo Bonzini }
7804260a739SPaolo Bonzini 
781253ecf83SStefan Weil #ifdef CONFIG_POSIX
782c8122c35SPaolo Bonzini static void reinit_timers(void)
783c8122c35SPaolo Bonzini {
784c8122c35SPaolo Bonzini     struct qemu_alarm_timer *t = alarm_timer;
785c8122c35SPaolo Bonzini     t->stop(t);
786c8122c35SPaolo Bonzini     if (t->start(t)) {
787c8122c35SPaolo Bonzini         fprintf(stderr, "Internal timer error: aborting\n");
788c8122c35SPaolo Bonzini         exit(1);
789c8122c35SPaolo Bonzini     }
790c8122c35SPaolo Bonzini     qemu_rearm_alarm_timer(t);
791c8122c35SPaolo Bonzini }
792253ecf83SStefan Weil #endif /* CONFIG_POSIX */
793c8122c35SPaolo Bonzini 
794db1a4972SPaolo Bonzini int init_timer_alarm(void)
795db1a4972SPaolo Bonzini {
796db1a4972SPaolo Bonzini     struct qemu_alarm_timer *t = NULL;
797db1a4972SPaolo Bonzini     int i, err = -1;
798db1a4972SPaolo Bonzini 
799744ca8e3SPaolo Bonzini     if (alarm_timer) {
800744ca8e3SPaolo Bonzini         return 0;
801744ca8e3SPaolo Bonzini     }
802744ca8e3SPaolo Bonzini 
803db1a4972SPaolo Bonzini     for (i = 0; alarm_timers[i].name; i++) {
804db1a4972SPaolo Bonzini         t = &alarm_timers[i];
805db1a4972SPaolo Bonzini 
806db1a4972SPaolo Bonzini         err = t->start(t);
807db1a4972SPaolo Bonzini         if (!err)
808db1a4972SPaolo Bonzini             break;
809db1a4972SPaolo Bonzini     }
810db1a4972SPaolo Bonzini 
811db1a4972SPaolo Bonzini     if (err) {
812db1a4972SPaolo Bonzini         err = -ENOENT;
813db1a4972SPaolo Bonzini         goto fail;
814db1a4972SPaolo Bonzini     }
815db1a4972SPaolo Bonzini 
8164260a739SPaolo Bonzini     atexit(quit_timers);
817c8122c35SPaolo Bonzini #ifdef CONFIG_POSIX
818c8122c35SPaolo Bonzini     pthread_atfork(NULL, NULL, reinit_timers);
819c8122c35SPaolo Bonzini #endif
820db1a4972SPaolo Bonzini     alarm_timer = t;
821db1a4972SPaolo Bonzini     return 0;
822db1a4972SPaolo Bonzini 
823db1a4972SPaolo Bonzini fail:
824db1a4972SPaolo Bonzini     return err;
825db1a4972SPaolo Bonzini }
826db1a4972SPaolo Bonzini 
827