qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

qemu-timer.c (18809B)


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