qemu-timer.c 15.8 KB
Newer Older
Paolo Bonzini's avatar
Paolo Bonzini committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * QEMU System Emulator
 *
 * Copyright (c) 2003-2008 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

25
#include "sysemu/sysemu.h"
26
#include "monitor/monitor.h"
27
#include "ui/console.h"
Paolo Bonzini's avatar
Paolo Bonzini committed
28 29 30

#include "hw/hw.h"

31
#include "qemu/timer.h"
32 33 34
#ifdef CONFIG_POSIX
#include <pthread.h>
#endif
35

36 37 38 39
#ifdef CONFIG_PPOLL
#include <poll.h>
#endif

40 41 42 43
#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
#include <sys/prctl.h>
#endif

Paolo Bonzini's avatar
Paolo Bonzini committed
44 45 46
/***********************************************************/
/* timers */

47
typedef struct QEMUClock {
48
    /* We rely on BQL to protect the timerlists */
49
    QLIST_HEAD(, QEMUTimerList) timerlists;
50 51 52

    NotifierList reset_notifiers;
    int64_t last;
53

54
    QEMUClockType type;
55
    bool enabled;
56
} QEMUClock;
Paolo Bonzini's avatar
Paolo Bonzini committed
57

58
QEMUTimerListGroup main_loop_tlg;
59
static QEMUClock qemu_clocks[QEMU_CLOCK_MAX];
60 61 62 63 64 65 66 67 68

/* A QEMUTimerList is a list of timers attached to a clock. More
 * than one QEMUTimerList can be attached to each clock, for instance
 * used by different AioContexts / threads. Each clock also has
 * a list of the QEMUTimerLists associated with it, in order that
 * reenabling the clock can call all the notifiers.
 */

struct QEMUTimerList {
69
    QEMUClock *clock;
70
    QemuMutex active_timers_lock;
71 72
    QEMUTimer *active_timers;
    QLIST_ENTRY(QEMUTimerList) list;
73 74
    QEMUTimerListNotifyCB *notify_cb;
    void *notify_opaque;
75 76 77

    /* lightweight method to mark the end of timerlist's running */
    QemuEvent timers_done_ev;
Paolo Bonzini's avatar
Paolo Bonzini committed
78 79
};

80 81 82 83 84 85 86 87
/**
 * qemu_clock_ptr:
 * @type: type of clock
 *
 * Translate a clock type into a pointer to QEMUClock object.
 *
 * Returns: a pointer to the QEMUClock object
 */
88
static inline QEMUClock *qemu_clock_ptr(QEMUClockType type)
89 90 91 92
{
    return &qemu_clocks[type];
}

93
static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
94 95 96 97
{
    return timer_head && (timer_head->expire_time <= current_time);
}

98 99 100
QEMUTimerList *timerlist_new(QEMUClockType type,
                             QEMUTimerListNotifyCB *cb,
                             void *opaque)
101 102
{
    QEMUTimerList *timer_list;
103
    QEMUClock *clock = qemu_clock_ptr(type);
104 105

    timer_list = g_malloc0(sizeof(QEMUTimerList));
106
    qemu_event_init(&timer_list->timers_done_ev, false);
107
    timer_list->clock = clock;
108 109
    timer_list->notify_cb = cb;
    timer_list->notify_opaque = opaque;
110
    qemu_mutex_init(&timer_list->active_timers_lock);
111 112 113 114 115 116 117 118 119 120
    QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
    return timer_list;
}

void timerlist_free(QEMUTimerList *timer_list)
{
    assert(!timerlist_has_timers(timer_list));
    if (timer_list->clock) {
        QLIST_REMOVE(timer_list, list);
    }
121
    qemu_mutex_destroy(&timer_list->active_timers_lock);
122 123 124
    g_free(timer_list);
}

125
static void qemu_clock_init(QEMUClockType type)
Paolo Bonzini's avatar
Paolo Bonzini committed
126
{
127
    QEMUClock *clock = qemu_clock_ptr(type);
128

Paolo Bonzini's avatar
Paolo Bonzini committed
129
    clock->type = type;
130
    clock->enabled = true;
131
    clock->last = INT64_MIN;
132
    QLIST_INIT(&clock->timerlists);
133
    notifier_list_init(&clock->reset_notifiers);
134
    main_loop_tlg.tl[type] = timerlist_new(type, NULL, NULL);
Paolo Bonzini's avatar
Paolo Bonzini committed
135 136
}

