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