qemu-timer.c revision f9077a88a0b9edca081b0810dde73d108db087a6
16a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/*
26a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * QEMU System Emulator
36a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner *
46a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * Copyright (c) 2003-2008 Fabrice Bellard
56a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner *
66a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * Permission is hereby granted, free of charge, to any person obtaining a copy
76a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * of this software and associated documentation files (the "Software"), to deal
86a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * in the Software without restriction, including without limitation the rights
96a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
106a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * copies of the Software, and to permit persons to whom the Software is
116a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * furnished to do so, subject to the following conditions:
126a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner *
136a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * The above copyright notice and this permission notice shall be included in
146a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * all copies or substantial portions of the Software.
156a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner *
166a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
176a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
186a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
196a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
206a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
216a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
226a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * THE SOFTWARE.
236a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner */
246a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2534c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/sysemu.h"
26cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "net/net.h"
276af6765e2f3bc930d0dce21d752bea570a1b1362David 'Digit' Turner#include "monitor/monitor.h"
281c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "ui/console.h"
296a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
306a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#include "hw/hw.h"
316a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
326a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#include <unistd.h>
336a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#include <fcntl.h>
346a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#include <time.h>
356a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#include <errno.h>
366a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#include <sys/time.h>
376a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#include <signal.h>
386a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#ifdef __FreeBSD__
396a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#include <sys/param.h>
406a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#endif
416a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
427a78db75ad42aea283f5073f51891464104a9fc3David 'Digit' Turner#include "qemu/timer.h"
436a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
446a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/***********************************************************/
456a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* guest cycle counter */
466a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
476a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnertypedef struct TimersState {
486a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int64_t cpu_ticks_prev;
496a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int64_t cpu_ticks_offset;
506a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int64_t cpu_clock_offset;
516a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int32_t cpu_ticks_enabled;
526a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int64_t dummy;
536a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner} TimersState;
546a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
556a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerstatic void timer_save(QEMUFile *f, void *opaque)
566a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
576a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    TimersState *s = opaque;
586a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
596a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (s->cpu_ticks_enabled) {
606a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        hw_error("cannot save state if virtual timers are running");
616a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
626a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    qemu_put_be64(f, s->cpu_ticks_prev);
636a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    qemu_put_be64(f, s->cpu_ticks_offset);
646a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    qemu_put_be64(f, s->cpu_clock_offset);
656a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner }
666a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
676a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerstatic int timer_load(QEMUFile *f, void *opaque, int version_id)
686a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
696a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    TimersState *s = opaque;
706a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
716a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (version_id != 1 && version_id != 2)
726a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return -EINVAL;
736a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (s->cpu_ticks_enabled) {
746a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return -EINVAL;
756a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
766a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    s->cpu_ticks_prev   = qemu_get_sbe64(f);
776a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    s->cpu_ticks_offset = qemu_get_sbe64(f);
786a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (version_id == 2) {
796a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        s->cpu_clock_offset = qemu_get_sbe64(f);
806a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
816a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    return 0;
826a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
836a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
846a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
856a9ef1773bf874dea493ff3861782a1e577b67ddDavid TurnerTimersState timers_state;
866a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
87f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnervoid qemu_timer_register_savevm(void) {
88f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    register_savevm("timer", 0, 2, timer_save, timer_load, &timers_state);
89f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
90f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
916a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* return the host CPU cycle counter and handle stop/restart */
926a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerint64_t cpu_get_ticks(void)
936a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
946a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (use_icount) {
956a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return cpu_get_icount();
966a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
976a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (!timers_state.cpu_ticks_enabled) {
986a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return timers_state.cpu_ticks_offset;
996a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    } else {
1006a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        int64_t ticks;
1016a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        ticks = cpu_get_real_ticks();
1026a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        if (timers_state.cpu_ticks_prev > ticks) {
1036a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            /* Note: non increasing ticks may happen if the host uses
1046a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner               software suspend */
1056a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
1066a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        }
1076a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        timers_state.cpu_ticks_prev = ticks;
1086a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return ticks + timers_state.cpu_ticks_offset;
1096a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
1106a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
1116a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
1126a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* return the host CPU monotonic timer and handle stop/restart */
113f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint64_t cpu_get_clock(void)
1146a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
1156a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int64_t ti;
1166a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (!timers_state.cpu_ticks_enabled) {
1176a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return timers_state.cpu_clock_offset;
1186a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    } else {
1196a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        ti = get_clock();
1206a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return ti + timers_state.cpu_clock_offset;
1216a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
1226a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
1236a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
1246a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* enable cpu_get_ticks() */
1256a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnervoid cpu_enable_ticks(void)
1266a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
1276a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (!timers_state.cpu_ticks_enabled) {
1286a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
1296a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        timers_state.cpu_clock_offset -= get_clock();
1306a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        timers_state.cpu_ticks_enabled = 1;
1316a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
1326a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
1336a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
1346a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* disable cpu_get_ticks() : the clock is stopped. You must not call
1356a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner   cpu_get_ticks() after that.  */
1366a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnervoid cpu_disable_ticks(void)
1376a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
1386a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (timers_state.cpu_ticks_enabled) {
1396a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        timers_state.cpu_ticks_offset = cpu_get_ticks();
1406a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        timers_state.cpu_clock_offset = cpu_get_clock();
1416a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        timers_state.cpu_ticks_enabled = 0;
1426a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
1436a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
1446a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
1456a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/***********************************************************/
1466a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* timers */
1476a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
1486a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerstruct QEMUClock {
1496a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int type;
1506a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int enabled;
151317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
152317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    QEMUTimer *warp_timer;
1536a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner};
1546a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
155f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' TurnerQEMUTimer* qemu_clock_get_warp_timer(QEMUClock* clock) {
156f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return clock ? clock->warp_timer : NULL;
157f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
158f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
1596a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerstruct QEMUTimer {
1606a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUClock *clock;
161317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    int64_t expire_time;	/* in nanoseconds */
162317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    int scale;
1636a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUTimerCB *cb;
1646a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    void *opaque;
1656a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    struct QEMUTimer *next;
1666a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner};
1676a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
168317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turnerstatic bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
169317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner{
170317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    return timer_head && (timer_head->expire_time <= current_time);
171317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner}
172317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
1736a9ef1773bf874dea493ff3861782a1e577b67ddDavid TurnerQEMUClock *rt_clock;
1746a9ef1773bf874dea493ff3861782a1e577b67ddDavid TurnerQEMUClock *vm_clock;
1756a9ef1773bf874dea493ff3861782a1e577b67ddDavid TurnerQEMUClock *host_clock;
1766a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
177f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' TurnerQEMUTimer *active_timers[QEMU_NUM_CLOCKS];
1786a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
1796a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerstatic QEMUClock *qemu_new_clock(int type)
1806a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
1816a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUClock *clock;
182aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    clock = g_malloc0(sizeof(QEMUClock));
1836a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    clock->type = type;
1846a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    clock->enabled = 1;
1856a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    return clock;
1866a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
1876a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
1886a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnervoid qemu_clock_enable(QEMUClock *clock, int enabled)
1896a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
1906a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    clock->enabled = enabled;
1916a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
1926a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
193f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint qemu_clock_has_active_timer(QEMUClock* clock) {
194f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return active_timers[clock->type] != NULL;
195317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner}
196317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
197f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint64_t qemu_clock_next_deadline(QEMUClock* clock) {
198f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* To avoid problems with overflow limit this to 2^32.  */
199f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int64_t delta = INT32_MAX;
200317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
201f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (active_timers[clock->type]) {
202f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        delta = active_timers[clock->type]->expire_time -
203f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                qemu_get_clock_ns(clock);
204317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    }
205317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
206f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (delta < 0)
207f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        delta = 0;
208317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
209f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return delta;
210317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner}
211317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
2125973c775c853e26f684de58ad28c267281aaffd6David 'Digit' TurnerQEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
213317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner                          QEMUTimerCB *cb, void *opaque)
2146a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
2156a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUTimer *ts;
2166a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
217aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    ts = g_malloc0(sizeof(QEMUTimer));
2186a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    ts->clock = clock;
2196a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    ts->cb = cb;
2206a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    ts->opaque = opaque;
221317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    ts->scale = scale;
2226a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    return ts;
2236a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
2246a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2256a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnervoid qemu_free_timer(QEMUTimer *ts)
2266a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
227aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(ts);
2286a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
2296a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2306a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* stop a timer, but do not dealloc it */
2316a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnervoid qemu_del_timer(QEMUTimer *ts)
2326a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
2336a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUTimer **pt, *t;
2346a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2356a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    /* NOTE: this code must be signal safe because
2366a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner       qemu_timer_expired() can be called from a signal. */
2376a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    pt = &active_timers[ts->clock->type];
2386a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    for(;;) {
2396a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        t = *pt;
2406a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        if (!t)
2416a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            break;
2426a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        if (t == ts) {
2436a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            *pt = t->next;
2446a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            break;
2456a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        }
2466a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        pt = &t->next;
2476a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
2486a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
2496a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2506a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* modify the current timer so that it will be fired when current_time
2516a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner   >= expire_time. The corresponding callback will be called. */
252317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turnerstatic void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
2536a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
2546a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUTimer **pt, *t;
2556a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2566a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    qemu_del_timer(ts);
2576a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2586a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    /* add the timer in the sorted list */
2596a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    /* NOTE: this code must be signal safe because
2606a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner       qemu_timer_expired() can be called from a signal. */
2616a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    pt = &active_timers[ts->clock->type];
2626a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    for(;;) {
2636a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        t = *pt;
264317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner        if (!qemu_timer_expired_ns(t, expire_time)) {
2656a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            break;
266317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner        }
2676a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        pt = &t->next;
2686a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
2696a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    ts->expire_time = expire_time;
2706a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    ts->next = *pt;
2716a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    *pt = ts;
2726a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2736a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    /* Rearm if necessary  */
2746a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (pt == &active_timers[ts->clock->type]) {
275f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        qemu_adjust_clock(ts->clock);
276317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    }
277317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner}
278317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
279317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner/* modify the current timer so that it will be fired when current_time
280317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner   >= expire_time. The corresponding callback will be called. */
281317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turnervoid qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
282317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner{
283317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    qemu_mod_timer_ns(ts, expire_time * ts->scale);
2846a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
2856a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2866a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerint qemu_timer_pending(QEMUTimer *ts)
2876a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
2886a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUTimer *t;
2896a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) {
2906a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        if (t == ts)
2916a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            return 1;
2926a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
2936a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    return 0;
2946a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
2956a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2966a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerint qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
2976a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
298317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
2996a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3006a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
301f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnervoid qemu_run_timers(QEMUClock *clock)
3026a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
3036a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUTimer **ptimer_head, *ts;
3046a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int64_t current_time;
3056b512811e01d7c81348bfa9c29c21f788ccc0a8eDavid 'Digit' Turner
3066a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (!clock->enabled)
3076a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return;
3086a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
309317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    current_time = qemu_get_clock_ns(clock);
3106a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    ptimer_head = &active_timers[clock->type];
3116a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    for(;;) {
3126a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        ts = *ptimer_head;
313317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner        if (!qemu_timer_expired_ns(ts, current_time)) {
3146a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            break;
315317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner        }
3166a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        /* remove timer from the list before calling the callback */
3176a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        *ptimer_head = ts->next;
3186a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        ts->next = NULL;
3196a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3206a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        /* run the callback (the timer list can be modified) */
3216a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        ts->cb(ts->opaque);
3226a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
3236a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3246a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3256a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerint64_t qemu_get_clock(QEMUClock *clock)
3266a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
3276a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    switch(clock->type) {
3286a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    case QEMU_CLOCK_REALTIME:
3296a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return get_clock() / 1000000;
3306a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    default:
3316a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    case QEMU_CLOCK_VIRTUAL:
3326a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        if (use_icount) {
3336a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            return cpu_get_icount();
3346a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        } else {
3356a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            return cpu_get_clock();
3366a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        }
3376a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    case QEMU_CLOCK_HOST:
3386a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return get_clock_realtime();
3396a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
3406a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3416a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3426a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerint64_t qemu_get_clock_ns(QEMUClock *clock)
3436a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
3446a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    switch(clock->type) {
3456a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    case QEMU_CLOCK_REALTIME:
3466a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return get_clock();
3476a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    default:
3486a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    case QEMU_CLOCK_VIRTUAL:
3496a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        if (use_icount) {
3506a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            return cpu_get_icount();
3516a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        } else {
3526a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            return cpu_get_clock();
3536a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        }
3546a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    case QEMU_CLOCK_HOST:
3556a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return get_clock_realtime();
3566a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
3576a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3586a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3596a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnervoid init_clocks(void)
3606a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
3616a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
3626a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
3636a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
3646a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3656a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    rtc_clock = host_clock;
3666a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3676a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3686a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* save a timer */
3696a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnervoid qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
3706a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
3716a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    uint64_t expire_time;
3726a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3736a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (qemu_timer_pending(ts)) {
3746a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        expire_time = ts->expire_time;
3756a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    } else {
3766a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        expire_time = -1;
3776a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
3786a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    qemu_put_be64(f, expire_time);
3796a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3806a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3816a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnervoid qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
3826a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
3836a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    uint64_t expire_time;
3846a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3856a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    expire_time = qemu_get_be64(f);
3866a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    if (expire_time != -1) {
387317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner        qemu_mod_timer_ns(ts, expire_time);
3886a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    } else {
3896a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        qemu_del_timer(ts);
3906a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
3916a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3926a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3936a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#if 0
3946a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turnerstatic const VMStateDescription vmstate_timers = {
3956a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    .name = "timer",
3966a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    .version_id = 2,
3976a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    .minimum_version_id = 1,
3986a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    .minimum_version_id_old = 1,
3996a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    .fields      = (VMStateField []) {
4006a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        VMSTATE_INT64(cpu_ticks_offset, TimersState),
4016a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        VMSTATE_INT64(dummy, TimersState),
4026a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
4036a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        VMSTATE_END_OF_LIST()
4046a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
4056a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner};
4066a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#endif
407