137
bool qemu_clock_use_for_deadline(QEMUClockType type)
138
{
139
    return !(use_icount && (type == QEMU_CLOCK_VIRTUAL));
140 141
}

142
void qemu_clock_notify(QEMUClockType type)
143 144
{
    QEMUTimerList *timer_list;
145
    QEMUClock *clock = qemu_clock_ptr(type);
146 147 148 149 150
    QLIST_FOREACH(timer_list, &clock->timerlists, list) {
        timerlist_notify(timer_list);
    }
}

151 152 153 154 155 156 157
/* Disabling the clock will wait for related timerlists to stop
 * executing qemu_run_timers.  Thus, this functions should not
 * be used from the callback of a timer that is based on @clock.
 * Doing so would cause a deadlock.
 *
 * Caller should hold BQL.
 */
158
void qemu_clock_enable(QEMUClockType type, bool enabled)
Paolo Bonzini's avatar
Paolo Bonzini committed
159
{
160
    QEMUClock *clock = qemu_clock_ptr(type);
161
    QEMUTimerList *tl;
162
    bool old = clock->enabled;
Paolo Bonzini's avatar
Paolo Bonzini committed
163
    clock->enabled = enabled;
164
    if (enabled && !old) {
165
        qemu_clock_notify(type);
166 167 168 169
    } else if (!enabled && old) {
        QLIST_FOREACH(tl, &clock->timerlists, list) {
            qemu_event_wait(&tl->timers_done_ev);
        }
170
    }
Paolo Bonzini's avatar
Paolo Bonzini committed
171 172
}

173
bool timerlist_has_timers(QEMUTimerList *timer_list)
174
{
175
    return !!timer_list->active_timers;
176 177
}

178
bool qemu_clock_has_timers(QEMUClockType type)
179
{
180
    return timerlist_has_timers(
181
        main_loop_tlg.tl[type]);
182 183
}

184 185
bool timerlist_expired(QEMUTimerList *timer_list)
{
186 187 188 189 190 191 192 193 194 195 196
    int64_t expire_time;

    qemu_mutex_lock(&timer_list->active_timers_lock);
    if (!timer_list->active_timers) {
        qemu_mutex_unlock(&timer_list->active_timers_lock);
        return false;
    }
    expire_time = timer_list->active_timers->expire_time;
    qemu_mutex_unlock(&timer_list->active_timers_lock);

    return expire_time < qemu_clock_get_ns(timer_list->clock->type);
197 198
}

199
bool qemu_clock_expired(QEMUClockType type)
200
{
201
    return timerlist_expired(
202
        main_loop_tlg.tl[type]);
203 204
}

205 206 207 208 209
/*
 * As above, but return -1 for no deadline, and do not cap to 2^32
 * as we know the result is always positive.
 */

210
int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
211 212
{
    int64_t delta;
213
    int64_t expire_time;
214

215
    if (!timer_list->clock->enabled) {
216 217 218
        return -1;
    }

219 220 221 222 223 224 225 226 227 228 229 230 231
    /* The active timers list may be modified before the caller uses our return
     * value but ->notify_cb() is called when the deadline changes.  Therefore
     * the caller should notice the change and there is no race condition.
     */
    qemu_mutex_lock(&timer_list->active_timers_lock);
    if (!timer_list->active_timers) {
        qemu_mutex_unlock(&timer_list->active_timers_lock);
        return -1;
    }
    expire_time = timer_list->active_timers->expire_time;
    qemu_mutex_unlock(&timer_list->active_timers_lock);

    delta = expire_time - qemu_clock_get_ns(timer_list->clock->type);
232 233 234 235 236 237 238 239

    if (delta <= 0) {
        return 0;
    }

    return delta;
}

240 241 242 243 244
/* Calculate the soonest deadline across all timerlists attached
 * to the clock. This is used for the icount timeout so we
 * ignore whether or not the clock should be used in deadline
 * calculations.
 */
