1 /*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25 #include "qemu/osdep.h"
26 #include "qemu/main-loop.h"
27 #include "qemu/timer.h"
28 #include "qemu/lockable.h"
29 #include "system/cpu-timers.h"
30 #include "exec/icount.h"
31 #include "system/replay.h"
32 #include "system/cpus.h"
33
34 #ifdef CONFIG_POSIX
35 #include <pthread.h>
36 #endif
37
38 #ifdef CONFIG_PPOLL
39 #include <poll.h>
40 #endif
41
42 #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
43 #include <sys/prctl.h>
44 #endif
45
46 /***********************************************************/
47 /* timers */
48
49 typedef struct QEMUClock {
50 /* We rely on BQL to protect the timerlists */
51 QLIST_HEAD(, QEMUTimerList) timerlists;
52
53 QEMUClockType type;
54 bool enabled;
55 } QEMUClock;
56
57 QEMUTimerListGroup main_loop_tlg;
58 static QEMUClock qemu_clocks[QEMU_CLOCK_MAX];
59
60 /* A QEMUTimerList is a list of timers attached to a clock. More
61 * than one QEMUTimerList can be attached to each clock, for instance
62 * used by different AioContexts / threads. Each clock also has
63 * a list of the QEMUTimerLists associated with it, in order that
64 * reenabling the clock can call all the notifiers.
65 */
66
67 struct QEMUTimerList {
68 QEMUClock *clock;
69 QemuMutex active_timers_lock;
70 QEMUTimer *active_timers;
71 QLIST_ENTRY(QEMUTimerList) list;
72 QEMUTimerListNotifyCB *notify_cb;
73 void *notify_opaque;
74
75 /* lightweight method to mark the end of timerlist's running */
76 QemuEvent timers_done_ev;
77 };
78
79 /**
80 * qemu_clock_ptr:
81 * @type: type of clock
82 *
83 * Translate a clock type into a pointer to QEMUClock object.
84 *
85 * Returns: a pointer to the QEMUClock object
86 */
qemu_clock_ptr(QEMUClockType type)87 static inline QEMUClock *qemu_clock_ptr(QEMUClockType type)
88 {
89 return &qemu_clocks[type];
90 }
91
timer_expired_ns(QEMUTimer * timer_head,int64_t current_time)92 static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
93 {
94 return timer_head && (timer_head->expire_time <= current_time);
95 }
96
timerlist_new(QEMUClockType type,QEMUTimerListNotifyCB * cb,void * opaque)97 QEMUTimerList *timerlist_new(QEMUClockType type,
98 QEMUTimerListNotifyCB *cb,
99 void *opaque)
100 {
101 QEMUTimerList *timer_list;
102 QEMUClock *clock = qemu_clock_ptr(type);
103
104 timer_list = g_new0(QEMUTimerList, 1);
105 qemu_event_init(&timer_list->timers_done_ev, true);
106 timer_list->clock = clock;
107 timer_list->notify_cb = cb;
108 timer_list->notify_opaque = opaque;
109 qemu_mutex_init(&timer_list->active_timers_lock);
110 QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
111 return timer_list;
112 }
113
timerlist_free(QEMUTimerList * timer_list)114 void timerlist_free(QEMUTimerList *timer_list)
115 {
116 assert(!timerlist_has_timers(timer_list));
117 if (timer_list->clock) {
118 QLIST_REMOVE(timer_list, list);
119 }
120 qemu_mutex_destroy(&timer_list->active_timers_lock);
121 g_free(timer_list);
122 }
123
qemu_clock_init(QEMUClockType type,QEMUTimerListNotifyCB * notify_cb)124 static void qemu_clock_init(QEMUClockType type, QEMUTimerListNotifyCB *notify_cb)
125 {
126 QEMUClock *clock = qemu_clock_ptr(type);
127
128 /* Assert that the clock of type TYPE has not been initialized yet. */
129 assert(main_loop_tlg.tl[type] == NULL);
130
131 clock->type = type;
132 clock->enabled = (type == QEMU_CLOCK_VIRTUAL ? false : true);
133 QLIST_INIT(&clock->timerlists);
134 main_loop_tlg.tl[type] = timerlist_new(type, notify_cb, NULL);
135 }
136
qemu_clock_use_for_deadline(QEMUClockType type)137 bool qemu_clock_use_for_deadline(QEMUClockType type)
138 {
139 return !(icount_enabled() && (type == QEMU_CLOCK_VIRTUAL));
140 }
141
qemu_clock_notify(QEMUClockType type)142 void qemu_clock_notify(QEMUClockType type)
143 {
144 QEMUTimerList *timer_list;
145 QEMUClock *clock = qemu_clock_ptr(type);
146 QLIST_FOREACH(timer_list, &clock->timerlists, list) {
147 timerlist_notify(timer_list);
148 }
149 }
150
151 /* Disabling the clock will wait for related timerlists to stop
152 * executing qemu_run_timers. Thus, this functions should not
153 * be used from the callback of a timer that is based on @clock.
154 * Doing so would cause a deadlock.
155 *
156 * Caller should hold BQL.
157 */
qemu_clock_enable(QEMUClockType type,bool enabled)158 void qemu_clock_enable(QEMUClockType type, bool enabled)
159 {
160 QEMUClock *clock = qemu_clock_ptr(type);
161 QEMUTimerList *tl;
162 bool old = clock->enabled;
163 clock->enabled = enabled;
164 if (enabled && !old) {
165 qemu_clock_notify(type);
166 } else if (!enabled && old) {
167 QLIST_FOREACH(tl, &clock->timerlists, list) {
168 qemu_event_wait(&tl->timers_done_ev);
169 }
170 }
171 }
172
timerlist_has_timers(QEMUTimerList * timer_list)173 bool timerlist_has_timers(QEMUTimerList *timer_list)
174 {
175 return !!qatomic_read(&timer_list->active_timers);
176 }
177
qemu_clock_has_timers(QEMUClockType type)178 bool qemu_clock_has_timers(QEMUClockType type)
179 {
180 return timerlist_has_timers(
181 main_loop_tlg.tl[type]);
182 }
183
timerlist_expired(QEMUTimerList * timer_list)184 bool timerlist_expired(QEMUTimerList *timer_list)
185 {
186 int64_t expire_time = 0;
187
188 if (!qatomic_read(&timer_list->active_timers)) {
189 return false;
190 }
191
192 WITH_QEMU_LOCK_GUARD(&timer_list->active_timers_lock) {
193 if (!timer_list->active_timers) {
194 return false;
195 }
196 expire_time = timer_list->active_timers->expire_time;
197 }
198
199 return expire_time <= qemu_clock_get_ns(timer_list->clock->type);
200 }
201
qemu_clock_expired(QEMUClockType type)202 bool qemu_clock_expired(QEMUClockType type)
203 {
204 return timerlist_expired(
205 main_loop_tlg.tl[type]);
206 }
207
208 /*
209 * As above, but return -1 for no deadline, and do not cap to 2^32
210 * as we know the result is always positive.
211 */
212
timerlist_deadline_ns(QEMUTimerList * timer_list)213 int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
214 {
215 int64_t delta;
216 int64_t expire_time = 0;
217
218 if (!qatomic_read(&timer_list->active_timers)) {
219 return -1;
220 }
221
222 if (!timer_list->clock->enabled) {
223 return -1;
224 }
225
226 /* The active timers list may be modified before the caller uses our return
227 * value but ->notify_cb() is called when the deadline changes. Therefore
228 * the caller should notice the change and there is no race condition.
229 */
230 WITH_QEMU_LOCK_GUARD(&timer_list->active_timers_lock) {
231 if (!timer_list->active_timers) {
232 return -1;
233 }
234 expire_time = timer_list->active_timers->expire_time;
235 }
236
237 delta = expire_time - qemu_clock_get_ns(timer_list->clock->type);
238
239 if (delta <= 0) {
240 return 0;
241 }
242
243 return delta;
244 }
245
246 /* Calculate the soonest deadline across all timerlists attached
247 * to the clock. This is used for the icount timeout so we
248 * ignore whether or not the clock should be used in deadline
249 * calculations.
250 */
qemu_clock_deadline_ns_all(QEMUClockType type,int attr_mask)251 int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask)
252 {
253 int64_t deadline = -1;
254 int64_t delta;
255 int64_t expire_time;
256 QEMUTimer *ts;
257 QEMUTimerList *timer_list;
258 QEMUClock *clock = qemu_clock_ptr(type);
259
260 if (!clock->enabled) {
261 return -1;
262 }
263
264 QLIST_FOREACH(timer_list, &clock->timerlists, list) {
265 if (!qatomic_read(&timer_list->active_timers)) {
266 continue;
267 }
268 qemu_mutex_lock(&timer_list->active_timers_lock);
269 ts = timer_list->active_timers;
270 /* Skip all external timers */
271 while (ts && (ts->attributes & ~attr_mask)) {
272 ts = ts->next;
273 }
274 if (!ts) {
275 qemu_mutex_unlock(&timer_list->active_timers_lock);
276 continue;
277 }
278 expire_time = ts->expire_time;
279 qemu_mutex_unlock(&timer_list->active_timers_lock);
280
281 delta = expire_time - qemu_clock_get_ns(type);
282 if (delta <= 0) {
283 delta = 0;
284 }
285 deadline = qemu_soonest_timeout(deadline, delta);
286 }
287 return deadline;
288 }
289
timerlist_notify(QEMUTimerList * timer_list)290 void timerlist_notify(QEMUTimerList *timer_list)
291 {
292 if (timer_list->notify_cb) {
293 timer_list->notify_cb(timer_list->notify_opaque, timer_list->clock->type);
294 } else {
295 qemu_notify_event();
296 }
297 }
298
299 /* Transition function to convert a nanosecond timeout to ms
300 * This is used where a system does not support ppoll
301 */
qemu_timeout_ns_to_ms(int64_t ns)302 int qemu_timeout_ns_to_ms(int64_t ns)
303 {
304 int64_t ms;
305 if (ns < 0) {
306 return -1;
307 }
308
309 if (!ns) {
310 return 0;
311 }
312
313 /* Always round up, because it's better to wait too long than to wait too
314 * little and effectively busy-wait
315 */
316 ms = DIV_ROUND_UP(ns, SCALE_MS);
317
318 /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
319 return MIN(ms, INT32_MAX);
320 }
321
322
323 /* qemu implementation of g_poll which uses a nanosecond timeout but is
324 * otherwise identical to g_poll
325 */
qemu_poll_ns(GPollFD * fds,guint nfds,int64_t timeout)326 int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout)
327 {
328 #ifdef CONFIG_PPOLL
329 if (timeout < 0) {
330 return ppoll((struct pollfd *)fds, nfds, NULL, NULL);
331 } else {
332 struct timespec ts;
333 int64_t tvsec = timeout / 1000000000LL;
334 /* Avoid possibly overflowing and specifying a negative number of
335 * seconds, which would turn a very long timeout into a busy-wait.
336 */
337 if (tvsec > (int64_t)INT32_MAX) {
338 tvsec = INT32_MAX;
339 }
340 ts.tv_sec = tvsec;
341 ts.tv_nsec = timeout % 1000000000LL;
342 return ppoll((struct pollfd *)fds, nfds, &ts, NULL);
343 }
344 #else
345 return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout));
346 #endif
347 }
348
349
timer_init_full(QEMUTimer * ts,QEMUTimerListGroup * timer_list_group,QEMUClockType type,int scale,int attributes,QEMUTimerCB * cb,void * opaque)350 void timer_init_full(QEMUTimer *ts,
351 QEMUTimerListGroup *timer_list_group, QEMUClockType type,
352 int scale, int attributes,
353 QEMUTimerCB *cb, void *opaque)
354 {
355 if (!timer_list_group) {
356 timer_list_group = &main_loop_tlg;
357 }
358 ts->timer_list = timer_list_group->tl[type];
359 ts->cb = cb;
360 ts->opaque = opaque;
361 ts->scale = scale;
362 ts->attributes = attributes;
363 ts->expire_time = -1;
364 }
365
timer_deinit(QEMUTimer * ts)366 void timer_deinit(QEMUTimer *ts)
367 {
368 assert(ts->expire_time == -1);
369 ts->timer_list = NULL;
370 }
371
timer_del_locked(QEMUTimerList * timer_list,QEMUTimer * ts)372 static void timer_del_locked(QEMUTimerList *timer_list, QEMUTimer *ts)
373 {
374 QEMUTimer **pt, *t;
375
376 ts->expire_time = -1;
377 pt = &timer_list->active_timers;
378 for(;;) {
379 t = *pt;
380 if (!t)
381 break;
382 if (t == ts) {
383 qatomic_set(pt, t->next);
384 break;
385 }
386 pt = &t->next;
387 }
388 }
389
timer_mod_ns_locked(QEMUTimerList * timer_list,QEMUTimer * ts,int64_t expire_time)390 static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
391 QEMUTimer *ts, int64_t expire_time)
392 {
393 QEMUTimer **pt, *t;
394
395 /* add the timer in the sorted list */
396 pt = &timer_list->active_timers;
397 for (;;) {
398 t = *pt;
399 if (!timer_expired_ns(t, expire_time)) {
400 break;
401 }
402 pt = &t->next;
403 }
404 ts->expire_time = MAX(expire_time, 0);
405 ts->next = *pt;
406 qatomic_set(pt, ts);
407
408 return pt == &timer_list->active_timers;
409 }
410
timerlist_rearm(QEMUTimerList * timer_list)411 static void timerlist_rearm(QEMUTimerList *timer_list)
412 {
413 timerlist_notify(timer_list);
414 }
415
416 /* stop a timer, but do not dealloc it */
timer_del(QEMUTimer * ts)417 void timer_del(QEMUTimer *ts)
418 {
419 QEMUTimerList *timer_list = ts->timer_list;
420
421 if (timer_list) {
422 qemu_mutex_lock(&timer_list->active_timers_lock);
423 timer_del_locked(timer_list, ts);
424 qemu_mutex_unlock(&timer_list->active_timers_lock);
425 }
426 }
427
428 /* modify the current timer so that it will be fired when current_time
429 >= expire_time. The corresponding callback will be called. */
timer_mod_ns(QEMUTimer * ts,int64_t expire_time)430 void timer_mod_ns(QEMUTimer *ts, int64_t expire_time)
431 {
432 QEMUTimerList *timer_list = ts->timer_list;
433 bool rearm;
434
435 qemu_mutex_lock(&timer_list->active_timers_lock);
436 timer_del_locked(timer_list, ts);
437 rearm = timer_mod_ns_locked(timer_list, ts, expire_time);
438 qemu_mutex_unlock(&timer_list->active_timers_lock);
439
440 if (rearm) {
441 timerlist_rearm(timer_list);
442 }
443 }
444
445 /* modify the current timer so that it will be fired when current_time
446 >= expire_time or the current deadline, whichever comes earlier.
447 The corresponding callback will be called. */
timer_mod_anticipate_ns(QEMUTimer * ts,int64_t expire_time)448 void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time)
449 {
450 QEMUTimerList *timer_list = ts->timer_list;
451 bool rearm = false;
452
453 WITH_QEMU_LOCK_GUARD(&timer_list->active_timers_lock) {
454 if (ts->expire_time == -1 || ts->expire_time > expire_time) {
455 if (ts->expire_time != -1) {
456 timer_del_locked(timer_list, ts);
457 }
458 rearm = timer_mod_ns_locked(timer_list, ts, expire_time);
459 } else {
460 rearm = false;
461 }
462 }
463 if (rearm) {
464 timerlist_rearm(timer_list);
465 }
466 }
467
timer_mod(QEMUTimer * ts,int64_t expire_time)468 void timer_mod(QEMUTimer *ts, int64_t expire_time)
469 {
470 timer_mod_ns(ts, expire_time * ts->scale);
471 }
472
timer_mod_anticipate(QEMUTimer * ts,int64_t expire_time)473 void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time)
474 {
475 timer_mod_anticipate_ns(ts, expire_time * ts->scale);
476 }
477
timer_pending(QEMUTimer * ts)478 bool timer_pending(QEMUTimer *ts)
479 {
480 return ts->expire_time >= 0;
481 }
482
timer_expired(QEMUTimer * timer_head,int64_t current_time)483 bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
484 {
485 return timer_expired_ns(timer_head, current_time * timer_head->scale);
486 }
487
timerlist_run_timers(QEMUTimerList * timer_list)488 bool timerlist_run_timers(QEMUTimerList *timer_list)
489 {
490 QEMUTimer *ts;
491 int64_t current_time;
492 bool progress = false;
493 QEMUTimerCB *cb;
494 void *opaque;
495
496 if (!qatomic_read(&timer_list->active_timers)) {
497 return false;
498 }
499
500 qemu_event_reset(&timer_list->timers_done_ev);
501 if (!timer_list->clock->enabled) {
502 goto out;
503 }
504
505 switch (timer_list->clock->type) {
506 case QEMU_CLOCK_REALTIME:
507 break;
508 default:
509 case QEMU_CLOCK_VIRTUAL:
510 break;
511 case QEMU_CLOCK_HOST:
512 if (!replay_checkpoint(CHECKPOINT_CLOCK_HOST)) {
513 goto out;
514 }
515 break;
516 case QEMU_CLOCK_VIRTUAL_RT:
517 if (!replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL_RT)) {
518 goto out;
519 }
520 break;
521 }
522
523 /*
524 * Extract expired timers from active timers list and process them.
525 *
526 * In rr mode we need "filtered" checkpointing for virtual clock. The
527 * checkpoint must be recorded/replayed before processing any non-EXTERNAL timer,
528 * and that must only be done once since the clock value stays the same. Because
529 * non-EXTERNAL timers may appear in the timers list while it being processed,
530 * the checkpoint can be issued at a time until no timers are left and we are
531 * done".
532 */
533 current_time = qemu_clock_get_ns(timer_list->clock->type);
534 qemu_mutex_lock(&timer_list->active_timers_lock);
535 while ((ts = timer_list->active_timers)) {
536 if (!timer_expired_ns(ts, current_time)) {
537 /* No expired timers left. The checkpoint can be skipped
538 * if no timers fired or they were all external.
539 */
540 break;
541 }
542 /* Checkpoint for virtual clock is redundant in cases where
543 * it's being triggered with only non-EXTERNAL timers, because
544 * these timers don't change guest state directly.
545 */
546 if (replay_mode != REPLAY_MODE_NONE
547 && timer_list->clock->type == QEMU_CLOCK_VIRTUAL
548 && !(ts->attributes & QEMU_TIMER_ATTR_EXTERNAL)
549 && !replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL)) {
550 qemu_mutex_unlock(&timer_list->active_timers_lock);
551 goto out;
552 }
553
554 /* remove timer from the list before calling the callback */
555 timer_list->active_timers = ts->next;
556 ts->next = NULL;
557 ts->expire_time = -1;
558 cb = ts->cb;
559 opaque = ts->opaque;
560
561 /* run the callback (the timer list can be modified) */
562 qemu_mutex_unlock(&timer_list->active_timers_lock);
563 cb(opaque);
564 qemu_mutex_lock(&timer_list->active_timers_lock);
565
566 progress = true;
567 }
568 qemu_mutex_unlock(&timer_list->active_timers_lock);
569
570 out:
571 qemu_event_set(&timer_list->timers_done_ev);
572 return progress;
573 }
574
qemu_clock_run_timers(QEMUClockType type)575 bool qemu_clock_run_timers(QEMUClockType type)
576 {
577 return timerlist_run_timers(main_loop_tlg.tl[type]);
578 }
579
timerlistgroup_init(QEMUTimerListGroup * tlg,QEMUTimerListNotifyCB * cb,void * opaque)580 void timerlistgroup_init(QEMUTimerListGroup *tlg,
581 QEMUTimerListNotifyCB *cb, void *opaque)
582 {
583 QEMUClockType type;
584 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
585 tlg->tl[type] = timerlist_new(type, cb, opaque);
586 }
587 }
588
timerlistgroup_deinit(QEMUTimerListGroup * tlg)589 void timerlistgroup_deinit(QEMUTimerListGroup *tlg)
590 {
591 QEMUClockType type;
592 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
593 timerlist_free(tlg->tl[type]);
594 }
595 }
596
timerlistgroup_run_timers(QEMUTimerListGroup * tlg)597 bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg)
598 {
599 QEMUClockType type;
600 bool progress = false;
601 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
602 progress |= timerlist_run_timers(tlg->tl[type]);
603 }
604 return progress;
605 }
606
timerlistgroup_deadline_ns(QEMUTimerListGroup * tlg)607 int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg)
608 {
609 int64_t deadline = -1;
610 QEMUClockType type;
611 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
612 if (qemu_clock_use_for_deadline(type)) {
613 deadline = qemu_soonest_timeout(deadline,
614 timerlist_deadline_ns(tlg->tl[type]));
615 }
616 }
617 return deadline;
618 }
619
qemu_clock_get_ns(QEMUClockType type)620 int64_t qemu_clock_get_ns(QEMUClockType type)
621 {
622 switch (type) {
623 case QEMU_CLOCK_REALTIME:
624 return get_clock();
625 default:
626 case QEMU_CLOCK_VIRTUAL:
627 return cpus_get_virtual_clock();
628 case QEMU_CLOCK_HOST:
629 return REPLAY_CLOCK(REPLAY_CLOCK_HOST, get_clock_realtime());
630 case QEMU_CLOCK_VIRTUAL_RT:
631 return REPLAY_CLOCK(REPLAY_CLOCK_VIRTUAL_RT, cpu_get_clock());
632 }
633 }
634
qemu_virtual_clock_set_ns(int64_t time)635 static void qemu_virtual_clock_set_ns(int64_t time)
636 {
637 return cpus_set_virtual_clock(time);
638 }
639
init_clocks(QEMUTimerListNotifyCB * notify_cb)640 void init_clocks(QEMUTimerListNotifyCB *notify_cb)
641 {
642 QEMUClockType type;
643 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
644 qemu_clock_init(type, notify_cb);
645 }
646
647 #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
648 prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
649 #endif
650 }
651
timer_expire_time_ns(QEMUTimer * ts)652 uint64_t timer_expire_time_ns(QEMUTimer *ts)
653 {
654 return timer_pending(ts) ? ts->expire_time : -1;
655 }
656
qemu_clock_run_all_timers(void)657 bool qemu_clock_run_all_timers(void)
658 {
659 bool progress = false;
660 QEMUClockType type;
661
662 for (type = 0; type < QEMU_CLOCK_MAX; type++) {
663 if (qemu_clock_use_for_deadline(type)) {
664 progress |= qemu_clock_run_timers(type);
665 }
666 }
667
668 return progress;
669 }
670
qemu_clock_advance_virtual_time(int64_t dest)671 int64_t qemu_clock_advance_virtual_time(int64_t dest)
672 {
673 int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
674 AioContext *aio_context;
675 aio_context = qemu_get_aio_context();
676 while (clock < dest) {
677 int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
678 QEMU_TIMER_ATTR_ALL);
679 int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
680
681 qemu_virtual_clock_set_ns(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + warp);
682
683 qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
684 timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]);
685 clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
686 }
687 qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
688
689 return clock;
690 }
691