1db1a4972SPaolo Bonzini /* 2db1a4972SPaolo Bonzini * QEMU System Emulator 3db1a4972SPaolo Bonzini * 4db1a4972SPaolo Bonzini * Copyright (c) 2003-2008 Fabrice Bellard 5db1a4972SPaolo Bonzini * 6db1a4972SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 7db1a4972SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 8db1a4972SPaolo Bonzini * in the Software without restriction, including without limitation the rights 9db1a4972SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10db1a4972SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 11db1a4972SPaolo Bonzini * furnished to do so, subject to the following conditions: 12db1a4972SPaolo Bonzini * 13db1a4972SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 14db1a4972SPaolo Bonzini * all copies or substantial portions of the Software. 15db1a4972SPaolo Bonzini * 16db1a4972SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17db1a4972SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18db1a4972SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19db1a4972SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20db1a4972SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21db1a4972SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22db1a4972SPaolo Bonzini * THE SOFTWARE. 23db1a4972SPaolo Bonzini */ 24db1a4972SPaolo Bonzini 259c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 2683c9089eSPaolo Bonzini #include "monitor/monitor.h" 2728ecbaeeSPaolo Bonzini #include "ui/console.h" 28db1a4972SPaolo Bonzini 29db1a4972SPaolo Bonzini #include "hw/hw.h" 30db1a4972SPaolo Bonzini 311de7afc9SPaolo Bonzini #include "qemu/timer.h" 3230ea8339SAnthony Liguori #ifdef CONFIG_POSIX 3330ea8339SAnthony Liguori #include <pthread.h> 3430ea8339SAnthony Liguori #endif 35bff9f8bfSStefan Weil 36db1a4972SPaolo Bonzini #ifdef _WIN32 37db1a4972SPaolo Bonzini #include <mmsystem.h> 38db1a4972SPaolo Bonzini #endif 39db1a4972SPaolo Bonzini 40db1a4972SPaolo Bonzini /***********************************************************/ 41db1a4972SPaolo Bonzini /* timers */ 42db1a4972SPaolo Bonzini 43db1a4972SPaolo Bonzini struct QEMUClock { 44688eb389SPaolo Bonzini QEMUTimer *active_timers; 45691a0c9cSJan Kiszka 46691a0c9cSJan Kiszka NotifierList reset_notifiers; 47691a0c9cSJan Kiszka int64_t last; 489a14b298SStefan Weil 499a14b298SStefan Weil int type; 509a14b298SStefan Weil bool enabled; 51db1a4972SPaolo Bonzini }; 52db1a4972SPaolo Bonzini 53db1a4972SPaolo Bonzini struct QEMUTimer { 544a998740SPaolo Bonzini int64_t expire_time; /* in nanoseconds */ 559a14b298SStefan Weil QEMUClock *clock; 56db1a4972SPaolo Bonzini QEMUTimerCB *cb; 57db1a4972SPaolo Bonzini void *opaque; 589a14b298SStefan Weil QEMUTimer *next; 599a14b298SStefan Weil int scale; 60db1a4972SPaolo Bonzini }; 61db1a4972SPaolo Bonzini 62db1a4972SPaolo Bonzini struct qemu_alarm_timer { 63db1a4972SPaolo Bonzini char const *name; 64db1a4972SPaolo Bonzini int (*start)(struct qemu_alarm_timer *t); 65db1a4972SPaolo Bonzini void (*stop)(struct qemu_alarm_timer *t); 66f3fc6e2eSPaolo Bonzini void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns); 67cd0544eeSStefan Weil #if defined(__linux__) 68cd0544eeSStefan Weil timer_t timer; 699a14b298SStefan Weil int fd; 70cd0544eeSStefan Weil #elif defined(_WIN32) 71cd0544eeSStefan Weil HANDLE timer; 72cd0544eeSStefan Weil #endif 735e1ec7b2SStefan Weil bool expired; 745e1ec7b2SStefan Weil bool pending; 75db1a4972SPaolo Bonzini }; 76db1a4972SPaolo Bonzini 77db1a4972SPaolo Bonzini static struct qemu_alarm_timer *alarm_timer; 78db1a4972SPaolo Bonzini 79e93379b0SAlex Bligh static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time) 8045c7b37fSStefan Weil { 8145c7b37fSStefan Weil return timer_head && (timer_head->expire_time <= current_time); 8245c7b37fSStefan Weil } 8345c7b37fSStefan Weil 84f3fc6e2eSPaolo Bonzini static int64_t qemu_next_alarm_deadline(void) 85f3fc6e2eSPaolo Bonzini { 864ffd16fcSStefano Stabellini int64_t delta = INT64_MAX; 87f3fc6e2eSPaolo Bonzini int64_t rtdelta; 88f3fc6e2eSPaolo Bonzini 894ffd16fcSStefano Stabellini if (!use_icount && vm_clock->enabled && vm_clock->active_timers) { 90f3fc6e2eSPaolo Bonzini delta = vm_clock->active_timers->expire_time - 91f3fc6e2eSPaolo Bonzini qemu_get_clock_ns(vm_clock); 92f3fc6e2eSPaolo Bonzini } 934ffd16fcSStefano Stabellini if (host_clock->enabled && host_clock->active_timers) { 94f3fc6e2eSPaolo Bonzini int64_t hdelta = host_clock->active_timers->expire_time - 95f3fc6e2eSPaolo Bonzini qemu_get_clock_ns(host_clock); 96f3fc6e2eSPaolo Bonzini if (hdelta < delta) { 97f3fc6e2eSPaolo Bonzini delta = hdelta; 98f3fc6e2eSPaolo Bonzini } 99f3fc6e2eSPaolo Bonzini } 1004ffd16fcSStefano Stabellini if (rt_clock->enabled && rt_clock->active_timers) { 101f3fc6e2eSPaolo Bonzini rtdelta = (rt_clock->active_timers->expire_time - 102f3fc6e2eSPaolo Bonzini qemu_get_clock_ns(rt_clock)); 103f3fc6e2eSPaolo Bonzini if (rtdelta < delta) { 104f3fc6e2eSPaolo Bonzini delta = rtdelta; 105f3fc6e2eSPaolo Bonzini } 106f3fc6e2eSPaolo Bonzini } 107f3fc6e2eSPaolo Bonzini 108f3fc6e2eSPaolo Bonzini return delta; 109f3fc6e2eSPaolo Bonzini } 110f3fc6e2eSPaolo Bonzini 111db1a4972SPaolo Bonzini static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t) 112db1a4972SPaolo Bonzini { 1138227421eSStefano Stabellini int64_t nearest_delta_ns = qemu_next_alarm_deadline(); 1148227421eSStefano Stabellini if (nearest_delta_ns < INT64_MAX) { 115f3fc6e2eSPaolo Bonzini t->rearm(t, nearest_delta_ns); 116db1a4972SPaolo Bonzini } 1178227421eSStefano Stabellini } 118db1a4972SPaolo Bonzini 1199c13246aSPaolo Bonzini /* TODO: MIN_TIMER_REARM_NS should be optimized */ 1209c13246aSPaolo Bonzini #define MIN_TIMER_REARM_NS 250000 121db1a4972SPaolo Bonzini 122db1a4972SPaolo Bonzini #ifdef _WIN32 123db1a4972SPaolo Bonzini 1242f9cba0cSStefan Weil static int mm_start_timer(struct qemu_alarm_timer *t); 1252f9cba0cSStefan Weil static void mm_stop_timer(struct qemu_alarm_timer *t); 126f3fc6e2eSPaolo Bonzini static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); 1272f9cba0cSStefan Weil 128db1a4972SPaolo Bonzini static int win32_start_timer(struct qemu_alarm_timer *t); 129db1a4972SPaolo Bonzini static void win32_stop_timer(struct qemu_alarm_timer *t); 130f3fc6e2eSPaolo Bonzini static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); 131db1a4972SPaolo Bonzini 132db1a4972SPaolo Bonzini #else 133db1a4972SPaolo Bonzini 134db1a4972SPaolo Bonzini static int unix_start_timer(struct qemu_alarm_timer *t); 135db1a4972SPaolo Bonzini static void unix_stop_timer(struct qemu_alarm_timer *t); 136f3fc6e2eSPaolo Bonzini static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); 137db1a4972SPaolo Bonzini 138db1a4972SPaolo Bonzini #ifdef __linux__ 139db1a4972SPaolo Bonzini 140db1a4972SPaolo Bonzini static int dynticks_start_timer(struct qemu_alarm_timer *t); 141db1a4972SPaolo Bonzini static void dynticks_stop_timer(struct qemu_alarm_timer *t); 142f3fc6e2eSPaolo Bonzini static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); 143db1a4972SPaolo Bonzini 144db1a4972SPaolo Bonzini #endif /* __linux__ */ 145db1a4972SPaolo Bonzini 146db1a4972SPaolo Bonzini #endif /* _WIN32 */ 147db1a4972SPaolo Bonzini 148db1a4972SPaolo Bonzini static struct qemu_alarm_timer alarm_timers[] = { 149db1a4972SPaolo Bonzini #ifndef _WIN32 150db1a4972SPaolo Bonzini #ifdef __linux__ 151db1a4972SPaolo Bonzini {"dynticks", dynticks_start_timer, 152cd0544eeSStefan Weil dynticks_stop_timer, dynticks_rearm_timer}, 153db1a4972SPaolo Bonzini #endif 15484682834SPaolo Bonzini {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer}, 155db1a4972SPaolo Bonzini #else 156cca5de73SPaolo Bonzini {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer}, 157cd0544eeSStefan Weil {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer}, 158db1a4972SPaolo Bonzini #endif 159db1a4972SPaolo Bonzini {NULL, } 160db1a4972SPaolo Bonzini }; 161db1a4972SPaolo Bonzini 162db1a4972SPaolo Bonzini static void show_available_alarms(void) 163db1a4972SPaolo Bonzini { 164db1a4972SPaolo Bonzini int i; 165db1a4972SPaolo Bonzini 166db1a4972SPaolo Bonzini printf("Available alarm timers, in order of precedence:\n"); 167db1a4972SPaolo Bonzini for (i = 0; alarm_timers[i].name; i++) 168db1a4972SPaolo Bonzini printf("%s\n", alarm_timers[i].name); 169db1a4972SPaolo Bonzini } 170db1a4972SPaolo Bonzini 171db1a4972SPaolo Bonzini void configure_alarms(char const *opt) 172db1a4972SPaolo Bonzini { 173db1a4972SPaolo Bonzini int i; 174db1a4972SPaolo Bonzini int cur = 0; 175db1a4972SPaolo Bonzini int count = ARRAY_SIZE(alarm_timers) - 1; 176db1a4972SPaolo Bonzini char *arg; 177db1a4972SPaolo Bonzini char *name; 178db1a4972SPaolo Bonzini struct qemu_alarm_timer tmp; 179db1a4972SPaolo Bonzini 180c8057f95SPeter Maydell if (is_help_option(opt)) { 181db1a4972SPaolo Bonzini show_available_alarms(); 182db1a4972SPaolo Bonzini exit(0); 183db1a4972SPaolo Bonzini } 184db1a4972SPaolo Bonzini 1857267c094SAnthony Liguori arg = g_strdup(opt); 186db1a4972SPaolo Bonzini 187db1a4972SPaolo Bonzini /* Reorder the array */ 188db1a4972SPaolo Bonzini name = strtok(arg, ","); 189db1a4972SPaolo Bonzini while (name) { 190db1a4972SPaolo Bonzini for (i = 0; i < count && alarm_timers[i].name; i++) { 191db1a4972SPaolo Bonzini if (!strcmp(alarm_timers[i].name, name)) 192db1a4972SPaolo Bonzini break; 193db1a4972SPaolo Bonzini } 194db1a4972SPaolo Bonzini 195db1a4972SPaolo Bonzini if (i == count) { 196db1a4972SPaolo Bonzini fprintf(stderr, "Unknown clock %s\n", name); 197db1a4972SPaolo Bonzini goto next; 198db1a4972SPaolo Bonzini } 199db1a4972SPaolo Bonzini 200db1a4972SPaolo Bonzini if (i < cur) 201db1a4972SPaolo Bonzini /* Ignore */ 202db1a4972SPaolo Bonzini goto next; 203db1a4972SPaolo Bonzini 204db1a4972SPaolo Bonzini /* Swap */ 205db1a4972SPaolo Bonzini tmp = alarm_timers[i]; 206db1a4972SPaolo Bonzini alarm_timers[i] = alarm_timers[cur]; 207db1a4972SPaolo Bonzini alarm_timers[cur] = tmp; 208db1a4972SPaolo Bonzini 209db1a4972SPaolo Bonzini cur++; 210db1a4972SPaolo Bonzini next: 211db1a4972SPaolo Bonzini name = strtok(NULL, ","); 212db1a4972SPaolo Bonzini } 213db1a4972SPaolo Bonzini 2147267c094SAnthony Liguori g_free(arg); 215db1a4972SPaolo Bonzini 216db1a4972SPaolo Bonzini if (cur) { 217db1a4972SPaolo Bonzini /* Disable remaining timers */ 218db1a4972SPaolo Bonzini for (i = cur; i < count; i++) 219db1a4972SPaolo Bonzini alarm_timers[i].name = NULL; 220db1a4972SPaolo Bonzini } else { 221db1a4972SPaolo Bonzini show_available_alarms(); 222db1a4972SPaolo Bonzini exit(1); 223db1a4972SPaolo Bonzini } 224db1a4972SPaolo Bonzini } 225db1a4972SPaolo Bonzini 226db1a4972SPaolo Bonzini QEMUClock *rt_clock; 227db1a4972SPaolo Bonzini QEMUClock *vm_clock; 228db1a4972SPaolo Bonzini QEMUClock *host_clock; 229db1a4972SPaolo Bonzini 23058ac56b9SAlex Bligh static QEMUClock *qemu_clock_new(int type) 231db1a4972SPaolo Bonzini { 232db1a4972SPaolo Bonzini QEMUClock *clock; 233691a0c9cSJan Kiszka 2347267c094SAnthony Liguori clock = g_malloc0(sizeof(QEMUClock)); 235db1a4972SPaolo Bonzini clock->type = type; 2365e1ec7b2SStefan Weil clock->enabled = true; 2372ff68d07SPaolo Bonzini clock->last = INT64_MIN; 238691a0c9cSJan Kiszka notifier_list_init(&clock->reset_notifiers); 239db1a4972SPaolo Bonzini return clock; 240db1a4972SPaolo Bonzini } 241db1a4972SPaolo Bonzini 2425e1ec7b2SStefan Weil void qemu_clock_enable(QEMUClock *clock, bool enabled) 243db1a4972SPaolo Bonzini { 244fbdc14ebSPaolo Bonzini bool old = clock->enabled; 245db1a4972SPaolo Bonzini clock->enabled = enabled; 246fbdc14ebSPaolo Bonzini if (enabled && !old) { 247fbdc14ebSPaolo Bonzini qemu_rearm_alarm_timer(alarm_timer); 248fbdc14ebSPaolo Bonzini } 249db1a4972SPaolo Bonzini } 250db1a4972SPaolo Bonzini 251dc2dfcf0SPaolo Bonzini int64_t qemu_clock_has_timers(QEMUClock *clock) 252dc2dfcf0SPaolo Bonzini { 253dc2dfcf0SPaolo Bonzini return !!clock->active_timers; 254dc2dfcf0SPaolo Bonzini } 255dc2dfcf0SPaolo Bonzini 256dc2dfcf0SPaolo Bonzini int64_t qemu_clock_expired(QEMUClock *clock) 257dc2dfcf0SPaolo Bonzini { 258dc2dfcf0SPaolo Bonzini return (clock->active_timers && 259dc2dfcf0SPaolo Bonzini clock->active_timers->expire_time < qemu_get_clock_ns(clock)); 260dc2dfcf0SPaolo Bonzini } 261dc2dfcf0SPaolo Bonzini 262dc2dfcf0SPaolo Bonzini int64_t qemu_clock_deadline(QEMUClock *clock) 263dc2dfcf0SPaolo Bonzini { 264dc2dfcf0SPaolo Bonzini /* To avoid problems with overflow limit this to 2^32. */ 265dc2dfcf0SPaolo Bonzini int64_t delta = INT32_MAX; 266dc2dfcf0SPaolo Bonzini 267dc2dfcf0SPaolo Bonzini if (clock->active_timers) { 268dc2dfcf0SPaolo Bonzini delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock); 269dc2dfcf0SPaolo Bonzini } 270dc2dfcf0SPaolo Bonzini if (delta < 0) { 271dc2dfcf0SPaolo Bonzini delta = 0; 272dc2dfcf0SPaolo Bonzini } 273dc2dfcf0SPaolo Bonzini return delta; 274dc2dfcf0SPaolo Bonzini } 275dc2dfcf0SPaolo Bonzini 276*02a03a9fSAlex Bligh /* 277*02a03a9fSAlex Bligh * As above, but return -1 for no deadline, and do not cap to 2^32 278*02a03a9fSAlex Bligh * as we know the result is always positive. 279*02a03a9fSAlex Bligh */ 280*02a03a9fSAlex Bligh 281*02a03a9fSAlex Bligh int64_t qemu_clock_deadline_ns(QEMUClock *clock) 282*02a03a9fSAlex Bligh { 283*02a03a9fSAlex Bligh int64_t delta; 284*02a03a9fSAlex Bligh 285*02a03a9fSAlex Bligh if (!clock->enabled || !clock->active_timers) { 286*02a03a9fSAlex Bligh return -1; 287*02a03a9fSAlex Bligh } 288*02a03a9fSAlex Bligh 289*02a03a9fSAlex Bligh delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock); 290*02a03a9fSAlex Bligh 291*02a03a9fSAlex Bligh if (delta <= 0) { 292*02a03a9fSAlex Bligh return 0; 293*02a03a9fSAlex Bligh } 294*02a03a9fSAlex Bligh 295*02a03a9fSAlex Bligh return delta; 296*02a03a9fSAlex Bligh } 297*02a03a9fSAlex Bligh 298*02a03a9fSAlex Bligh /* Transition function to convert a nanosecond timeout to ms 299*02a03a9fSAlex Bligh * This is used where a system does not support ppoll 300*02a03a9fSAlex Bligh */ 301*02a03a9fSAlex Bligh int qemu_timeout_ns_to_ms(int64_t ns) 302*02a03a9fSAlex Bligh { 303*02a03a9fSAlex Bligh int64_t ms; 304*02a03a9fSAlex Bligh if (ns < 0) { 305*02a03a9fSAlex Bligh return -1; 306*02a03a9fSAlex Bligh } 307*02a03a9fSAlex Bligh 308*02a03a9fSAlex Bligh if (!ns) { 309*02a03a9fSAlex Bligh return 0; 310*02a03a9fSAlex Bligh } 311*02a03a9fSAlex Bligh 312*02a03a9fSAlex Bligh /* Always round up, because it's better to wait too long than to wait too 313*02a03a9fSAlex Bligh * little and effectively busy-wait 314*02a03a9fSAlex Bligh */ 315*02a03a9fSAlex Bligh ms = (ns + SCALE_MS - 1) / SCALE_MS; 316*02a03a9fSAlex Bligh 317*02a03a9fSAlex Bligh /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */ 318*02a03a9fSAlex Bligh if (ms > (int64_t) INT32_MAX) { 319*02a03a9fSAlex Bligh ms = INT32_MAX; 320*02a03a9fSAlex Bligh } 321*02a03a9fSAlex Bligh 322*02a03a9fSAlex Bligh return (int) ms; 323*02a03a9fSAlex Bligh } 324*02a03a9fSAlex Bligh 325*02a03a9fSAlex Bligh 3264a998740SPaolo Bonzini QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale, 3274a998740SPaolo Bonzini QEMUTimerCB *cb, void *opaque) 328db1a4972SPaolo Bonzini { 329db1a4972SPaolo Bonzini QEMUTimer *ts; 330db1a4972SPaolo Bonzini 3317267c094SAnthony Liguori ts = g_malloc0(sizeof(QEMUTimer)); 332db1a4972SPaolo Bonzini ts->clock = clock; 333db1a4972SPaolo Bonzini ts->cb = cb; 334db1a4972SPaolo Bonzini ts->opaque = opaque; 3354a998740SPaolo Bonzini ts->scale = scale; 336db1a4972SPaolo Bonzini return ts; 337db1a4972SPaolo Bonzini } 338db1a4972SPaolo Bonzini 339db1a4972SPaolo Bonzini void qemu_free_timer(QEMUTimer *ts) 340db1a4972SPaolo Bonzini { 3417267c094SAnthony Liguori g_free(ts); 342db1a4972SPaolo Bonzini } 343db1a4972SPaolo Bonzini 344db1a4972SPaolo Bonzini /* stop a timer, but do not dealloc it */ 345db1a4972SPaolo Bonzini void qemu_del_timer(QEMUTimer *ts) 346db1a4972SPaolo Bonzini { 347db1a4972SPaolo Bonzini QEMUTimer **pt, *t; 348db1a4972SPaolo Bonzini 349db1a4972SPaolo Bonzini /* NOTE: this code must be signal safe because 350e93379b0SAlex Bligh timer_expired() can be called from a signal. */ 351688eb389SPaolo Bonzini pt = &ts->clock->active_timers; 352db1a4972SPaolo Bonzini for(;;) { 353db1a4972SPaolo Bonzini t = *pt; 354db1a4972SPaolo Bonzini if (!t) 355db1a4972SPaolo Bonzini break; 356db1a4972SPaolo Bonzini if (t == ts) { 357db1a4972SPaolo Bonzini *pt = t->next; 358db1a4972SPaolo Bonzini break; 359db1a4972SPaolo Bonzini } 360db1a4972SPaolo Bonzini pt = &t->next; 361db1a4972SPaolo Bonzini } 362db1a4972SPaolo Bonzini } 363db1a4972SPaolo Bonzini 364db1a4972SPaolo Bonzini /* modify the current timer so that it will be fired when current_time 365db1a4972SPaolo Bonzini >= expire_time. The corresponding callback will be called. */ 3662ff68d07SPaolo Bonzini void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) 367db1a4972SPaolo Bonzini { 368db1a4972SPaolo Bonzini QEMUTimer **pt, *t; 369db1a4972SPaolo Bonzini 370db1a4972SPaolo Bonzini qemu_del_timer(ts); 371db1a4972SPaolo Bonzini 372db1a4972SPaolo Bonzini /* add the timer in the sorted list */ 373db1a4972SPaolo Bonzini /* NOTE: this code must be signal safe because 374e93379b0SAlex Bligh timer_expired() can be called from a signal. */ 375688eb389SPaolo Bonzini pt = &ts->clock->active_timers; 376db1a4972SPaolo Bonzini for(;;) { 377db1a4972SPaolo Bonzini t = *pt; 378e93379b0SAlex Bligh if (!timer_expired_ns(t, expire_time)) { 379db1a4972SPaolo Bonzini break; 38045c7b37fSStefan Weil } 381db1a4972SPaolo Bonzini pt = &t->next; 382db1a4972SPaolo Bonzini } 383db1a4972SPaolo Bonzini ts->expire_time = expire_time; 384db1a4972SPaolo Bonzini ts->next = *pt; 385db1a4972SPaolo Bonzini *pt = ts; 386db1a4972SPaolo Bonzini 387db1a4972SPaolo Bonzini /* Rearm if necessary */ 388688eb389SPaolo Bonzini if (pt == &ts->clock->active_timers) { 389db1a4972SPaolo Bonzini if (!alarm_timer->pending) { 390db1a4972SPaolo Bonzini qemu_rearm_alarm_timer(alarm_timer); 391db1a4972SPaolo Bonzini } 392db1a4972SPaolo Bonzini /* Interrupt execution to force deadline recalculation. */ 393ab33fcdaSPaolo Bonzini qemu_clock_warp(ts->clock); 394ab33fcdaSPaolo Bonzini if (use_icount) { 395db1a4972SPaolo Bonzini qemu_notify_event(); 396db1a4972SPaolo Bonzini } 397db1a4972SPaolo Bonzini } 398ab33fcdaSPaolo Bonzini } 399db1a4972SPaolo Bonzini 4004a998740SPaolo Bonzini void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) 4014a998740SPaolo Bonzini { 4024a998740SPaolo Bonzini qemu_mod_timer_ns(ts, expire_time * ts->scale); 4034a998740SPaolo Bonzini } 4044a998740SPaolo Bonzini 405e93379b0SAlex Bligh bool timer_pending(QEMUTimer *ts) 406db1a4972SPaolo Bonzini { 407db1a4972SPaolo Bonzini QEMUTimer *t; 408688eb389SPaolo Bonzini for (t = ts->clock->active_timers; t != NULL; t = t->next) { 4095e1ec7b2SStefan Weil if (t == ts) { 4105e1ec7b2SStefan Weil return true; 411db1a4972SPaolo Bonzini } 4125e1ec7b2SStefan Weil } 4135e1ec7b2SStefan Weil return false; 414db1a4972SPaolo Bonzini } 415db1a4972SPaolo Bonzini 416e93379b0SAlex Bligh bool timer_expired(QEMUTimer *timer_head, int64_t current_time) 417db1a4972SPaolo Bonzini { 418e93379b0SAlex Bligh return timer_expired_ns(timer_head, current_time * timer_head->scale); 419db1a4972SPaolo Bonzini } 420db1a4972SPaolo Bonzini 4218156be56SPaolo Bonzini void qemu_run_timers(QEMUClock *clock) 422db1a4972SPaolo Bonzini { 423144b97c2SPaolo Bonzini QEMUTimer *ts; 424db1a4972SPaolo Bonzini int64_t current_time; 425db1a4972SPaolo Bonzini 426db1a4972SPaolo Bonzini if (!clock->enabled) 427db1a4972SPaolo Bonzini return; 428db1a4972SPaolo Bonzini 4294a998740SPaolo Bonzini current_time = qemu_get_clock_ns(clock); 430db1a4972SPaolo Bonzini for(;;) { 431144b97c2SPaolo Bonzini ts = clock->active_timers; 432e93379b0SAlex Bligh if (!timer_expired_ns(ts, current_time)) { 433db1a4972SPaolo Bonzini break; 43445c7b37fSStefan Weil } 435db1a4972SPaolo Bonzini /* remove timer from the list before calling the callback */ 436144b97c2SPaolo Bonzini clock->active_timers = ts->next; 437db1a4972SPaolo Bonzini ts->next = NULL; 438db1a4972SPaolo Bonzini 439db1a4972SPaolo Bonzini /* run the callback (the timer list can be modified) */ 440db1a4972SPaolo Bonzini ts->cb(ts->opaque); 441db1a4972SPaolo Bonzini } 442db1a4972SPaolo Bonzini } 443db1a4972SPaolo Bonzini 444db1a4972SPaolo Bonzini int64_t qemu_get_clock_ns(QEMUClock *clock) 445db1a4972SPaolo Bonzini { 446691a0c9cSJan Kiszka int64_t now, last; 447691a0c9cSJan Kiszka 448db1a4972SPaolo Bonzini switch(clock->type) { 449db1a4972SPaolo Bonzini case QEMU_CLOCK_REALTIME: 450db1a4972SPaolo Bonzini return get_clock(); 451db1a4972SPaolo Bonzini default: 452db1a4972SPaolo Bonzini case QEMU_CLOCK_VIRTUAL: 453db1a4972SPaolo Bonzini if (use_icount) { 454db1a4972SPaolo Bonzini return cpu_get_icount(); 455db1a4972SPaolo Bonzini } else { 456db1a4972SPaolo Bonzini return cpu_get_clock(); 457db1a4972SPaolo Bonzini } 458db1a4972SPaolo Bonzini case QEMU_CLOCK_HOST: 459691a0c9cSJan Kiszka now = get_clock_realtime(); 460691a0c9cSJan Kiszka last = clock->last; 461691a0c9cSJan Kiszka clock->last = now; 462691a0c9cSJan Kiszka if (now < last) { 463691a0c9cSJan Kiszka notifier_list_notify(&clock->reset_notifiers, &now); 464db1a4972SPaolo Bonzini } 465691a0c9cSJan Kiszka return now; 466691a0c9cSJan Kiszka } 467691a0c9cSJan Kiszka } 468691a0c9cSJan Kiszka 469691a0c9cSJan Kiszka void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier) 470691a0c9cSJan Kiszka { 471691a0c9cSJan Kiszka notifier_list_add(&clock->reset_notifiers, notifier); 472691a0c9cSJan Kiszka } 473691a0c9cSJan Kiszka 474691a0c9cSJan Kiszka void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier) 475691a0c9cSJan Kiszka { 47631552529SPaolo Bonzini notifier_remove(notifier); 477db1a4972SPaolo Bonzini } 478db1a4972SPaolo Bonzini 479db1a4972SPaolo Bonzini void init_clocks(void) 480db1a4972SPaolo Bonzini { 481744ca8e3SPaolo Bonzini if (!rt_clock) { 48258ac56b9SAlex Bligh rt_clock = qemu_clock_new(QEMU_CLOCK_REALTIME); 48358ac56b9SAlex Bligh vm_clock = qemu_clock_new(QEMU_CLOCK_VIRTUAL); 48458ac56b9SAlex Bligh host_clock = qemu_clock_new(QEMU_CLOCK_HOST); 485db1a4972SPaolo Bonzini } 486744ca8e3SPaolo Bonzini } 487db1a4972SPaolo Bonzini 488e93379b0SAlex Bligh uint64_t timer_expire_time_ns(QEMUTimer *ts) 489db1a4972SPaolo Bonzini { 490e93379b0SAlex Bligh return timer_pending(ts) ? ts->expire_time : -1; 491db1a4972SPaolo Bonzini } 492db1a4972SPaolo Bonzini 493db1a4972SPaolo Bonzini void qemu_run_all_timers(void) 494db1a4972SPaolo Bonzini { 4955e1ec7b2SStefan Weil alarm_timer->pending = false; 496ca5a2a4bSPaolo Bonzini 497158fd3ceSPeter Portante /* vm time timers */ 498158fd3ceSPeter Portante qemu_run_timers(vm_clock); 499158fd3ceSPeter Portante qemu_run_timers(rt_clock); 500158fd3ceSPeter Portante qemu_run_timers(host_clock); 501158fd3ceSPeter Portante 502db1a4972SPaolo Bonzini /* rearm timer, if not periodic */ 503db1a4972SPaolo Bonzini if (alarm_timer->expired) { 5045e1ec7b2SStefan Weil alarm_timer->expired = false; 505db1a4972SPaolo Bonzini qemu_rearm_alarm_timer(alarm_timer); 506db1a4972SPaolo Bonzini } 507db1a4972SPaolo Bonzini } 508db1a4972SPaolo Bonzini 509db1a4972SPaolo Bonzini #ifdef _WIN32 51068c23e55SPaolo Bonzini static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused) 511db1a4972SPaolo Bonzini #else 512db1a4972SPaolo Bonzini static void host_alarm_handler(int host_signum) 513db1a4972SPaolo Bonzini #endif 514db1a4972SPaolo Bonzini { 515db1a4972SPaolo Bonzini struct qemu_alarm_timer *t = alarm_timer; 516db1a4972SPaolo Bonzini if (!t) 517db1a4972SPaolo Bonzini return; 518db1a4972SPaolo Bonzini 5198205199dSStefan Weil t->expired = true; 5205e1ec7b2SStefan Weil t->pending = true; 521db1a4972SPaolo Bonzini qemu_notify_event(); 522db1a4972SPaolo Bonzini } 523db1a4972SPaolo Bonzini 5244c3d45ebSPaolo Bonzini #if defined(__linux__) 5254c3d45ebSPaolo Bonzini 5261de7afc9SPaolo Bonzini #include "qemu/compatfd.h" 527d25f89c9SJan Kiszka 528db1a4972SPaolo Bonzini static int dynticks_start_timer(struct qemu_alarm_timer *t) 529db1a4972SPaolo Bonzini { 530db1a4972SPaolo Bonzini struct sigevent ev; 531db1a4972SPaolo Bonzini timer_t host_timer; 532db1a4972SPaolo Bonzini struct sigaction act; 533db1a4972SPaolo Bonzini 534db1a4972SPaolo Bonzini sigfillset(&act.sa_mask); 535db1a4972SPaolo Bonzini act.sa_flags = 0; 536db1a4972SPaolo Bonzini act.sa_handler = host_alarm_handler; 537db1a4972SPaolo Bonzini 538db1a4972SPaolo Bonzini sigaction(SIGALRM, &act, NULL); 539db1a4972SPaolo Bonzini 540db1a4972SPaolo Bonzini /* 541db1a4972SPaolo Bonzini * Initialize ev struct to 0 to avoid valgrind complaining 542db1a4972SPaolo Bonzini * about uninitialized data in timer_create call 543db1a4972SPaolo Bonzini */ 544db1a4972SPaolo Bonzini memset(&ev, 0, sizeof(ev)); 545db1a4972SPaolo Bonzini ev.sigev_value.sival_int = 0; 546db1a4972SPaolo Bonzini ev.sigev_notify = SIGEV_SIGNAL; 5471e9737daSRichard Henderson #ifdef CONFIG_SIGEV_THREAD_ID 548d25f89c9SJan Kiszka if (qemu_signalfd_available()) { 549d25f89c9SJan Kiszka ev.sigev_notify = SIGEV_THREAD_ID; 550d25f89c9SJan Kiszka ev._sigev_un._tid = qemu_get_thread_id(); 551d25f89c9SJan Kiszka } 5521e9737daSRichard Henderson #endif /* CONFIG_SIGEV_THREAD_ID */ 553db1a4972SPaolo Bonzini ev.sigev_signo = SIGALRM; 554db1a4972SPaolo Bonzini 555db1a4972SPaolo Bonzini if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) { 556db1a4972SPaolo Bonzini perror("timer_create"); 557db1a4972SPaolo Bonzini return -1; 558db1a4972SPaolo Bonzini } 559db1a4972SPaolo Bonzini 560cd0544eeSStefan Weil t->timer = host_timer; 561db1a4972SPaolo Bonzini 562db1a4972SPaolo Bonzini return 0; 563db1a4972SPaolo Bonzini } 564db1a4972SPaolo Bonzini 565db1a4972SPaolo Bonzini static void dynticks_stop_timer(struct qemu_alarm_timer *t) 566db1a4972SPaolo Bonzini { 567cd0544eeSStefan Weil timer_t host_timer = t->timer; 568db1a4972SPaolo Bonzini 569db1a4972SPaolo Bonzini timer_delete(host_timer); 570db1a4972SPaolo Bonzini } 571db1a4972SPaolo Bonzini 572f3fc6e2eSPaolo Bonzini static void dynticks_rearm_timer(struct qemu_alarm_timer *t, 573f3fc6e2eSPaolo Bonzini int64_t nearest_delta_ns) 574db1a4972SPaolo Bonzini { 575cd0544eeSStefan Weil timer_t host_timer = t->timer; 576db1a4972SPaolo Bonzini struct itimerspec timeout; 5779c13246aSPaolo Bonzini int64_t current_ns; 578db1a4972SPaolo Bonzini 5794c3d45ebSPaolo Bonzini if (nearest_delta_ns < MIN_TIMER_REARM_NS) 5804c3d45ebSPaolo Bonzini nearest_delta_ns = MIN_TIMER_REARM_NS; 581db1a4972SPaolo Bonzini 582db1a4972SPaolo Bonzini /* check whether a timer is already running */ 583db1a4972SPaolo Bonzini if (timer_gettime(host_timer, &timeout)) { 584db1a4972SPaolo Bonzini perror("gettime"); 585db1a4972SPaolo Bonzini fprintf(stderr, "Internal timer error: aborting\n"); 586db1a4972SPaolo Bonzini exit(1); 587db1a4972SPaolo Bonzini } 5889c13246aSPaolo Bonzini current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec; 5899c13246aSPaolo Bonzini if (current_ns && current_ns <= nearest_delta_ns) 590db1a4972SPaolo Bonzini return; 591db1a4972SPaolo Bonzini 592db1a4972SPaolo Bonzini timeout.it_interval.tv_sec = 0; 593db1a4972SPaolo Bonzini timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */ 5949c13246aSPaolo Bonzini timeout.it_value.tv_sec = nearest_delta_ns / 1000000000; 5959c13246aSPaolo Bonzini timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000; 596db1a4972SPaolo Bonzini if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) { 597db1a4972SPaolo Bonzini perror("settime"); 598db1a4972SPaolo Bonzini fprintf(stderr, "Internal timer error: aborting\n"); 599db1a4972SPaolo Bonzini exit(1); 600db1a4972SPaolo Bonzini } 601db1a4972SPaolo Bonzini } 602db1a4972SPaolo Bonzini 603db1a4972SPaolo Bonzini #endif /* defined(__linux__) */ 604db1a4972SPaolo Bonzini 605f26e5a54SStefan Weil #if !defined(_WIN32) 606f26e5a54SStefan Weil 607db1a4972SPaolo Bonzini static int unix_start_timer(struct qemu_alarm_timer *t) 608db1a4972SPaolo Bonzini { 609db1a4972SPaolo Bonzini struct sigaction act; 610db1a4972SPaolo Bonzini 611db1a4972SPaolo Bonzini /* timer signal */ 612db1a4972SPaolo Bonzini sigfillset(&act.sa_mask); 613db1a4972SPaolo Bonzini act.sa_flags = 0; 614db1a4972SPaolo Bonzini act.sa_handler = host_alarm_handler; 615db1a4972SPaolo Bonzini 616db1a4972SPaolo Bonzini sigaction(SIGALRM, &act, NULL); 61784682834SPaolo Bonzini return 0; 61884682834SPaolo Bonzini } 61984682834SPaolo Bonzini 620f3fc6e2eSPaolo Bonzini static void unix_rearm_timer(struct qemu_alarm_timer *t, 621f3fc6e2eSPaolo Bonzini int64_t nearest_delta_ns) 62284682834SPaolo Bonzini { 62384682834SPaolo Bonzini struct itimerval itv; 62484682834SPaolo Bonzini int err; 62584682834SPaolo Bonzini 62684682834SPaolo Bonzini if (nearest_delta_ns < MIN_TIMER_REARM_NS) 62784682834SPaolo Bonzini nearest_delta_ns = MIN_TIMER_REARM_NS; 628db1a4972SPaolo Bonzini 629db1a4972SPaolo Bonzini itv.it_interval.tv_sec = 0; 63084682834SPaolo Bonzini itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */ 63184682834SPaolo Bonzini itv.it_value.tv_sec = nearest_delta_ns / 1000000000; 63284682834SPaolo Bonzini itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000; 633db1a4972SPaolo Bonzini err = setitimer(ITIMER_REAL, &itv, NULL); 63484682834SPaolo Bonzini if (err) { 63584682834SPaolo Bonzini perror("setitimer"); 63684682834SPaolo Bonzini fprintf(stderr, "Internal timer error: aborting\n"); 63784682834SPaolo Bonzini exit(1); 63884682834SPaolo Bonzini } 639db1a4972SPaolo Bonzini } 640db1a4972SPaolo Bonzini 641db1a4972SPaolo Bonzini static void unix_stop_timer(struct qemu_alarm_timer *t) 642db1a4972SPaolo Bonzini { 643db1a4972SPaolo Bonzini struct itimerval itv; 644db1a4972SPaolo Bonzini 645db1a4972SPaolo Bonzini memset(&itv, 0, sizeof(itv)); 646db1a4972SPaolo Bonzini setitimer(ITIMER_REAL, &itv, NULL); 647db1a4972SPaolo Bonzini } 648db1a4972SPaolo Bonzini 649db1a4972SPaolo Bonzini #endif /* !defined(_WIN32) */ 650db1a4972SPaolo Bonzini 651db1a4972SPaolo Bonzini 652db1a4972SPaolo Bonzini #ifdef _WIN32 653db1a4972SPaolo Bonzini 6542f9cba0cSStefan Weil static MMRESULT mm_timer; 65540f08e87SStefan Weil static TIMECAPS mm_tc; 6562f9cba0cSStefan Weil 6572f9cba0cSStefan Weil static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg, 6582f9cba0cSStefan Weil DWORD_PTR dwUser, DWORD_PTR dw1, 6592f9cba0cSStefan Weil DWORD_PTR dw2) 6602f9cba0cSStefan Weil { 6612f9cba0cSStefan Weil struct qemu_alarm_timer *t = alarm_timer; 6622f9cba0cSStefan Weil if (!t) { 6632f9cba0cSStefan Weil return; 6642f9cba0cSStefan Weil } 6658205199dSStefan Weil t->expired = true; 6665e1ec7b2SStefan Weil t->pending = true; 6672f9cba0cSStefan Weil qemu_notify_event(); 6682f9cba0cSStefan Weil } 6692f9cba0cSStefan Weil 6702f9cba0cSStefan Weil static int mm_start_timer(struct qemu_alarm_timer *t) 6712f9cba0cSStefan Weil { 67240f08e87SStefan Weil timeGetDevCaps(&mm_tc, sizeof(mm_tc)); 6732f9cba0cSStefan Weil return 0; 6742f9cba0cSStefan Weil } 6752f9cba0cSStefan Weil 6762f9cba0cSStefan Weil static void mm_stop_timer(struct qemu_alarm_timer *t) 6772f9cba0cSStefan Weil { 6780727b867SPaolo Bonzini if (mm_timer) { 6792f9cba0cSStefan Weil timeKillEvent(mm_timer); 6800727b867SPaolo Bonzini } 6812f9cba0cSStefan Weil } 6822f9cba0cSStefan Weil 683f3fc6e2eSPaolo Bonzini static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta) 6842f9cba0cSStefan Weil { 6855bfb723fSStefano Stabellini int64_t nearest_delta_ms = delta / 1000000; 68640f08e87SStefan Weil if (nearest_delta_ms < mm_tc.wPeriodMin) { 68740f08e87SStefan Weil nearest_delta_ms = mm_tc.wPeriodMin; 68840f08e87SStefan Weil } else if (nearest_delta_ms > mm_tc.wPeriodMax) { 68940f08e87SStefan Weil nearest_delta_ms = mm_tc.wPeriodMax; 6905bfb723fSStefano Stabellini } 691f3fc6e2eSPaolo Bonzini 6920727b867SPaolo Bonzini if (mm_timer) { 693f3fc6e2eSPaolo Bonzini timeKillEvent(mm_timer); 6940727b867SPaolo Bonzini } 69540f08e87SStefan Weil mm_timer = timeSetEvent((UINT)nearest_delta_ms, 69640f08e87SStefan Weil mm_tc.wPeriodMin, 6972f9cba0cSStefan Weil mm_alarm_handler, 6982f9cba0cSStefan Weil (DWORD_PTR)t, 6992f9cba0cSStefan Weil TIME_ONESHOT | TIME_CALLBACK_FUNCTION); 7002f9cba0cSStefan Weil 7012f9cba0cSStefan Weil if (!mm_timer) { 70252ef651fSStefan Weil fprintf(stderr, "Failed to re-arm win32 alarm timer\n"); 70340f08e87SStefan Weil timeEndPeriod(mm_tc.wPeriodMin); 7042f9cba0cSStefan Weil exit(1); 7052f9cba0cSStefan Weil } 7062f9cba0cSStefan Weil } 7072f9cba0cSStefan Weil 708db1a4972SPaolo Bonzini static int win32_start_timer(struct qemu_alarm_timer *t) 709db1a4972SPaolo Bonzini { 71068c23e55SPaolo Bonzini HANDLE hTimer; 71168c23e55SPaolo Bonzini BOOLEAN success; 712db1a4972SPaolo Bonzini 71368c23e55SPaolo Bonzini /* If you call ChangeTimerQueueTimer on a one-shot timer (its period 71468c23e55SPaolo Bonzini is zero) that has already expired, the timer is not updated. Since 71568c23e55SPaolo Bonzini creating a new timer is relatively expensive, set a bogus one-hour 71668c23e55SPaolo Bonzini interval in the dynticks case. */ 71768c23e55SPaolo Bonzini success = CreateTimerQueueTimer(&hTimer, 71868c23e55SPaolo Bonzini NULL, 71968c23e55SPaolo Bonzini host_alarm_handler, 72068c23e55SPaolo Bonzini t, 72168c23e55SPaolo Bonzini 1, 7228205199dSStefan Weil 3600000, 72368c23e55SPaolo Bonzini WT_EXECUTEINTIMERTHREAD); 724db1a4972SPaolo Bonzini 72568c23e55SPaolo Bonzini if (!success) { 726db1a4972SPaolo Bonzini fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", 727db1a4972SPaolo Bonzini GetLastError()); 728db1a4972SPaolo Bonzini return -1; 729db1a4972SPaolo Bonzini } 730db1a4972SPaolo Bonzini 731cd0544eeSStefan Weil t->timer = hTimer; 732db1a4972SPaolo Bonzini return 0; 733db1a4972SPaolo Bonzini } 734db1a4972SPaolo Bonzini 735db1a4972SPaolo Bonzini static void win32_stop_timer(struct qemu_alarm_timer *t) 736db1a4972SPaolo Bonzini { 737cd0544eeSStefan Weil HANDLE hTimer = t->timer; 738db1a4972SPaolo Bonzini 73968c23e55SPaolo Bonzini if (hTimer) { 74068c23e55SPaolo Bonzini DeleteTimerQueueTimer(NULL, hTimer, NULL); 74168c23e55SPaolo Bonzini } 742db1a4972SPaolo Bonzini } 743db1a4972SPaolo Bonzini 744f3fc6e2eSPaolo Bonzini static void win32_rearm_timer(struct qemu_alarm_timer *t, 745f3fc6e2eSPaolo Bonzini int64_t nearest_delta_ns) 746db1a4972SPaolo Bonzini { 747cd0544eeSStefan Weil HANDLE hTimer = t->timer; 7485bfb723fSStefano Stabellini int64_t nearest_delta_ms; 74968c23e55SPaolo Bonzini BOOLEAN success; 750db1a4972SPaolo Bonzini 7515bfb723fSStefano Stabellini nearest_delta_ms = nearest_delta_ns / 1000000; 752cfced5b2SPaolo Bonzini if (nearest_delta_ms < 1) { 753cfced5b2SPaolo Bonzini nearest_delta_ms = 1; 754cfced5b2SPaolo Bonzini } 7555bfb723fSStefano Stabellini /* ULONG_MAX can be 32 bit */ 7565bfb723fSStefano Stabellini if (nearest_delta_ms > ULONG_MAX) { 7575bfb723fSStefano Stabellini nearest_delta_ms = ULONG_MAX; 7585bfb723fSStefano Stabellini } 75968c23e55SPaolo Bonzini success = ChangeTimerQueueTimer(NULL, 76068c23e55SPaolo Bonzini hTimer, 7615bfb723fSStefano Stabellini (unsigned long) nearest_delta_ms, 76268c23e55SPaolo Bonzini 3600000); 763db1a4972SPaolo Bonzini 76468c23e55SPaolo Bonzini if (!success) { 76568c23e55SPaolo Bonzini fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n", 766db1a4972SPaolo Bonzini GetLastError()); 76768c23e55SPaolo Bonzini exit(-1); 768db1a4972SPaolo Bonzini } 76968c23e55SPaolo Bonzini 770db1a4972SPaolo Bonzini } 771db1a4972SPaolo Bonzini 772db1a4972SPaolo Bonzini #endif /* _WIN32 */ 773db1a4972SPaolo Bonzini 7744260a739SPaolo Bonzini static void quit_timers(void) 7754260a739SPaolo Bonzini { 7764260a739SPaolo Bonzini struct qemu_alarm_timer *t = alarm_timer; 7774260a739SPaolo Bonzini alarm_timer = NULL; 7784260a739SPaolo Bonzini t->stop(t); 7794260a739SPaolo Bonzini } 7804260a739SPaolo Bonzini 781253ecf83SStefan Weil #ifdef CONFIG_POSIX 782c8122c35SPaolo Bonzini static void reinit_timers(void) 783c8122c35SPaolo Bonzini { 784c8122c35SPaolo Bonzini struct qemu_alarm_timer *t = alarm_timer; 785c8122c35SPaolo Bonzini t->stop(t); 786c8122c35SPaolo Bonzini if (t->start(t)) { 787c8122c35SPaolo Bonzini fprintf(stderr, "Internal timer error: aborting\n"); 788c8122c35SPaolo Bonzini exit(1); 789c8122c35SPaolo Bonzini } 790c8122c35SPaolo Bonzini qemu_rearm_alarm_timer(t); 791c8122c35SPaolo Bonzini } 792253ecf83SStefan Weil #endif /* CONFIG_POSIX */ 793c8122c35SPaolo Bonzini 794db1a4972SPaolo Bonzini int init_timer_alarm(void) 795db1a4972SPaolo Bonzini { 796db1a4972SPaolo Bonzini struct qemu_alarm_timer *t = NULL; 797db1a4972SPaolo Bonzini int i, err = -1; 798db1a4972SPaolo Bonzini 799744ca8e3SPaolo Bonzini if (alarm_timer) { 800744ca8e3SPaolo Bonzini return 0; 801744ca8e3SPaolo Bonzini } 802744ca8e3SPaolo Bonzini 803db1a4972SPaolo Bonzini for (i = 0; alarm_timers[i].name; i++) { 804db1a4972SPaolo Bonzini t = &alarm_timers[i]; 805db1a4972SPaolo Bonzini 806db1a4972SPaolo Bonzini err = t->start(t); 807db1a4972SPaolo Bonzini if (!err) 808db1a4972SPaolo Bonzini break; 809db1a4972SPaolo Bonzini } 810db1a4972SPaolo Bonzini 811db1a4972SPaolo Bonzini if (err) { 812db1a4972SPaolo Bonzini err = -ENOENT; 813db1a4972SPaolo Bonzini goto fail; 814db1a4972SPaolo Bonzini } 815db1a4972SPaolo Bonzini 8164260a739SPaolo Bonzini atexit(quit_timers); 817c8122c35SPaolo Bonzini #ifdef CONFIG_POSIX 818c8122c35SPaolo Bonzini pthread_atfork(NULL, NULL, reinit_timers); 819c8122c35SPaolo Bonzini #endif 820db1a4972SPaolo Bonzini alarm_timer = t; 821db1a4972SPaolo Bonzini return 0; 822db1a4972SPaolo Bonzini 823db1a4972SPaolo Bonzini fail: 824db1a4972SPaolo Bonzini return err; 825db1a4972SPaolo Bonzini } 826db1a4972SPaolo Bonzini 827