245
int64_t qemu_clock_deadline_ns_all(QEMUClockType type)
246 247 248
{
    int64_t deadline = -1;
    QEMUTimerList *timer_list;
249
    QEMUClock *clock = qemu_clock_ptr(type);
250 251 252 253 254 255 256
    QLIST_FOREACH(timer_list, &clock->timerlists, list) {
        deadline = qemu_soonest_timeout(deadline,
                                        timerlist_deadline_ns(timer_list));
    }
    return deadline;
}

257
QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list)
258
{
259
    return timer_list->clock->type;
260 261
}

262
QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type)
263
{
264
    return main_loop_tlg.tl[type];
265 266
}

267 268 269 270 271 272 273 274 275
void timerlist_notify(QEMUTimerList *timer_list)
{
    if (timer_list->notify_cb) {
        timer_list->notify_cb(timer_list->notify_opaque);
    } else {
        qemu_notify_event();
    }
}

276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
/* Transition function to convert a nanosecond timeout to ms
 * This is used where a system does not support ppoll
 */
int qemu_timeout_ns_to_ms(int64_t ns)
{
    int64_t ms;
    if (ns < 0) {
        return -1;
    }

    if (!ns) {
        return 0;
    }

    /* Always round up, because it's better to wait too long than to wait too
     * little and effectively busy-wait
     */
    ms = (ns + SCALE_MS - 1) / SCALE_MS;

    /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
    if (ms > (int64_t) INT32_MAX) {
        ms = INT32_MAX;
    }

    return (int) ms;
}


304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
/* qemu implementation of g_poll which uses a nanosecond timeout but is
 * otherwise identical to g_poll
 */
int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout)
{
#ifdef CONFIG_PPOLL
    if (timeout < 0) {
        return ppoll((struct pollfd *)fds, nfds, NULL, NULL);
    } else {
        struct timespec ts;
        ts.tv_sec = timeout / 1000000000LL;
        ts.tv_nsec = timeout % 1000000000LL;
        return ppoll((struct pollfd *)fds, nfds, &ts, NULL);
    }
#else
    return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout));
#endif
}


324 325 326
void timer_init(QEMUTimer *ts,
                QEMUTimerList *timer_list, int scale,
                QEMUTimerCB *cb, void *opaque)
Paolo Bonzini's avatar
Paolo Bonzini committed
327
{
328
    ts->timer_list = timer_list;
Paolo Bonzini's avatar
Paolo Bonzini committed
329 330
    ts->cb = cb;
    ts->opaque = opaque;
331
    ts->scale = scale;
332
    ts->expire_time = -1;
333 334
}

335
void timer_free(QEMUTimer *ts)
Paolo Bonzini's avatar
Paolo Bonzini committed
336
{
337
    g_free(ts);
Paolo Bonzini's avatar
Paolo Bonzini committed
338 339
}

340
static void timer_del_locked(QEMUTimerList *timer_list, QEMUTimer *ts)
Paolo Bonzini's avatar
Paolo Bonzini committed
341 342 343
{
    QEMUTimer **pt, *t;

344
    ts->expire_time = -1;
345
    pt = &timer_list->active_timers;
Paolo Bonzini's avatar
Paolo Bonzini committed
346 347 348 349 350 351 352 353 354 355 356 357
    for(;;) {
        t = *pt;
        if (!t)
            break;
        if (t == ts) {
            *pt = t->next;
            break;
        }
        pt = &t->next;
    }
}

358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
                                QEMUTimer *ts, int64_t expire_time)
{
    QEMUTimer **pt, *t;

    /* add the timer in the sorted list */
    pt = &timer_list->active_timers;
    for (;;) {
        t = *pt;
        if (!timer_expired_ns(t, expire_time)) {
            break;
        }
        pt = &t->next;
    }
    ts->expire_time = MAX(expire_time, 0);
    ts->next = *pt;
    *pt = ts;

    return pt == &timer_list->active_timers;
}

static void timerlist_rearm(QEMUTimerList *timer_list)
{
    /* Interrupt execution to force deadline recalculation.  */
    qemu_clock_warp(timer_list->clock->type);
    timerlist_notify(timer_list);
}

