1 /* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "sysemu/sysemu.h" 26 #include "monitor/monitor.h" 27 #include "ui/console.h" 28 29 #include "hw/hw.h" 30 31 #include "qemu/timer.h" 32 #ifdef CONFIG_POSIX 33 #include <pthread.h> 34 #endif 35 36 #ifdef CONFIG_PPOLL 37 #include <poll.h> 38 #endif 39 40 #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK 41 #include <sys/prctl.h> 42 #endif 43 44 /***********************************************************/ 45 /* timers */ 46 47 typedef struct QEMUClock { 48 QLIST_HEAD(, QEMUTimerList) timerlists; 49 50 NotifierList reset_notifiers; 51 int64_t last; 52 53 QEMUClockType type; 54 bool enabled; 55 } QEMUClock; 56 57 QEMUTimerListGroup main_loop_tlg; 58 QEMUClock qemu_clocks[QEMU_CLOCK_MAX]; 59 60 /* A QEMUTimerList is a list of timers attached to a clock. More 61 * than one QEMUTimerList can be attached to each clock, for instance 62 * used by different AioContexts / threads. Each clock also has 63 * a list of the QEMUTimerLists associated with it, in order that 64 * reenabling the clock can call all the notifiers. 65 */ 66 67 struct QEMUTimerList { 68 QEMUClock *clock; 69 QemuMutex active_timers_lock; 70 QEMUTimer *active_timers; 71 QLIST_ENTRY(QEMUTimerList) list; 72 QEMUTimerListNotifyCB *notify_cb; 73 void *notify_opaque; 74 }; 75 76 /** 77 * qemu_clock_ptr: 78 * @type: type of clock 79 * 80 * Translate a clock type into a pointer to QEMUClock object. 81 * 82 * Returns: a pointer to the QEMUClock object 83 */ 84 static inline QEMUClock *qemu_clock_ptr(QEMUClockType type) 85 { 86 return &qemu_clocks[type]; 87 } 88 89 static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time) 90 { 91 return timer_head && (timer_head->expire_time <= current_time); 92 } 93 94 QEMUTimerList *timerlist_new(QEMUClockType type, 95 QEMUTimerListNotifyCB *cb, 96 void *opaque) 97 { 98 QEMUTimerList *timer_list; 99 QEMUClock *clock = qemu_clock_ptr(type); 100 101 timer_list = g_malloc0(sizeof(QEMUTimerList)); 102 timer_list->clock = clock; 103 timer_list->notify_cb = cb; 104 timer_list->notify_opaque = opaque; 105 qemu_mutex_init(&timer_list->active_timers_lock); 106 QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list); 107 return timer_list; 108 } 109 110 void timerlist_free(QEMUTimerList *timer_list) 111 { 112 assert(!timerlist_has_timers(timer_list)); 113 if (timer_list->clock) { 114 QLIST_REMOVE(timer_list, list); 115 } 116 qemu_mutex_destroy(&timer_list->active_timers_lock); 117 g_free(timer_list); 118 } 119 120 static void qemu_clock_init(QEMUClockType type) 121 { 122 QEMUClock *clock = qemu_clock_ptr(type); 123 124 clock->type = type; 125 clock->enabled = true; 126 clock->last = INT64_MIN; 127 QLIST_INIT(&clock->timerlists); 128 notifier_list_init(&clock->reset_notifiers); 129 main_loop_tlg.tl[type] = timerlist_new(type, NULL, NULL); 130 } 131 132 bool qemu_clock_use_for_deadline(QEMUClockType type) 133 { 134 return !(use_icount && (type == QEMU_CLOCK_VIRTUAL)); 135 } 136 137 void qemu_clock_notify(QEMUClockType type) 138 { 139 QEMUTimerList *timer_list; 140 QEMUClock *clock = qemu_clock_ptr(type); 141 QLIST_FOREACH(timer_list, &clock->timerlists, list) { 142 timerlist_notify(timer_list); 143 } 144 } 145 146 void qemu_clock_enable(QEMUClockType type, bool enabled) 147 { 148 QEMUClock *clock = qemu_clock_ptr(type); 149 bool old = clock->enabled; 150 clock->enabled = enabled; 151 if (enabled && !old) { 152 qemu_clock_notify(type); 153 } 154 } 155 156 bool timerlist_has_timers(QEMUTimerList *timer_list) 157 { 158 return !!timer_list->active_timers; 159 } 160 161 bool qemu_clock_has_timers(QEMUClockType type) 162 { 163 return timerlist_has_timers( 164 main_loop_tlg.tl[type]); 165 } 166 167 bool timerlist_expired(QEMUTimerList *timer_list) 168 { 169 int64_t expire_time; 170 171 qemu_mutex_lock(&timer_list->active_timers_lock); 172 if (!timer_list->active_timers) { 173 qemu_mutex_unlock(&timer_list->active_timers_lock); 174 return false; 175 } 176 expire_time = timer_list->active_timers->expire_time; 177 qemu_mutex_unlock(&timer_list->active_timers_lock); 178 179 return expire_time < qemu_clock_get_ns(timer_list->clock->type); 180 } 181 182 bool qemu_clock_expired(QEMUClockType type) 183 { 184 return timerlist_expired( 185 main_loop_tlg.tl[type]); 186 } 187 188 /* 189 * As above, but return -1 for no deadline, and do not cap to 2^32 190 * as we know the result is always positive. 191 */ 192 193 int64_t timerlist_deadline_ns(QEMUTimerList *timer_list) 194 { 195 int64_t delta; 196 int64_t expire_time; 197 198 if (!timer_list->clock->enabled) { 199 return -1; 200 } 201 202 /* The active timers list may be modified before the caller uses our return 203 * value but ->notify_cb() is called when the deadline changes. Therefore 204 * the caller should notice the change and there is no race condition. 205 */ 206 qemu_mutex_lock(&timer_list->active_timers_lock); 207 if (!timer_list->active_timers) { 208 qemu_mutex_unlock(&timer_list->active_timers_lock); 209 return -1; 210 } 211 expire_time = timer_list->active_timers->expire_time; 212 qemu_mutex_unlock(&timer_list->active_timers_lock); 213 214 delta = expire_time - qemu_clock_get_ns(timer_list->clock->type); 215 216 if (delta <= 0) { 217 return 0; 218 } 219 220 return delta; 221 } 222 223 /* Calculate the soonest deadline across all timerlists attached 224 * to the clock. This is used for the icount timeout so we 225 * ignore whether or not the clock should be used in deadline 226 * calculations. 227 */ 228 int64_t qemu_clock_deadline_ns_all(QEMUClockType type) 229 { 230 int64_t deadline = -1; 231 QEMUTimerList *timer_list; 232 QEMUClock *clock = qemu_clock_ptr(type); 233 QLIST_FOREACH(timer_list, &clock->timerlists, list) { 234 deadline = qemu_soonest_timeout(deadline, 235 timerlist_deadline_ns(timer_list)); 236 } 237 return deadline; 238 } 239 240 QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list) 241 { 242 return timer_list->clock->type; 243 } 244 245 QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type) 246 { 247 return main_loop_tlg.tl[type]; 248 } 249 250 void timerlist_notify(QEMUTimerList *timer_list) 251 { 252 if (timer_list->notify_cb) { 253 timer_list->notify_cb(timer_list->notify_opaque); 254 } else { 255 qemu_notify_event(); 256 } 257 } 258 259 /* Transition function to convert a nanosecond timeout to ms 260 * This is used where a system does not support ppoll 261 */ 262 int qemu_timeout_ns_to_ms(int64_t ns) 263 { 264 int64_t ms; 265 if (ns < 0) { 266 return -1; 267 } 268 269 if (!ns) { 270 return 0; 271 } 272 273 /* Always round up, because it's better to wait too long than to wait too 274 * little and effectively busy-wait 275 */ 276 ms = (ns + SCALE_MS - 1) / SCALE_MS; 277 278 /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */ 279 if (ms > (int64_t) INT32_MAX) { 280 ms = INT32_MAX; 281 } 282 283 return (int) ms; 284 } 285 286 287 /* qemu implementation of g_poll which uses a nanosecond timeout but is 288 * otherwise identical to g_poll 289 */ 290 int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout) 291 { 292 #ifdef CONFIG_PPOLL 293 if (timeout < 0) { 294 return ppoll((struct pollfd *)fds, nfds, NULL, NULL); 295 } else { 296 struct timespec ts; 297 ts.tv_sec = timeout / 1000000000LL; 298 ts.tv_nsec = timeout % 1000000000LL; 299 return ppoll((struct pollfd *)fds, nfds, &ts, NULL); 300 } 301 #else 302 return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout)); 303 #endif 304 } 305 306 307 void timer_init(QEMUTimer *ts, 308 QEMUTimerList *timer_list, int scale, 309 QEMUTimerCB *cb, void *opaque) 310 { 311 ts->timer_list = timer_list; 312 ts->cb = cb; 313 ts->opaque = opaque; 314 ts->scale = scale; 315 ts->expire_time = -1; 316 } 317 318 void timer_free(QEMUTimer *ts) 319 { 320 g_free(ts); 321 } 322 323 static void timer_del_locked(QEMUTimerList *timer_list, QEMUTimer *ts) 324 { 325 QEMUTimer **pt, *t; 326 327 ts->expire_time = -1; 328 pt = &timer_list->active_timers; 329 for(;;) { 330 t = *pt; 331 if (!t) 332 break; 333 if (t == ts) { 334 *pt = t->next; 335 break; 336 } 337 pt = &t->next; 338 } 339 } 340 341 /* stop a timer, but do not dealloc it */ 342 void timer_del(QEMUTimer *ts) 343 { 344 QEMUTimerList *timer_list = ts->timer_list; 345 346 qemu_mutex_lock(&timer_list->active_timers_lock); 347 timer_del_locked(timer_list, ts); 348 qemu_mutex_unlock(&timer_list->active_timers_lock); 349 } 350 351 /* modify the current timer so that it will be fired when current_time 352 >= expire_time. The corresponding callback will be called. */ 353 void timer_mod_ns(QEMUTimer *ts, int64_t expire_time) 354 { 355 QEMUTimerList *timer_list = ts->timer_list; 356 QEMUTimer **pt, *t; 357 358 qemu_mutex_lock(&timer_list->active_timers_lock); 359 timer_del_locked(timer_list, ts); 360 361 /* add the timer in the sorted list */ 362 pt = &timer_list->active_timers; 363 for(;;) { 364 t = *pt; 365 if (!timer_expired_ns(t, expire_time)) { 366 break; 367 } 368 pt = &t->next; 369 } 370 ts->expire_time = MAX(expire_time, 0); 371 ts->next = *pt; 372 *pt = ts; 373 qemu_mutex_unlock(&timer_list->active_timers_lock); 374 375 /* Rearm if necessary */ 376 if (pt == &timer_list->active_timers) { 377 /* Interrupt execution to force deadline recalculation. */ 378 qemu_clock_warp(timer_list->clock->type); 379 timerlist_notify(timer_list); 380 } 381 } 382 383 void timer_mod(QEMUTimer *ts, int64_t expire_time) 384 { 385 timer_mod_ns(ts, expire_time * ts->scale); 386 } 387 388 bool timer_pending(QEMUTimer *ts) 389 { 390 return ts->expire_time >= 0; 391 } 392 393 bool timer_expired(QEMUTimer *timer_head, int64_t current_time) 394 { 395 return timer_expired_ns(timer_head, current_time * timer_head->scale); 396 } 397 398 bool timerlist_run_timers(QEMUTimerList *timer_list) 399 { 400 QEMUTimer *ts; 401 int64_t current_time; 402 bool progress = false; 403 QEMUTimerCB *cb; 404 void *opaque; 405 406 if (!timer_list->clock->enabled) { 407 return progress; 408 } 409 410 current_time = qemu_clock_get_ns(timer_list->clock->type); 411 for(;;) { 412 qemu_mutex_lock(&timer_list->active_timers_lock); 413 ts = timer_list->active_timers; 414 if (!timer_expired_ns(ts, current_time)) { 415 qemu_mutex_unlock(&timer_list->active_timers_lock); 416 break; 417 } 418 419 /* remove timer from the list before calling the callback */ 420 timer_list->active_timers = ts->next; 421 ts->next = NULL; 422 ts->expire_time = -1; 423 cb = ts->cb; 424 opaque = ts->opaque; 425 qemu_mutex_unlock(&timer_list->active_timers_lock); 426 427 /* run the callback (the timer list can be modified) */ 428 cb(opaque); 429 progress = true; 430 } 431 return progress; 432 } 433 434 bool qemu_clock_run_timers(QEMUClockType type) 435 { 436 return timerlist_run_timers(main_loop_tlg.tl[type]); 437 } 438 439 void timerlistgroup_init(QEMUTimerListGroup *tlg, 440 QEMUTimerListNotifyCB *cb, void *opaque) 441 { 442 QEMUClockType type; 443 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 444 tlg->tl[type] = timerlist_new(type, cb, opaque); 445 } 446 } 447 448 void timerlistgroup_deinit(QEMUTimerListGroup *tlg) 449 { 450 QEMUClockType type; 451 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 452 timerlist_free(tlg->tl[type]); 453 } 454 } 455 456 bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg) 457 { 458 QEMUClockType type; 459 bool progress = false; 460 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 461 progress |= timerlist_run_timers(tlg->tl[type]); 462 } 463 return progress; 464 } 465 466 int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg) 467 { 468 int64_t deadline = -1; 469 QEMUClockType type; 470 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 471 if (qemu_clock_use_for_deadline(tlg->tl[type]->clock->type)) { 472 deadline = qemu_soonest_timeout(deadline, 473 timerlist_deadline_ns( 474 tlg->tl[type])); 475 } 476 } 477 return deadline; 478 } 479 480 int64_t qemu_clock_get_ns(QEMUClockType type) 481 { 482 int64_t now, last; 483 QEMUClock *clock = qemu_clock_ptr(type); 484 485 switch (type) { 486 case QEMU_CLOCK_REALTIME: 487 return get_clock(); 488 default: 489 case QEMU_CLOCK_VIRTUAL: 490 if (use_icount) { 491 return cpu_get_icount(); 492 } else { 493 return cpu_get_clock(); 494 } 495 case QEMU_CLOCK_HOST: 496 now = get_clock_realtime(); 497 last = clock->last; 498 clock->last = now; 499 if (now < last) { 500 notifier_list_notify(&clock->reset_notifiers, &now); 501 } 502 return now; 503 } 504 } 505 506 void qemu_clock_register_reset_notifier(QEMUClockType type, 507 Notifier *notifier) 508 { 509 QEMUClock *clock = qemu_clock_ptr(type); 510 notifier_list_add(&clock->reset_notifiers, notifier); 511 } 512 513 void qemu_clock_unregister_reset_notifier(QEMUClockType type, 514 Notifier *notifier) 515 { 516 notifier_remove(notifier); 517 } 518 519 void init_clocks(void) 520 { 521 QEMUClockType type; 522 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 523 qemu_clock_init(type); 524 } 525 526 #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK 527 prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0); 528 #endif 529 } 530 531 uint64_t timer_expire_time_ns(QEMUTimer *ts) 532 { 533 return timer_pending(ts) ? ts->expire_time : -1; 534 } 535 536 bool qemu_clock_run_all_timers(void) 537 { 538 bool progress = false; 539 QEMUClockType type; 540 541 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 542 progress |= qemu_clock_run_timers(type); 543 } 544 545 return progress; 546 } 547