xref: /qemu/util/qemu-timer.c (revision ac70aafc28bec4d1014082f0c6659a368c5a95bd)
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 
404e0c6529SAlex Bligh #ifdef CONFIG_PPOLL
414e0c6529SAlex Bligh #include <poll.h>
424e0c6529SAlex Bligh #endif
434e0c6529SAlex Bligh 
44cd758dd0SAlex Bligh #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
45cd758dd0SAlex Bligh #include <sys/prctl.h>
46cd758dd0SAlex Bligh #endif
47cd758dd0SAlex Bligh 
48db1a4972SPaolo Bonzini /***********************************************************/
49db1a4972SPaolo Bonzini /* timers */
50db1a4972SPaolo Bonzini 
51db1a4972SPaolo Bonzini struct QEMUClock {
52ff83c66eSAlex Bligh     QEMUTimerList *main_loop_timerlist;
53ff83c66eSAlex Bligh     QLIST_HEAD(, QEMUTimerList) timerlists;
54691a0c9cSJan Kiszka 
55691a0c9cSJan Kiszka     NotifierList reset_notifiers;
56691a0c9cSJan Kiszka     int64_t last;
579a14b298SStefan Weil 
58ff83c66eSAlex Bligh     QEMUClockType type;
599a14b298SStefan Weil     bool enabled;
60db1a4972SPaolo Bonzini };
61db1a4972SPaolo Bonzini 
62754d6a54SAlex Bligh QEMUTimerListGroup main_loop_tlg;
63ff83c66eSAlex Bligh QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
64ff83c66eSAlex Bligh 
65ff83c66eSAlex Bligh /* A QEMUTimerList is a list of timers attached to a clock. More
66ff83c66eSAlex Bligh  * than one QEMUTimerList can be attached to each clock, for instance
67ff83c66eSAlex Bligh  * used by different AioContexts / threads. Each clock also has
68ff83c66eSAlex Bligh  * a list of the QEMUTimerLists associated with it, in order that
69ff83c66eSAlex Bligh  * reenabling the clock can call all the notifiers.
70ff83c66eSAlex Bligh  */
71ff83c66eSAlex Bligh 
72ff83c66eSAlex Bligh struct QEMUTimerList {
739a14b298SStefan Weil     QEMUClock *clock;
74ff83c66eSAlex Bligh     QEMUTimer *active_timers;
75ff83c66eSAlex Bligh     QLIST_ENTRY(QEMUTimerList) list;
76d5541d86SAlex Bligh     QEMUTimerListNotifyCB *notify_cb;
77d5541d86SAlex Bligh     void *notify_opaque;
78db1a4972SPaolo Bonzini };
79db1a4972SPaolo Bonzini 
80db1a4972SPaolo Bonzini struct qemu_alarm_timer {
81db1a4972SPaolo Bonzini     char const *name;
82db1a4972SPaolo Bonzini     int (*start)(struct qemu_alarm_timer *t);
83db1a4972SPaolo Bonzini     void (*stop)(struct qemu_alarm_timer *t);
84f3fc6e2eSPaolo Bonzini     void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
85cd0544eeSStefan Weil #if defined(__linux__)
86cd0544eeSStefan Weil     timer_t timer;
879a14b298SStefan Weil     int fd;
88cd0544eeSStefan Weil #elif defined(_WIN32)
89cd0544eeSStefan Weil     HANDLE timer;
90cd0544eeSStefan Weil #endif
915e1ec7b2SStefan Weil     bool expired;
925e1ec7b2SStefan Weil     bool pending;
93db1a4972SPaolo Bonzini };
94db1a4972SPaolo Bonzini 
95db1a4972SPaolo Bonzini static struct qemu_alarm_timer *alarm_timer;
96db1a4972SPaolo Bonzini 
97e93379b0SAlex Bligh static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
9845c7b37fSStefan Weil {
9945c7b37fSStefan Weil     return timer_head && (timer_head->expire_time <= current_time);
10045c7b37fSStefan Weil }
10145c7b37fSStefan Weil 
102f3fc6e2eSPaolo Bonzini static int64_t qemu_next_alarm_deadline(void)
103f3fc6e2eSPaolo Bonzini {
1044ffd16fcSStefano Stabellini     int64_t delta = INT64_MAX;
105f3fc6e2eSPaolo Bonzini     int64_t rtdelta;
106ff83c66eSAlex Bligh     int64_t hdelta;
107f3fc6e2eSPaolo Bonzini 
108ff83c66eSAlex Bligh     if (!use_icount && vm_clock->enabled &&
109ff83c66eSAlex Bligh         vm_clock->main_loop_timerlist->active_timers) {
110ff83c66eSAlex Bligh         delta = vm_clock->main_loop_timerlist->active_timers->expire_time -
111f3fc6e2eSPaolo Bonzini             qemu_get_clock_ns(vm_clock);
112f3fc6e2eSPaolo Bonzini     }
113ff83c66eSAlex Bligh     if (host_clock->enabled &&
114ff83c66eSAlex Bligh         host_clock->main_loop_timerlist->active_timers) {
115ff83c66eSAlex Bligh         hdelta = host_clock->main_loop_timerlist->active_timers->expire_time -
116f3fc6e2eSPaolo Bonzini             qemu_get_clock_ns(host_clock);
117f3fc6e2eSPaolo Bonzini         if (hdelta < delta) {
118f3fc6e2eSPaolo Bonzini             delta = hdelta;
119f3fc6e2eSPaolo Bonzini         }
120f3fc6e2eSPaolo Bonzini     }
121ff83c66eSAlex Bligh     if (rt_clock->enabled &&
122ff83c66eSAlex Bligh         rt_clock->main_loop_timerlist->active_timers) {
123ff83c66eSAlex Bligh         rtdelta = (rt_clock->main_loop_timerlist->active_timers->expire_time -
124f3fc6e2eSPaolo Bonzini                    qemu_get_clock_ns(rt_clock));
125f3fc6e2eSPaolo Bonzini         if (rtdelta < delta) {
126f3fc6e2eSPaolo Bonzini             delta = rtdelta;
127f3fc6e2eSPaolo Bonzini         }
128f3fc6e2eSPaolo Bonzini     }
129f3fc6e2eSPaolo Bonzini 
130f3fc6e2eSPaolo Bonzini     return delta;
131f3fc6e2eSPaolo Bonzini }
132f3fc6e2eSPaolo Bonzini 
133db1a4972SPaolo Bonzini static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
134db1a4972SPaolo Bonzini {
1358227421eSStefano Stabellini     int64_t nearest_delta_ns = qemu_next_alarm_deadline();
1368227421eSStefano Stabellini     if (nearest_delta_ns < INT64_MAX) {
137f3fc6e2eSPaolo Bonzini         t->rearm(t, nearest_delta_ns);
138db1a4972SPaolo Bonzini     }
1398227421eSStefano Stabellini }
140db1a4972SPaolo Bonzini 
1419c13246aSPaolo Bonzini /* TODO: MIN_TIMER_REARM_NS should be optimized */
1429c13246aSPaolo Bonzini #define MIN_TIMER_REARM_NS 250000
143db1a4972SPaolo Bonzini 
144db1a4972SPaolo Bonzini #ifdef _WIN32
145db1a4972SPaolo Bonzini 
1462f9cba0cSStefan Weil static int mm_start_timer(struct qemu_alarm_timer *t);
1472f9cba0cSStefan Weil static void mm_stop_timer(struct qemu_alarm_timer *t);
148f3fc6e2eSPaolo Bonzini static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
1492f9cba0cSStefan Weil 
150db1a4972SPaolo Bonzini static int win32_start_timer(struct qemu_alarm_timer *t);
151db1a4972SPaolo Bonzini static void win32_stop_timer(struct qemu_alarm_timer *t);
152f3fc6e2eSPaolo Bonzini static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
153db1a4972SPaolo Bonzini 
154db1a4972SPaolo Bonzini #else
155db1a4972SPaolo Bonzini 
156db1a4972SPaolo Bonzini static int unix_start_timer(struct qemu_alarm_timer *t);
157db1a4972SPaolo Bonzini static void unix_stop_timer(struct qemu_alarm_timer *t);
158f3fc6e2eSPaolo Bonzini static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
159db1a4972SPaolo Bonzini 
160db1a4972SPaolo Bonzini #ifdef __linux__
161db1a4972SPaolo Bonzini 
162db1a4972SPaolo Bonzini static int dynticks_start_timer(struct qemu_alarm_timer *t);
163db1a4972SPaolo Bonzini static void dynticks_stop_timer(struct qemu_alarm_timer *t);
164f3fc6e2eSPaolo Bonzini static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
165db1a4972SPaolo Bonzini 
166db1a4972SPaolo Bonzini #endif /* __linux__ */
167db1a4972SPaolo Bonzini 
168db1a4972SPaolo Bonzini #endif /* _WIN32 */
169db1a4972SPaolo Bonzini 
170db1a4972SPaolo Bonzini static struct qemu_alarm_timer alarm_timers[] = {
171db1a4972SPaolo Bonzini #ifndef _WIN32
172db1a4972SPaolo Bonzini #ifdef __linux__
173db1a4972SPaolo Bonzini     {"dynticks", dynticks_start_timer,
174cd0544eeSStefan Weil      dynticks_stop_timer, dynticks_rearm_timer},
175db1a4972SPaolo Bonzini #endif
17684682834SPaolo Bonzini     {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer},
177db1a4972SPaolo Bonzini #else
178cca5de73SPaolo Bonzini     {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer},
179cd0544eeSStefan Weil     {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
180db1a4972SPaolo Bonzini #endif
181db1a4972SPaolo Bonzini     {NULL, }
182db1a4972SPaolo Bonzini };
183db1a4972SPaolo Bonzini 
184db1a4972SPaolo Bonzini static void show_available_alarms(void)
185db1a4972SPaolo Bonzini {
186db1a4972SPaolo Bonzini     int i;
187db1a4972SPaolo Bonzini 
188db1a4972SPaolo Bonzini     printf("Available alarm timers, in order of precedence:\n");
189db1a4972SPaolo Bonzini     for (i = 0; alarm_timers[i].name; i++)
190db1a4972SPaolo Bonzini         printf("%s\n", alarm_timers[i].name);
191db1a4972SPaolo Bonzini }
192db1a4972SPaolo Bonzini 
193db1a4972SPaolo Bonzini void configure_alarms(char const *opt)
194db1a4972SPaolo Bonzini {
195db1a4972SPaolo Bonzini     int i;
196db1a4972SPaolo Bonzini     int cur = 0;
197db1a4972SPaolo Bonzini     int count = ARRAY_SIZE(alarm_timers) - 1;
198db1a4972SPaolo Bonzini     char *arg;
199db1a4972SPaolo Bonzini     char *name;
200db1a4972SPaolo Bonzini     struct qemu_alarm_timer tmp;
201db1a4972SPaolo Bonzini 
202c8057f95SPeter Maydell     if (is_help_option(opt)) {
203db1a4972SPaolo Bonzini         show_available_alarms();
204db1a4972SPaolo Bonzini         exit(0);
205db1a4972SPaolo Bonzini     }
206db1a4972SPaolo Bonzini 
2077267c094SAnthony Liguori     arg = g_strdup(opt);
208db1a4972SPaolo Bonzini 
209db1a4972SPaolo Bonzini     /* Reorder the array */
210db1a4972SPaolo Bonzini     name = strtok(arg, ",");
211db1a4972SPaolo Bonzini     while (name) {
212db1a4972SPaolo Bonzini         for (i = 0; i < count && alarm_timers[i].name; i++) {
213db1a4972SPaolo Bonzini             if (!strcmp(alarm_timers[i].name, name))
214db1a4972SPaolo Bonzini                 break;
215db1a4972SPaolo Bonzini         }
216db1a4972SPaolo Bonzini 
217db1a4972SPaolo Bonzini         if (i == count) {
218db1a4972SPaolo Bonzini             fprintf(stderr, "Unknown clock %s\n", name);
219db1a4972SPaolo Bonzini             goto next;
220db1a4972SPaolo Bonzini         }
221db1a4972SPaolo Bonzini 
222db1a4972SPaolo Bonzini         if (i < cur)
223db1a4972SPaolo Bonzini             /* Ignore */
224db1a4972SPaolo Bonzini             goto next;
225db1a4972SPaolo Bonzini 
226db1a4972SPaolo Bonzini 	/* Swap */
227db1a4972SPaolo Bonzini         tmp = alarm_timers[i];
228db1a4972SPaolo Bonzini         alarm_timers[i] = alarm_timers[cur];
229db1a4972SPaolo Bonzini         alarm_timers[cur] = tmp;
230db1a4972SPaolo Bonzini 
231db1a4972SPaolo Bonzini         cur++;
232db1a4972SPaolo Bonzini next:
233db1a4972SPaolo Bonzini         name = strtok(NULL, ",");
234db1a4972SPaolo Bonzini     }
235db1a4972SPaolo Bonzini 
2367267c094SAnthony Liguori     g_free(arg);
237db1a4972SPaolo Bonzini 
238db1a4972SPaolo Bonzini     if (cur) {
239db1a4972SPaolo Bonzini         /* Disable remaining timers */
240db1a4972SPaolo Bonzini         for (i = cur; i < count; i++)
241db1a4972SPaolo Bonzini             alarm_timers[i].name = NULL;
242db1a4972SPaolo Bonzini     } else {
243db1a4972SPaolo Bonzini         show_available_alarms();
244db1a4972SPaolo Bonzini         exit(1);
245db1a4972SPaolo Bonzini     }
246db1a4972SPaolo Bonzini }
247db1a4972SPaolo Bonzini 
248d5541d86SAlex Bligh static QEMUTimerList *timerlist_new_from_clock(QEMUClock *clock,
249d5541d86SAlex Bligh                                                QEMUTimerListNotifyCB *cb,
250d5541d86SAlex Bligh                                                void *opaque)
251ff83c66eSAlex Bligh {
252ff83c66eSAlex Bligh     QEMUTimerList *timer_list;
253db1a4972SPaolo Bonzini 
254ff83c66eSAlex Bligh     /* Assert if we do not have a clock. If you see this
255ff83c66eSAlex Bligh      * assertion in means that the clocks have not been
256ff83c66eSAlex Bligh      * initialised before a timerlist is needed. This
257ff83c66eSAlex Bligh      * normally happens if an AioContext is used before
258ff83c66eSAlex Bligh      * init_clocks() is called within main().
259ff83c66eSAlex Bligh      */
260ff83c66eSAlex Bligh     assert(clock);
261ff83c66eSAlex Bligh 
262ff83c66eSAlex Bligh     timer_list = g_malloc0(sizeof(QEMUTimerList));
263ff83c66eSAlex Bligh     timer_list->clock = clock;
264d5541d86SAlex Bligh     timer_list->notify_cb = cb;
265d5541d86SAlex Bligh     timer_list->notify_opaque = opaque;
266ff83c66eSAlex Bligh     QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
267ff83c66eSAlex Bligh     return timer_list;
268ff83c66eSAlex Bligh }
269ff83c66eSAlex Bligh 
270d5541d86SAlex Bligh QEMUTimerList *timerlist_new(QEMUClockType type,
271d5541d86SAlex Bligh                              QEMUTimerListNotifyCB *cb, void *opaque)
272ff83c66eSAlex Bligh {
273d5541d86SAlex Bligh     return timerlist_new_from_clock(qemu_clock_ptr(type), cb, opaque);
274ff83c66eSAlex Bligh }
275ff83c66eSAlex Bligh 
276ff83c66eSAlex Bligh void timerlist_free(QEMUTimerList *timer_list)
277ff83c66eSAlex Bligh {
278ff83c66eSAlex Bligh     assert(!timerlist_has_timers(timer_list));
279ff83c66eSAlex Bligh     if (timer_list->clock) {
280ff83c66eSAlex Bligh         QLIST_REMOVE(timer_list, list);
281ff83c66eSAlex Bligh         if (timer_list->clock->main_loop_timerlist == timer_list) {
282ff83c66eSAlex Bligh             timer_list->clock->main_loop_timerlist = NULL;
283ff83c66eSAlex Bligh         }
284ff83c66eSAlex Bligh     }
285ff83c66eSAlex Bligh     g_free(timer_list);
286ff83c66eSAlex Bligh }
287ff83c66eSAlex Bligh 
288ff83c66eSAlex Bligh static QEMUClock *qemu_clock_new(QEMUClockType type)
289db1a4972SPaolo Bonzini {
290db1a4972SPaolo Bonzini     QEMUClock *clock;
291691a0c9cSJan Kiszka 
2927267c094SAnthony Liguori     clock = g_malloc0(sizeof(QEMUClock));
293db1a4972SPaolo Bonzini     clock->type = type;
2945e1ec7b2SStefan Weil     clock->enabled = true;
2952ff68d07SPaolo Bonzini     clock->last = INT64_MIN;
296ff83c66eSAlex Bligh     QLIST_INIT(&clock->timerlists);
297691a0c9cSJan Kiszka     notifier_list_init(&clock->reset_notifiers);
298d5541d86SAlex Bligh     clock->main_loop_timerlist = timerlist_new_from_clock(clock, NULL, NULL);
299db1a4972SPaolo Bonzini     return clock;
300db1a4972SPaolo Bonzini }
301db1a4972SPaolo Bonzini 
302ff83c66eSAlex Bligh bool qemu_clock_use_for_deadline(QEMUClock *clock)
303ff83c66eSAlex Bligh {
304ff83c66eSAlex Bligh     return !(use_icount && (clock->type == QEMU_CLOCK_VIRTUAL));
305ff83c66eSAlex Bligh }
306ff83c66eSAlex Bligh 
307b1bbfe72SAlex Bligh void qemu_clock_notify(QEMUClock *clock)
308b1bbfe72SAlex Bligh {
309b1bbfe72SAlex Bligh     QEMUTimerList *timer_list;
310b1bbfe72SAlex Bligh     QLIST_FOREACH(timer_list, &clock->timerlists, list) {
311b1bbfe72SAlex Bligh         timerlist_notify(timer_list);
312b1bbfe72SAlex Bligh     }
313b1bbfe72SAlex Bligh }
314b1bbfe72SAlex Bligh 
3155e1ec7b2SStefan Weil void qemu_clock_enable(QEMUClock *clock, bool enabled)
316db1a4972SPaolo Bonzini {
317fbdc14ebSPaolo Bonzini     bool old = clock->enabled;
318db1a4972SPaolo Bonzini     clock->enabled = enabled;
319fbdc14ebSPaolo Bonzini     if (enabled && !old) {
320b1bbfe72SAlex Bligh         qemu_clock_notify(clock);
321fbdc14ebSPaolo Bonzini         qemu_rearm_alarm_timer(alarm_timer);
322fbdc14ebSPaolo Bonzini     }
323db1a4972SPaolo Bonzini }
324db1a4972SPaolo Bonzini 
325ff83c66eSAlex Bligh bool timerlist_has_timers(QEMUTimerList *timer_list)
326dc2dfcf0SPaolo Bonzini {
327ff83c66eSAlex Bligh     return !!timer_list->active_timers;
328dc2dfcf0SPaolo Bonzini }
329dc2dfcf0SPaolo Bonzini 
330ff83c66eSAlex Bligh bool qemu_clock_has_timers(QEMUClock *clock)
331dc2dfcf0SPaolo Bonzini {
332ff83c66eSAlex Bligh     return timerlist_has_timers(clock->main_loop_timerlist);
333dc2dfcf0SPaolo Bonzini }
334dc2dfcf0SPaolo Bonzini 
335ff83c66eSAlex Bligh bool timerlist_expired(QEMUTimerList *timer_list)
336ff83c66eSAlex Bligh {
337ff83c66eSAlex Bligh     return (timer_list->active_timers &&
338ff83c66eSAlex Bligh             timer_list->active_timers->expire_time <
339ff83c66eSAlex Bligh             qemu_get_clock_ns(timer_list->clock));
340ff83c66eSAlex Bligh }
341ff83c66eSAlex Bligh 
342ff83c66eSAlex Bligh bool qemu_clock_expired(QEMUClock *clock)
343ff83c66eSAlex Bligh {
344ff83c66eSAlex Bligh     return timerlist_expired(clock->main_loop_timerlist);
345ff83c66eSAlex Bligh }
346ff83c66eSAlex Bligh 
347ff83c66eSAlex Bligh int64_t timerlist_deadline(QEMUTimerList *timer_list)
348dc2dfcf0SPaolo Bonzini {
349dc2dfcf0SPaolo Bonzini     /* To avoid problems with overflow limit this to 2^32.  */
350dc2dfcf0SPaolo Bonzini     int64_t delta = INT32_MAX;
351dc2dfcf0SPaolo Bonzini 
352ff83c66eSAlex Bligh     if (timer_list->clock->enabled && timer_list->active_timers) {
353ff83c66eSAlex Bligh         delta = timer_list->active_timers->expire_time -
354ff83c66eSAlex Bligh             qemu_get_clock_ns(timer_list->clock);
355dc2dfcf0SPaolo Bonzini     }
356dc2dfcf0SPaolo Bonzini     if (delta < 0) {
357dc2dfcf0SPaolo Bonzini         delta = 0;
358dc2dfcf0SPaolo Bonzini     }
359dc2dfcf0SPaolo Bonzini     return delta;
360dc2dfcf0SPaolo Bonzini }
361dc2dfcf0SPaolo Bonzini 
362ff83c66eSAlex Bligh int64_t qemu_clock_deadline(QEMUClock *clock)
363ff83c66eSAlex Bligh {
364ff83c66eSAlex Bligh     return timerlist_deadline(clock->main_loop_timerlist);
365ff83c66eSAlex Bligh }
366ff83c66eSAlex Bligh 
36702a03a9fSAlex Bligh /*
36802a03a9fSAlex Bligh  * As above, but return -1 for no deadline, and do not cap to 2^32
36902a03a9fSAlex Bligh  * as we know the result is always positive.
37002a03a9fSAlex Bligh  */
37102a03a9fSAlex Bligh 
372ff83c66eSAlex Bligh int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
37302a03a9fSAlex Bligh {
37402a03a9fSAlex Bligh     int64_t delta;
37502a03a9fSAlex Bligh 
376ff83c66eSAlex Bligh     if (!timer_list->clock->enabled || !timer_list->active_timers) {
37702a03a9fSAlex Bligh         return -1;
37802a03a9fSAlex Bligh     }
37902a03a9fSAlex Bligh 
380ff83c66eSAlex Bligh     delta = timer_list->active_timers->expire_time -
381ff83c66eSAlex Bligh         qemu_get_clock_ns(timer_list->clock);
38202a03a9fSAlex Bligh 
38302a03a9fSAlex Bligh     if (delta <= 0) {
38402a03a9fSAlex Bligh         return 0;
38502a03a9fSAlex Bligh     }
38602a03a9fSAlex Bligh 
38702a03a9fSAlex Bligh     return delta;
38802a03a9fSAlex Bligh }
38902a03a9fSAlex Bligh 
390ff83c66eSAlex Bligh int64_t qemu_clock_deadline_ns(QEMUClock *clock)
391ff83c66eSAlex Bligh {
392ff83c66eSAlex Bligh     return timerlist_deadline_ns(clock->main_loop_timerlist);
393ff83c66eSAlex Bligh }
394ff83c66eSAlex Bligh 
395*ac70aafcSAlex Bligh /* Calculate the soonest deadline across all timerlists attached
396*ac70aafcSAlex Bligh  * to the clock. This is used for the icount timeout so we
397*ac70aafcSAlex Bligh  * ignore whether or not the clock should be used in deadline
398*ac70aafcSAlex Bligh  * calculations.
399*ac70aafcSAlex Bligh  */
400*ac70aafcSAlex Bligh int64_t qemu_clock_deadline_ns_all(QEMUClock *clock)
401*ac70aafcSAlex Bligh {
402*ac70aafcSAlex Bligh     int64_t deadline = -1;
403*ac70aafcSAlex Bligh     QEMUTimerList *timer_list;
404*ac70aafcSAlex Bligh     QLIST_FOREACH(timer_list, &clock->timerlists, list) {
405*ac70aafcSAlex Bligh         deadline = qemu_soonest_timeout(deadline,
406*ac70aafcSAlex Bligh                                         timerlist_deadline_ns(timer_list));
407*ac70aafcSAlex Bligh     }
408*ac70aafcSAlex Bligh     return deadline;
409*ac70aafcSAlex Bligh }
410*ac70aafcSAlex Bligh 
411ff83c66eSAlex Bligh QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list)
412ff83c66eSAlex Bligh {
413ff83c66eSAlex Bligh     return timer_list->clock;
414ff83c66eSAlex Bligh }
415ff83c66eSAlex Bligh 
416ff83c66eSAlex Bligh QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClock *clock)
417ff83c66eSAlex Bligh {
418ff83c66eSAlex Bligh     return clock->main_loop_timerlist;
419ff83c66eSAlex Bligh }
420ff83c66eSAlex Bligh 
421d5541d86SAlex Bligh void timerlist_notify(QEMUTimerList *timer_list)
422d5541d86SAlex Bligh {
423d5541d86SAlex Bligh     if (timer_list->notify_cb) {
424d5541d86SAlex Bligh         timer_list->notify_cb(timer_list->notify_opaque);
425d5541d86SAlex Bligh     } else {
426d5541d86SAlex Bligh         qemu_notify_event();
427d5541d86SAlex Bligh     }
428d5541d86SAlex Bligh }
429d5541d86SAlex Bligh 
43002a03a9fSAlex Bligh /* Transition function to convert a nanosecond timeout to ms
43102a03a9fSAlex Bligh  * This is used where a system does not support ppoll
43202a03a9fSAlex Bligh  */
43302a03a9fSAlex Bligh int qemu_timeout_ns_to_ms(int64_t ns)
43402a03a9fSAlex Bligh {
43502a03a9fSAlex Bligh     int64_t ms;
43602a03a9fSAlex Bligh     if (ns < 0) {
43702a03a9fSAlex Bligh         return -1;
43802a03a9fSAlex Bligh     }
43902a03a9fSAlex Bligh 
44002a03a9fSAlex Bligh     if (!ns) {
44102a03a9fSAlex Bligh         return 0;
44202a03a9fSAlex Bligh     }
44302a03a9fSAlex Bligh 
44402a03a9fSAlex Bligh     /* Always round up, because it's better to wait too long than to wait too
44502a03a9fSAlex Bligh      * little and effectively busy-wait
44602a03a9fSAlex Bligh      */
44702a03a9fSAlex Bligh     ms = (ns + SCALE_MS - 1) / SCALE_MS;
44802a03a9fSAlex Bligh 
44902a03a9fSAlex Bligh     /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
45002a03a9fSAlex Bligh     if (ms > (int64_t) INT32_MAX) {
45102a03a9fSAlex Bligh         ms = INT32_MAX;
45202a03a9fSAlex Bligh     }
45302a03a9fSAlex Bligh 
45402a03a9fSAlex Bligh     return (int) ms;
45502a03a9fSAlex Bligh }
45602a03a9fSAlex Bligh 
45702a03a9fSAlex Bligh 
4584e0c6529SAlex Bligh /* qemu implementation of g_poll which uses a nanosecond timeout but is
4594e0c6529SAlex Bligh  * otherwise identical to g_poll
4604e0c6529SAlex Bligh  */
4614e0c6529SAlex Bligh int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout)
4624e0c6529SAlex Bligh {
4634e0c6529SAlex Bligh #ifdef CONFIG_PPOLL
4644e0c6529SAlex Bligh     if (timeout < 0) {
4654e0c6529SAlex Bligh         return ppoll((struct pollfd *)fds, nfds, NULL, NULL);
4664e0c6529SAlex Bligh     } else {
4674e0c6529SAlex Bligh         struct timespec ts;
4684e0c6529SAlex Bligh         ts.tv_sec = timeout / 1000000000LL;
4694e0c6529SAlex Bligh         ts.tv_nsec = timeout % 1000000000LL;
4704e0c6529SAlex Bligh         return ppoll((struct pollfd *)fds, nfds, &ts, NULL);
4714e0c6529SAlex Bligh     }
4724e0c6529SAlex Bligh #else
4734e0c6529SAlex Bligh     return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout));
4744e0c6529SAlex Bligh #endif
4754e0c6529SAlex Bligh }
4764e0c6529SAlex Bligh 
4774e0c6529SAlex Bligh 
478ff83c66eSAlex Bligh void timer_init(QEMUTimer *ts,
479ff83c66eSAlex Bligh                 QEMUTimerList *timer_list, int scale,
4804a998740SPaolo Bonzini                 QEMUTimerCB *cb, void *opaque)
481db1a4972SPaolo Bonzini {
482ff83c66eSAlex Bligh     ts->timer_list = timer_list;
483db1a4972SPaolo Bonzini     ts->cb = cb;
484db1a4972SPaolo Bonzini     ts->opaque = opaque;
4854a998740SPaolo Bonzini     ts->scale = scale;
486ff83c66eSAlex Bligh }
487ff83c66eSAlex Bligh 
488ff83c66eSAlex Bligh QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
489ff83c66eSAlex Bligh                           QEMUTimerCB *cb, void *opaque)
490ff83c66eSAlex Bligh {
491ff83c66eSAlex Bligh     return timer_new_tl(clock->main_loop_timerlist,
492ff83c66eSAlex Bligh                      scale, cb, opaque);
493db1a4972SPaolo Bonzini }
494db1a4972SPaolo Bonzini 
495db1a4972SPaolo Bonzini void qemu_free_timer(QEMUTimer *ts)
496db1a4972SPaolo Bonzini {
4977267c094SAnthony Liguori     g_free(ts);
498db1a4972SPaolo Bonzini }
499db1a4972SPaolo Bonzini 
500db1a4972SPaolo Bonzini /* stop a timer, but do not dealloc it */
501db1a4972SPaolo Bonzini void qemu_del_timer(QEMUTimer *ts)
502db1a4972SPaolo Bonzini {
503db1a4972SPaolo Bonzini     QEMUTimer **pt, *t;
504db1a4972SPaolo Bonzini 
505db1a4972SPaolo Bonzini     /* NOTE: this code must be signal safe because
506e93379b0SAlex Bligh        timer_expired() can be called from a signal. */
507ff83c66eSAlex Bligh     pt = &ts->timer_list->active_timers;
508db1a4972SPaolo Bonzini     for(;;) {
509db1a4972SPaolo Bonzini         t = *pt;
510db1a4972SPaolo Bonzini         if (!t)
511db1a4972SPaolo Bonzini             break;
512db1a4972SPaolo Bonzini         if (t == ts) {
513db1a4972SPaolo Bonzini             *pt = t->next;
514db1a4972SPaolo Bonzini             break;
515db1a4972SPaolo Bonzini         }
516db1a4972SPaolo Bonzini         pt = &t->next;
517db1a4972SPaolo Bonzini     }
518db1a4972SPaolo Bonzini }
519db1a4972SPaolo Bonzini 
520db1a4972SPaolo Bonzini /* modify the current timer so that it will be fired when current_time
521db1a4972SPaolo Bonzini    >= expire_time. The corresponding callback will be called. */
5222ff68d07SPaolo Bonzini void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
523db1a4972SPaolo Bonzini {
524db1a4972SPaolo Bonzini     QEMUTimer **pt, *t;
525db1a4972SPaolo Bonzini 
526db1a4972SPaolo Bonzini     qemu_del_timer(ts);
527db1a4972SPaolo Bonzini 
528db1a4972SPaolo Bonzini     /* add the timer in the sorted list */
529db1a4972SPaolo Bonzini     /* NOTE: this code must be signal safe because
530e93379b0SAlex Bligh        timer_expired() can be called from a signal. */
531ff83c66eSAlex Bligh     pt = &ts->timer_list->active_timers;
532db1a4972SPaolo Bonzini     for(;;) {
533db1a4972SPaolo Bonzini         t = *pt;
534e93379b0SAlex Bligh         if (!timer_expired_ns(t, expire_time)) {
535db1a4972SPaolo Bonzini             break;
53645c7b37fSStefan Weil         }
537db1a4972SPaolo Bonzini         pt = &t->next;
538db1a4972SPaolo Bonzini     }
539db1a4972SPaolo Bonzini     ts->expire_time = expire_time;
540db1a4972SPaolo Bonzini     ts->next = *pt;
541db1a4972SPaolo Bonzini     *pt = ts;
542db1a4972SPaolo Bonzini 
543db1a4972SPaolo Bonzini     /* Rearm if necessary  */
544ff83c66eSAlex Bligh     if (pt == &ts->timer_list->active_timers) {
545db1a4972SPaolo Bonzini         if (!alarm_timer->pending) {
546db1a4972SPaolo Bonzini             qemu_rearm_alarm_timer(alarm_timer);
547db1a4972SPaolo Bonzini         }
548db1a4972SPaolo Bonzini         /* Interrupt execution to force deadline recalculation.  */
549ff83c66eSAlex Bligh         qemu_clock_warp(ts->timer_list->clock);
550d5541d86SAlex Bligh         timerlist_notify(ts->timer_list);
551db1a4972SPaolo Bonzini     }
552db1a4972SPaolo Bonzini }
553db1a4972SPaolo Bonzini 
5544a998740SPaolo Bonzini void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
5554a998740SPaolo Bonzini {
5564a998740SPaolo Bonzini     qemu_mod_timer_ns(ts, expire_time * ts->scale);
5574a998740SPaolo Bonzini }
5584a998740SPaolo Bonzini 
559e93379b0SAlex Bligh bool timer_pending(QEMUTimer *ts)
560db1a4972SPaolo Bonzini {
561db1a4972SPaolo Bonzini     QEMUTimer *t;
562ff83c66eSAlex Bligh     for (t = ts->timer_list->active_timers; t != NULL; t = t->next) {
5635e1ec7b2SStefan Weil         if (t == ts) {
5645e1ec7b2SStefan Weil             return true;
565db1a4972SPaolo Bonzini         }
5665e1ec7b2SStefan Weil     }
5675e1ec7b2SStefan Weil     return false;
568db1a4972SPaolo Bonzini }
569db1a4972SPaolo Bonzini 
570e93379b0SAlex Bligh bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
571db1a4972SPaolo Bonzini {
572e93379b0SAlex Bligh     return timer_expired_ns(timer_head, current_time * timer_head->scale);
573db1a4972SPaolo Bonzini }
574db1a4972SPaolo Bonzini 
575ff83c66eSAlex Bligh bool timerlist_run_timers(QEMUTimerList *timer_list)
576db1a4972SPaolo Bonzini {
577144b97c2SPaolo Bonzini     QEMUTimer *ts;
578db1a4972SPaolo Bonzini     int64_t current_time;
579f9a976b7SAlex Bligh     bool progress = false;
580db1a4972SPaolo Bonzini 
581ff83c66eSAlex Bligh     if (!timer_list->clock->enabled) {
582f9a976b7SAlex Bligh         return progress;
583ff83c66eSAlex Bligh     }
584db1a4972SPaolo Bonzini 
585ff83c66eSAlex Bligh     current_time = qemu_get_clock_ns(timer_list->clock);
586db1a4972SPaolo Bonzini     for(;;) {
587ff83c66eSAlex Bligh         ts = timer_list->active_timers;
588e93379b0SAlex Bligh         if (!timer_expired_ns(ts, current_time)) {
589db1a4972SPaolo Bonzini             break;
59045c7b37fSStefan Weil         }
591db1a4972SPaolo Bonzini         /* remove timer from the list before calling the callback */
592ff83c66eSAlex Bligh         timer_list->active_timers = ts->next;
593db1a4972SPaolo Bonzini         ts->next = NULL;
594db1a4972SPaolo Bonzini 
595db1a4972SPaolo Bonzini         /* run the callback (the timer list can be modified) */
596db1a4972SPaolo Bonzini         ts->cb(ts->opaque);
597f9a976b7SAlex Bligh         progress = true;
598db1a4972SPaolo Bonzini     }
599f9a976b7SAlex Bligh     return progress;
600db1a4972SPaolo Bonzini }
601db1a4972SPaolo Bonzini 
602ff83c66eSAlex Bligh bool qemu_run_timers(QEMUClock *clock)
603ff83c66eSAlex Bligh {
604ff83c66eSAlex Bligh     return timerlist_run_timers(clock->main_loop_timerlist);
605ff83c66eSAlex Bligh }
606ff83c66eSAlex Bligh 
607d5541d86SAlex Bligh void timerlistgroup_init(QEMUTimerListGroup *tlg,
608d5541d86SAlex Bligh                          QEMUTimerListNotifyCB *cb, void *opaque)
609754d6a54SAlex Bligh {
610754d6a54SAlex Bligh     QEMUClockType type;
611754d6a54SAlex Bligh     for (type = 0; type < QEMU_CLOCK_MAX; type++) {
612d5541d86SAlex Bligh         tlg->tl[type] = timerlist_new(type, cb, opaque);
613754d6a54SAlex Bligh     }
614754d6a54SAlex Bligh }
615754d6a54SAlex Bligh 
616754d6a54SAlex Bligh void timerlistgroup_deinit(QEMUTimerListGroup *tlg)
617754d6a54SAlex Bligh {
618754d6a54SAlex Bligh     QEMUClockType type;
619754d6a54SAlex Bligh     for (type = 0; type < QEMU_CLOCK_MAX; type++) {
620754d6a54SAlex Bligh         timerlist_free(tlg->tl[type]);
621754d6a54SAlex Bligh     }
622754d6a54SAlex Bligh }
623754d6a54SAlex Bligh 
624754d6a54SAlex Bligh bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg)
625754d6a54SAlex Bligh {
626754d6a54SAlex Bligh     QEMUClockType type;
627754d6a54SAlex Bligh     bool progress = false;
628754d6a54SAlex Bligh     for (type = 0; type < QEMU_CLOCK_MAX; type++) {
629754d6a54SAlex Bligh         progress |= timerlist_run_timers(tlg->tl[type]);
630754d6a54SAlex Bligh     }
631754d6a54SAlex Bligh     return progress;
632754d6a54SAlex Bligh }
633754d6a54SAlex Bligh 
634754d6a54SAlex Bligh int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg)
635754d6a54SAlex Bligh {
636754d6a54SAlex Bligh     int64_t deadline = -1;
637754d6a54SAlex Bligh     QEMUClockType type;
638754d6a54SAlex Bligh     for (type = 0; type < QEMU_CLOCK_MAX; type++) {
639754d6a54SAlex Bligh         if (qemu_clock_use_for_deadline(tlg->tl[type]->clock)) {
640754d6a54SAlex Bligh             deadline = qemu_soonest_timeout(deadline,
641754d6a54SAlex Bligh                                             timerlist_deadline_ns(
642754d6a54SAlex Bligh                                                 tlg->tl[type]));
643754d6a54SAlex Bligh         }
644754d6a54SAlex Bligh     }
645754d6a54SAlex Bligh     return deadline;
646754d6a54SAlex Bligh }
647754d6a54SAlex Bligh 
648db1a4972SPaolo Bonzini int64_t qemu_get_clock_ns(QEMUClock *clock)
649db1a4972SPaolo Bonzini {
650691a0c9cSJan Kiszka     int64_t now, last;
651691a0c9cSJan Kiszka 
652db1a4972SPaolo Bonzini     switch(clock->type) {
653db1a4972SPaolo Bonzini     case QEMU_CLOCK_REALTIME:
654db1a4972SPaolo Bonzini         return get_clock();
655db1a4972SPaolo Bonzini     default:
656db1a4972SPaolo Bonzini     case QEMU_CLOCK_VIRTUAL:
657db1a4972SPaolo Bonzini         if (use_icount) {
658db1a4972SPaolo Bonzini             return cpu_get_icount();
659db1a4972SPaolo Bonzini         } else {
660db1a4972SPaolo Bonzini             return cpu_get_clock();
661db1a4972SPaolo Bonzini         }
662db1a4972SPaolo Bonzini     case QEMU_CLOCK_HOST:
663691a0c9cSJan Kiszka         now = get_clock_realtime();
664691a0c9cSJan Kiszka         last = clock->last;
665691a0c9cSJan Kiszka         clock->last = now;
666691a0c9cSJan Kiszka         if (now < last) {
667691a0c9cSJan Kiszka             notifier_list_notify(&clock->reset_notifiers, &now);
668db1a4972SPaolo Bonzini         }
669691a0c9cSJan Kiszka         return now;
670691a0c9cSJan Kiszka     }
671691a0c9cSJan Kiszka }
672691a0c9cSJan Kiszka 
673691a0c9cSJan Kiszka void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
674691a0c9cSJan Kiszka {
675691a0c9cSJan Kiszka     notifier_list_add(&clock->reset_notifiers, notifier);
676691a0c9cSJan Kiszka }
677691a0c9cSJan Kiszka 
678691a0c9cSJan Kiszka void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
679691a0c9cSJan Kiszka {
68031552529SPaolo Bonzini     notifier_remove(notifier);
681db1a4972SPaolo Bonzini }
682db1a4972SPaolo Bonzini 
683db1a4972SPaolo Bonzini void init_clocks(void)
684db1a4972SPaolo Bonzini {
685ff83c66eSAlex Bligh     QEMUClockType type;
686ff83c66eSAlex Bligh     for (type = 0; type < QEMU_CLOCK_MAX; type++) {
687ff83c66eSAlex Bligh         if (!qemu_clocks[type]) {
688ff83c66eSAlex Bligh             qemu_clocks[type] = qemu_clock_new(type);
689754d6a54SAlex Bligh             main_loop_tlg.tl[type] = qemu_clocks[type]->main_loop_timerlist;
690db1a4972SPaolo Bonzini         }
691ff83c66eSAlex Bligh     }
692ff83c66eSAlex Bligh 
693cd758dd0SAlex Bligh #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
694cd758dd0SAlex Bligh     prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
695cd758dd0SAlex Bligh #endif
696744ca8e3SPaolo Bonzini }
697db1a4972SPaolo Bonzini 
698e93379b0SAlex Bligh uint64_t timer_expire_time_ns(QEMUTimer *ts)
699db1a4972SPaolo Bonzini {
700e93379b0SAlex Bligh     return timer_pending(ts) ? ts->expire_time : -1;
701db1a4972SPaolo Bonzini }
702db1a4972SPaolo Bonzini 
703f9a976b7SAlex Bligh bool qemu_run_all_timers(void)
704db1a4972SPaolo Bonzini {
705f9a976b7SAlex Bligh     bool progress = false;
7065e1ec7b2SStefan Weil     alarm_timer->pending = false;
707ca5a2a4bSPaolo Bonzini 
708158fd3ceSPeter Portante     /* vm time timers */
709ff83c66eSAlex Bligh     QEMUClockType type;
710ff83c66eSAlex Bligh     for (type = 0; type < QEMU_CLOCK_MAX; type++) {
711ff83c66eSAlex Bligh         progress |= qemu_run_timers(qemu_clock_ptr(type));
712ff83c66eSAlex Bligh     }
713158fd3ceSPeter Portante 
714db1a4972SPaolo Bonzini     /* rearm timer, if not periodic */
715db1a4972SPaolo Bonzini     if (alarm_timer->expired) {
7165e1ec7b2SStefan Weil         alarm_timer->expired = false;
717db1a4972SPaolo Bonzini         qemu_rearm_alarm_timer(alarm_timer);
718db1a4972SPaolo Bonzini     }
719f9a976b7SAlex Bligh 
720f9a976b7SAlex Bligh     return progress;
721db1a4972SPaolo Bonzini }
722db1a4972SPaolo Bonzini 
723db1a4972SPaolo Bonzini #ifdef _WIN32
72468c23e55SPaolo Bonzini static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
725db1a4972SPaolo Bonzini #else
726db1a4972SPaolo Bonzini static void host_alarm_handler(int host_signum)
727db1a4972SPaolo Bonzini #endif
728db1a4972SPaolo Bonzini {
729db1a4972SPaolo Bonzini     struct qemu_alarm_timer *t = alarm_timer;
730db1a4972SPaolo Bonzini     if (!t)
731db1a4972SPaolo Bonzini 	return;
732db1a4972SPaolo Bonzini 
7338205199dSStefan Weil     t->expired = true;
7345e1ec7b2SStefan Weil     t->pending = true;
735db1a4972SPaolo Bonzini     qemu_notify_event();
736db1a4972SPaolo Bonzini }
737db1a4972SPaolo Bonzini 
7384c3d45ebSPaolo Bonzini #if defined(__linux__)
7394c3d45ebSPaolo Bonzini 
7401de7afc9SPaolo Bonzini #include "qemu/compatfd.h"
741d25f89c9SJan Kiszka 
742db1a4972SPaolo Bonzini static int dynticks_start_timer(struct qemu_alarm_timer *t)
743db1a4972SPaolo Bonzini {
744db1a4972SPaolo Bonzini     struct sigevent ev;
745db1a4972SPaolo Bonzini     timer_t host_timer;
746db1a4972SPaolo Bonzini     struct sigaction act;
747db1a4972SPaolo Bonzini 
748db1a4972SPaolo Bonzini     sigfillset(&act.sa_mask);
749db1a4972SPaolo Bonzini     act.sa_flags = 0;
750db1a4972SPaolo Bonzini     act.sa_handler = host_alarm_handler;
751db1a4972SPaolo Bonzini 
752db1a4972SPaolo Bonzini     sigaction(SIGALRM, &act, NULL);
753db1a4972SPaolo Bonzini 
754db1a4972SPaolo Bonzini     /*
755db1a4972SPaolo Bonzini      * Initialize ev struct to 0 to avoid valgrind complaining
756db1a4972SPaolo Bonzini      * about uninitialized data in timer_create call
757db1a4972SPaolo Bonzini      */
758db1a4972SPaolo Bonzini     memset(&ev, 0, sizeof(ev));
759db1a4972SPaolo Bonzini     ev.sigev_value.sival_int = 0;
760db1a4972SPaolo Bonzini     ev.sigev_notify = SIGEV_SIGNAL;
7611e9737daSRichard Henderson #ifdef CONFIG_SIGEV_THREAD_ID
762d25f89c9SJan Kiszka     if (qemu_signalfd_available()) {
763d25f89c9SJan Kiszka         ev.sigev_notify = SIGEV_THREAD_ID;
764d25f89c9SJan Kiszka         ev._sigev_un._tid = qemu_get_thread_id();
765d25f89c9SJan Kiszka     }
7661e9737daSRichard Henderson #endif /* CONFIG_SIGEV_THREAD_ID */
767db1a4972SPaolo Bonzini     ev.sigev_signo = SIGALRM;
768db1a4972SPaolo Bonzini 
769db1a4972SPaolo Bonzini     if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
770db1a4972SPaolo Bonzini         perror("timer_create");
771db1a4972SPaolo Bonzini         return -1;
772db1a4972SPaolo Bonzini     }
773db1a4972SPaolo Bonzini 
774cd0544eeSStefan Weil     t->timer = host_timer;
775db1a4972SPaolo Bonzini 
776db1a4972SPaolo Bonzini     return 0;
777db1a4972SPaolo Bonzini }
778db1a4972SPaolo Bonzini 
779db1a4972SPaolo Bonzini static void dynticks_stop_timer(struct qemu_alarm_timer *t)
780db1a4972SPaolo Bonzini {
781cd0544eeSStefan Weil     timer_t host_timer = t->timer;
782db1a4972SPaolo Bonzini 
783db1a4972SPaolo Bonzini     timer_delete(host_timer);
784db1a4972SPaolo Bonzini }
785db1a4972SPaolo Bonzini 
786f3fc6e2eSPaolo Bonzini static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
787f3fc6e2eSPaolo Bonzini                                  int64_t nearest_delta_ns)
788db1a4972SPaolo Bonzini {
789cd0544eeSStefan Weil     timer_t host_timer = t->timer;
790db1a4972SPaolo Bonzini     struct itimerspec timeout;
7919c13246aSPaolo Bonzini     int64_t current_ns;
792db1a4972SPaolo Bonzini 
7934c3d45ebSPaolo Bonzini     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
7944c3d45ebSPaolo Bonzini         nearest_delta_ns = MIN_TIMER_REARM_NS;
795db1a4972SPaolo Bonzini 
796db1a4972SPaolo Bonzini     /* check whether a timer is already running */
797db1a4972SPaolo Bonzini     if (timer_gettime(host_timer, &timeout)) {
798db1a4972SPaolo Bonzini         perror("gettime");
799db1a4972SPaolo Bonzini         fprintf(stderr, "Internal timer error: aborting\n");
800db1a4972SPaolo Bonzini         exit(1);
801db1a4972SPaolo Bonzini     }
8029c13246aSPaolo Bonzini     current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
8039c13246aSPaolo Bonzini     if (current_ns && current_ns <= nearest_delta_ns)
804db1a4972SPaolo Bonzini         return;
805db1a4972SPaolo Bonzini 
806db1a4972SPaolo Bonzini     timeout.it_interval.tv_sec = 0;
807db1a4972SPaolo Bonzini     timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
8089c13246aSPaolo Bonzini     timeout.it_value.tv_sec =  nearest_delta_ns / 1000000000;
8099c13246aSPaolo Bonzini     timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
810db1a4972SPaolo Bonzini     if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
811db1a4972SPaolo Bonzini         perror("settime");
812db1a4972SPaolo Bonzini         fprintf(stderr, "Internal timer error: aborting\n");
813db1a4972SPaolo Bonzini         exit(1);
814db1a4972SPaolo Bonzini     }
815db1a4972SPaolo Bonzini }
816db1a4972SPaolo Bonzini 
817db1a4972SPaolo Bonzini #endif /* defined(__linux__) */
818db1a4972SPaolo Bonzini 
819f26e5a54SStefan Weil #if !defined(_WIN32)
820f26e5a54SStefan Weil 
821db1a4972SPaolo Bonzini static int unix_start_timer(struct qemu_alarm_timer *t)
822db1a4972SPaolo Bonzini {
823db1a4972SPaolo Bonzini     struct sigaction act;
824db1a4972SPaolo Bonzini 
825db1a4972SPaolo Bonzini     /* timer signal */
826db1a4972SPaolo Bonzini     sigfillset(&act.sa_mask);
827db1a4972SPaolo Bonzini     act.sa_flags = 0;
828db1a4972SPaolo Bonzini     act.sa_handler = host_alarm_handler;
829db1a4972SPaolo Bonzini 
830db1a4972SPaolo Bonzini     sigaction(SIGALRM, &act, NULL);
83184682834SPaolo Bonzini     return 0;
83284682834SPaolo Bonzini }
83384682834SPaolo Bonzini 
834f3fc6e2eSPaolo Bonzini static void unix_rearm_timer(struct qemu_alarm_timer *t,
835f3fc6e2eSPaolo Bonzini                              int64_t nearest_delta_ns)
83684682834SPaolo Bonzini {
83784682834SPaolo Bonzini     struct itimerval itv;
83884682834SPaolo Bonzini     int err;
83984682834SPaolo Bonzini 
84084682834SPaolo Bonzini     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
84184682834SPaolo Bonzini         nearest_delta_ns = MIN_TIMER_REARM_NS;
842db1a4972SPaolo Bonzini 
843db1a4972SPaolo Bonzini     itv.it_interval.tv_sec = 0;
84484682834SPaolo Bonzini     itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
84584682834SPaolo Bonzini     itv.it_value.tv_sec =  nearest_delta_ns / 1000000000;
84684682834SPaolo Bonzini     itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
847db1a4972SPaolo Bonzini     err = setitimer(ITIMER_REAL, &itv, NULL);
84884682834SPaolo Bonzini     if (err) {
84984682834SPaolo Bonzini         perror("setitimer");
85084682834SPaolo Bonzini         fprintf(stderr, "Internal timer error: aborting\n");
85184682834SPaolo Bonzini         exit(1);
85284682834SPaolo Bonzini     }
853db1a4972SPaolo Bonzini }
854db1a4972SPaolo Bonzini 
855db1a4972SPaolo Bonzini static void unix_stop_timer(struct qemu_alarm_timer *t)
856db1a4972SPaolo Bonzini {
857db1a4972SPaolo Bonzini     struct itimerval itv;
858db1a4972SPaolo Bonzini 
859db1a4972SPaolo Bonzini     memset(&itv, 0, sizeof(itv));
860db1a4972SPaolo Bonzini     setitimer(ITIMER_REAL, &itv, NULL);
861db1a4972SPaolo Bonzini }
862db1a4972SPaolo Bonzini 
863db1a4972SPaolo Bonzini #endif /* !defined(_WIN32) */
864db1a4972SPaolo Bonzini 
865db1a4972SPaolo Bonzini 
866db1a4972SPaolo Bonzini #ifdef _WIN32
867db1a4972SPaolo Bonzini 
8682f9cba0cSStefan Weil static MMRESULT mm_timer;
86940f08e87SStefan Weil static TIMECAPS mm_tc;
8702f9cba0cSStefan Weil 
8712f9cba0cSStefan Weil static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
8722f9cba0cSStefan Weil                                       DWORD_PTR dwUser, DWORD_PTR dw1,
8732f9cba0cSStefan Weil                                       DWORD_PTR dw2)
8742f9cba0cSStefan Weil {
8752f9cba0cSStefan Weil     struct qemu_alarm_timer *t = alarm_timer;
8762f9cba0cSStefan Weil     if (!t) {
8772f9cba0cSStefan Weil         return;
8782f9cba0cSStefan Weil     }
8798205199dSStefan Weil     t->expired = true;
8805e1ec7b2SStefan Weil     t->pending = true;
8812f9cba0cSStefan Weil     qemu_notify_event();
8822f9cba0cSStefan Weil }
8832f9cba0cSStefan Weil 
8842f9cba0cSStefan Weil static int mm_start_timer(struct qemu_alarm_timer *t)
8852f9cba0cSStefan Weil {
88640f08e87SStefan Weil     timeGetDevCaps(&mm_tc, sizeof(mm_tc));
8872f9cba0cSStefan Weil     return 0;
8882f9cba0cSStefan Weil }
8892f9cba0cSStefan Weil 
8902f9cba0cSStefan Weil static void mm_stop_timer(struct qemu_alarm_timer *t)
8912f9cba0cSStefan Weil {
8920727b867SPaolo Bonzini     if (mm_timer) {
8932f9cba0cSStefan Weil         timeKillEvent(mm_timer);
8940727b867SPaolo Bonzini     }
8952f9cba0cSStefan Weil }
8962f9cba0cSStefan Weil 
897f3fc6e2eSPaolo Bonzini static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
8982f9cba0cSStefan Weil {
8995bfb723fSStefano Stabellini     int64_t nearest_delta_ms = delta / 1000000;
90040f08e87SStefan Weil     if (nearest_delta_ms < mm_tc.wPeriodMin) {
90140f08e87SStefan Weil         nearest_delta_ms = mm_tc.wPeriodMin;
90240f08e87SStefan Weil     } else if (nearest_delta_ms > mm_tc.wPeriodMax) {
90340f08e87SStefan Weil         nearest_delta_ms = mm_tc.wPeriodMax;
9045bfb723fSStefano Stabellini     }
905f3fc6e2eSPaolo Bonzini 
9060727b867SPaolo Bonzini     if (mm_timer) {
907f3fc6e2eSPaolo Bonzini         timeKillEvent(mm_timer);
9080727b867SPaolo Bonzini     }
90940f08e87SStefan Weil     mm_timer = timeSetEvent((UINT)nearest_delta_ms,
91040f08e87SStefan Weil                             mm_tc.wPeriodMin,
9112f9cba0cSStefan Weil                             mm_alarm_handler,
9122f9cba0cSStefan Weil                             (DWORD_PTR)t,
9132f9cba0cSStefan Weil                             TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
9142f9cba0cSStefan Weil 
9152f9cba0cSStefan Weil     if (!mm_timer) {
91652ef651fSStefan Weil         fprintf(stderr, "Failed to re-arm win32 alarm timer\n");
91740f08e87SStefan Weil         timeEndPeriod(mm_tc.wPeriodMin);
9182f9cba0cSStefan Weil         exit(1);
9192f9cba0cSStefan Weil     }
9202f9cba0cSStefan Weil }
9212f9cba0cSStefan Weil 
922db1a4972SPaolo Bonzini static int win32_start_timer(struct qemu_alarm_timer *t)
923db1a4972SPaolo Bonzini {
92468c23e55SPaolo Bonzini     HANDLE hTimer;
92568c23e55SPaolo Bonzini     BOOLEAN success;
926db1a4972SPaolo Bonzini 
92768c23e55SPaolo Bonzini     /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
92868c23e55SPaolo Bonzini        is zero) that has already expired, the timer is not updated.  Since
92968c23e55SPaolo Bonzini        creating a new timer is relatively expensive, set a bogus one-hour
93068c23e55SPaolo Bonzini        interval in the dynticks case.  */
93168c23e55SPaolo Bonzini     success = CreateTimerQueueTimer(&hTimer,
93268c23e55SPaolo Bonzini                           NULL,
93368c23e55SPaolo Bonzini                           host_alarm_handler,
93468c23e55SPaolo Bonzini                           t,
93568c23e55SPaolo Bonzini                           1,
9368205199dSStefan Weil                           3600000,
93768c23e55SPaolo Bonzini                           WT_EXECUTEINTIMERTHREAD);
938db1a4972SPaolo Bonzini 
93968c23e55SPaolo Bonzini     if (!success) {
940db1a4972SPaolo Bonzini         fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
941db1a4972SPaolo Bonzini                 GetLastError());
942db1a4972SPaolo Bonzini         return -1;
943db1a4972SPaolo Bonzini     }
944db1a4972SPaolo Bonzini 
945cd0544eeSStefan Weil     t->timer = hTimer;
946db1a4972SPaolo Bonzini     return 0;
947db1a4972SPaolo Bonzini }
948db1a4972SPaolo Bonzini 
949db1a4972SPaolo Bonzini static void win32_stop_timer(struct qemu_alarm_timer *t)
950db1a4972SPaolo Bonzini {
951cd0544eeSStefan Weil     HANDLE hTimer = t->timer;
952db1a4972SPaolo Bonzini 
95368c23e55SPaolo Bonzini     if (hTimer) {
95468c23e55SPaolo Bonzini         DeleteTimerQueueTimer(NULL, hTimer, NULL);
95568c23e55SPaolo Bonzini     }
956db1a4972SPaolo Bonzini }
957db1a4972SPaolo Bonzini 
958f3fc6e2eSPaolo Bonzini static void win32_rearm_timer(struct qemu_alarm_timer *t,
959f3fc6e2eSPaolo Bonzini                               int64_t nearest_delta_ns)
960db1a4972SPaolo Bonzini {
961cd0544eeSStefan Weil     HANDLE hTimer = t->timer;
9625bfb723fSStefano Stabellini     int64_t nearest_delta_ms;
96368c23e55SPaolo Bonzini     BOOLEAN success;
964db1a4972SPaolo Bonzini 
9655bfb723fSStefano Stabellini     nearest_delta_ms = nearest_delta_ns / 1000000;
966cfced5b2SPaolo Bonzini     if (nearest_delta_ms < 1) {
967cfced5b2SPaolo Bonzini         nearest_delta_ms = 1;
968cfced5b2SPaolo Bonzini     }
9695bfb723fSStefano Stabellini     /* ULONG_MAX can be 32 bit */
9705bfb723fSStefano Stabellini     if (nearest_delta_ms > ULONG_MAX) {
9715bfb723fSStefano Stabellini         nearest_delta_ms = ULONG_MAX;
9725bfb723fSStefano Stabellini     }
97368c23e55SPaolo Bonzini     success = ChangeTimerQueueTimer(NULL,
97468c23e55SPaolo Bonzini                                     hTimer,
9755bfb723fSStefano Stabellini                                     (unsigned long) nearest_delta_ms,
97668c23e55SPaolo Bonzini                                     3600000);
977db1a4972SPaolo Bonzini 
97868c23e55SPaolo Bonzini     if (!success) {
97968c23e55SPaolo Bonzini         fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
980db1a4972SPaolo Bonzini                 GetLastError());
98168c23e55SPaolo Bonzini         exit(-1);
982db1a4972SPaolo Bonzini     }
98368c23e55SPaolo Bonzini 
984db1a4972SPaolo Bonzini }
985db1a4972SPaolo Bonzini 
986db1a4972SPaolo Bonzini #endif /* _WIN32 */
987db1a4972SPaolo Bonzini 
9884260a739SPaolo Bonzini static void quit_timers(void)
9894260a739SPaolo Bonzini {
9904260a739SPaolo Bonzini     struct qemu_alarm_timer *t = alarm_timer;
9914260a739SPaolo Bonzini     alarm_timer = NULL;
9924260a739SPaolo Bonzini     t->stop(t);
9934260a739SPaolo Bonzini }
9944260a739SPaolo Bonzini 
995253ecf83SStefan Weil #ifdef CONFIG_POSIX
996c8122c35SPaolo Bonzini static void reinit_timers(void)
997c8122c35SPaolo Bonzini {
998c8122c35SPaolo Bonzini     struct qemu_alarm_timer *t = alarm_timer;
999c8122c35SPaolo Bonzini     t->stop(t);
1000c8122c35SPaolo Bonzini     if (t->start(t)) {
1001c8122c35SPaolo Bonzini         fprintf(stderr, "Internal timer error: aborting\n");
1002c8122c35SPaolo Bonzini         exit(1);
1003c8122c35SPaolo Bonzini     }
1004c8122c35SPaolo Bonzini     qemu_rearm_alarm_timer(t);
1005c8122c35SPaolo Bonzini }
1006253ecf83SStefan Weil #endif /* CONFIG_POSIX */
1007c8122c35SPaolo Bonzini 
1008db1a4972SPaolo Bonzini int init_timer_alarm(void)
1009db1a4972SPaolo Bonzini {
1010db1a4972SPaolo Bonzini     struct qemu_alarm_timer *t = NULL;
1011db1a4972SPaolo Bonzini     int i, err = -1;
1012db1a4972SPaolo Bonzini 
1013744ca8e3SPaolo Bonzini     if (alarm_timer) {
1014744ca8e3SPaolo Bonzini         return 0;
1015744ca8e3SPaolo Bonzini     }
1016744ca8e3SPaolo Bonzini 
1017db1a4972SPaolo Bonzini     for (i = 0; alarm_timers[i].name; i++) {
1018db1a4972SPaolo Bonzini         t = &alarm_timers[i];
1019db1a4972SPaolo Bonzini 
1020db1a4972SPaolo Bonzini         err = t->start(t);
1021db1a4972SPaolo Bonzini         if (!err)
1022db1a4972SPaolo Bonzini             break;
1023db1a4972SPaolo Bonzini     }
1024db1a4972SPaolo Bonzini 
1025db1a4972SPaolo Bonzini     if (err) {
1026db1a4972SPaolo Bonzini         err = -ENOENT;
1027db1a4972SPaolo Bonzini         goto fail;
1028db1a4972SPaolo Bonzini     }
1029db1a4972SPaolo Bonzini 
10304260a739SPaolo Bonzini     atexit(quit_timers);
1031c8122c35SPaolo Bonzini #ifdef CONFIG_POSIX
1032c8122c35SPaolo Bonzini     pthread_atfork(NULL, NULL, reinit_timers);
1033c8122c35SPaolo Bonzini #endif
1034db1a4972SPaolo Bonzini     alarm_timer = t;
1035db1a4972SPaolo Bonzini     return 0;
1036db1a4972SPaolo Bonzini 
1037db1a4972SPaolo Bonzini fail:
1038db1a4972SPaolo Bonzini     return err;
1039db1a4972SPaolo Bonzini }
1040db1a4972SPaolo Bonzini 
1041