386 387 388 389 390 391 392 393 394 395
/* stop a timer, but do not dealloc it */
void timer_del(QEMUTimer *ts)
{
    QEMUTimerList *timer_list = ts->timer_list;

    qemu_mutex_lock(&timer_list->active_timers_lock);
    timer_del_locked(timer_list, ts);
    qemu_mutex_unlock(&timer_list->active_timers_lock);
}

Paolo Bonzini's avatar
Paolo Bonzini committed
396 397
/* modify the current timer so that it will be fired when current_time
   >= expire_time. The corresponding callback will be called. */
398
void timer_mod_ns(QEMUTimer *ts, int64_t expire_time)
Paolo Bonzini's avatar
Paolo Bonzini committed
399
{
400
    QEMUTimerList *timer_list = ts->timer_list;
401
    bool rearm;
Paolo Bonzini's avatar
Paolo Bonzini committed
402

403 404
    qemu_mutex_lock(&timer_list->active_timers_lock);
    timer_del_locked(timer_list, ts);
405
    rearm = timer_mod_ns_locked(timer_list, ts, expire_time);
406
    qemu_mutex_unlock(&timer_list->active_timers_lock);
Paolo Bonzini's avatar
Paolo Bonzini committed
407

408 409
    if (rearm) {
        timerlist_rearm(timer_list);
Paolo Bonzini's avatar
Paolo Bonzini committed
410 411 412
    }
}

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
/* modify the current timer so that it will be fired when current_time
   >= expire_time or the current deadline, whichever comes earlier.
   The corresponding callback will be called. */
void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time)
{
    QEMUTimerList *timer_list = ts->timer_list;
    bool rearm;

    qemu_mutex_lock(&timer_list->active_timers_lock);
    if (ts->expire_time == -1 || ts->expire_time > expire_time) {
        if (ts->expire_time != -1) {
            timer_del_locked(timer_list, ts);
        }
        rearm = timer_mod_ns_locked(timer_list, ts, expire_time);
    } else {
        rearm = false;
    }
    qemu_mutex_unlock(&timer_list->active_timers_lock);

    if (rearm) {
        timerlist_rearm(timer_list);
    }
}

437
void timer_mod(QEMUTimer *ts, int64_t expire_time)
438
{
439
    timer_mod_ns(ts, expire_time * ts->scale);
440 441
}

442 443 444 445 446
void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time)
{
    timer_mod_anticipate_ns(ts, expire_time * ts->scale);
}

447
bool timer_pending(QEMUTimer *ts)
Paolo Bonzini's avatar
Paolo Bonzini committed
448
{
449
    return ts->expire_time >= 0;
Paolo Bonzini's avatar
Paolo Bonzini committed
450 451
}

452
bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
Paolo Bonzini's avatar
Paolo Bonzini committed
453
{
454
    return timer_expired_ns(timer_head, current_time * timer_head->scale);
Paolo Bonzini's avatar
Paolo Bonzini committed
455 456
}

457
bool timerlist_run_timers(QEMUTimerList *timer_list)
Paolo Bonzini's avatar
Paolo Bonzini committed
458
{
459
    QEMUTimer *ts;
Paolo Bonzini's avatar
Paolo Bonzini committed
460
    int64_t current_time;
461
    bool progress = false;
462 463 464
    QEMUTimerCB *cb;
    void *opaque;

465
    qemu_event_reset(&timer_list->timers_done_ev);
466
    if (!timer_list->clock->enabled) {
467
        goto out;
468
    }
Paolo Bonzini's avatar
Paolo Bonzini committed
469

470
    current_time = qemu_clock_get_ns(timer_list->clock->type);
Paolo Bonzini's avatar
Paolo Bonzini committed
471
    for(;;) {
472
        qemu_mutex_lock(&timer_list->active_timers_lock);
473
        ts = timer_list->active_timers;
474
        if (!timer_expired_ns(ts, current_time)) {
475
            qemu_mutex_unlock(&timer_list->active_timers_lock);
Paolo Bonzini's avatar
Paolo Bonzini committed
476
            break;
477
        }
478

Paolo Bonzini's avatar
Paolo Bonzini committed
479
        /* remove timer from the list before calling the callback */
480
        timer_list->active_timers = ts->next;
Paolo Bonzini's avatar
Paolo Bonzini committed
481
        ts->next = NULL;
482
        ts->expire_time = -1;
483 484 485
        cb = ts->cb;
        opaque = ts->opaque;
        qemu_mutex_unlock(&timer_list->active_timers_lock);
Paolo Bonzini's avatar
Paolo Bonzini committed
486 487

        /* run the callback (the timer list can be modified) */
488
        cb(opaque);
489
        progress = true;
Paolo Bonzini's avatar
Paolo Bonzini committed
490
    }
491 492 493

out:
    qemu_event_set(&timer_list->timers_done_ev);
494
    return progress;
Paolo Bonzini's avatar
Paolo Bonzini committed
495 496
}

