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