497 498
bool qemu_clock_run_timers(QEMUClockType type)
{
499
    return timerlist_run_timers(main_loop_tlg.tl[type]);
500 501
}

502 503
void timerlistgroup_init(QEMUTimerListGroup *tlg,
                         QEMUTimerListNotifyCB *cb, void *opaque)
504 505 506
{
    QEMUClockType type;
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
507
        tlg->tl[type] = timerlist_new(type, cb, opaque);
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
    }
}

void timerlistgroup_deinit(QEMUTimerListGroup *tlg)
{
    QEMUClockType type;
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
        timerlist_free(tlg->tl[type]);
    }
}

bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg)
{
    QEMUClockType type;
    bool progress = false;
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
        progress |= timerlist_run_timers(tlg->tl[type]);
    }
    return progress;
}

int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg)
{
    int64_t deadline = -1;
    QEMUClockType type;
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
534
        if (qemu_clock_use_for_deadline(tlg->tl[type]->clock->type)) {
535 536 537 538 539 540 541 542
            deadline = qemu_soonest_timeout(deadline,
                                            timerlist_deadline_ns(
                                                tlg->tl[type]));
        }
    }
    return deadline;
}

543
int64_t qemu_clock_get_ns(QEMUClockType type)
Paolo Bonzini's avatar
Paolo Bonzini committed
544
{
545
    int64_t now, last;
546
    QEMUClock *clock = qemu_clock_ptr(type);
547

548
    switch (type) {
Paolo Bonzini's avatar
Paolo Bonzini committed
549 550 551 552 553 554 555 556 557 558
    case QEMU_CLOCK_REALTIME:
        return get_clock();
    default:
    case QEMU_CLOCK_VIRTUAL:
        if (use_icount) {
            return cpu_get_icount();
        } else {
            return cpu_get_clock();
        }
    case QEMU_CLOCK_HOST:
559 560 561 562 563 564 565
        now = get_clock_realtime();
        last = clock->last;
        clock->last = now;
        if (now < last) {
            notifier_list_notify(&clock->reset_notifiers, &now);
        }
        return now;
Paolo Bonzini's avatar
Paolo Bonzini committed
566 567 568
    }
}

569 570 571 572
void qemu_clock_register_reset_notifier(QEMUClockType type,
                                        Notifier *notifier)
{
    QEMUClock *clock = qemu_clock_ptr(type);
573 574 575
    notifier_list_add(&clock->reset_notifiers, notifier);
}

576 577
void qemu_clock_unregister_reset_notifier(QEMUClockType type,
                                          Notifier *notifier)
578
{
Paolo Bonzini's avatar
Paolo Bonzini committed
579
    notifier_remove(notifier);
580 581
}

Paolo Bonzini's avatar
Paolo Bonzini committed
582 583
void init_clocks(void)
{
584 585
    QEMUClockType type;
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
586
        qemu_clock_init(type);
587
    }
588

589 590 591
#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
    prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
#endif
Paolo Bonzini's avatar
Paolo Bonzini committed
592 593
}

594
uint64_t timer_expire_time_ns(QEMUTimer *ts)
Paolo Bonzini's avatar
Paolo Bonzini committed
595
{
596
    return timer_pending(ts) ? ts->expire_time : -1;
Paolo Bonzini's avatar
Paolo Bonzini committed
597 598
}

599
bool qemu_clock_run_all_timers(void)
Paolo Bonzini's avatar
Paolo Bonzini committed
600
{
601
    bool progress = false;
602
    QEMUClockType type;
603

604
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
605
        progress |= qemu_clock_run_timers(type);
606
    }
607

608
    return progress;
Paolo Bonzini's avatar
Paolo Bonzini committed
609
}