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 /* We rely on BQL to protect the timerlists */ 49 QLIST_HEAD(, QEMUTimerList) timerlists; 50 51 NotifierList reset_notifiers; 52 int64_t last; 53 54 QEMUClockType type; 55 bool enabled; 56 } QEMUClock; 57 58 QEMUTimerListGroup main_loop_tlg; 59 static QEMUClock qemu_clocks[QEMU_CLOCK_MAX]; 60 61 /* A QEMUTimerList is a list of timers attached to a clock. More 62 * than one QEMUTimerList can be attached to each clock, for instance 63 * used by different AioContexts / threads. Each clock also has 64 * a list of the QEMUTimerLists associated with it, in order that 65 * reenabling the clock can call all the notifiers. 66 */ 67 68 struct QEMUTimerList { 69 QEMUClock *clock; 70 QemuMutex active_timers_lock; 71 QEMUTimer *active_timers; 72 QLIST_ENTRY(QEMUTimerList) list; 73 QEMUTimerListNotifyCB *notify_cb; 74 void *notify_opaque; 75 76 /* lightweight method to mark the end of timerlist's running */ 77 QemuEvent timers_done_ev; 78 }; 79 80 /** 81 * qemu_clock_ptr: 82 * @type: type of clock 83 * 84 * Translate a clock type into a pointer to QEMUClock object. 85 * 86 * Returns: a pointer to the QEMUClock object 87 */ 88 static inline QEMUClock *qemu_clock_ptr(QEMUClockType type) 89 { 90 return &qemu_clocks[type]; 91 } 92 93 static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time) 94 { 95 return timer_head && (timer_head->expire_time <= current_time); 96 } 97 98 QEMUTimerList *timerlist_new(QEMUClockType type, 99 QEMUTimerListNotifyCB *cb, 100 void *opaque) 101 { 102 QEMUTimerList *timer_list; 103 QEMUClock *clock = qemu_clock_ptr(type); 104 105 timer_list = g_malloc0(sizeof(QEMUTimerList)); 106 qemu_event_init(&timer_list->timers_done_ev, false); 107 timer_list->clock = clock; 108 timer_list->notify_cb = cb; 109 timer_list->notify_opaque = opaque; 110 qemu_mutex_init(&timer_list->active_timers_lock); 111 QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list); 112 return timer_list; 113 } 114 115 void timerlist_free(QEMUTimerList *timer_list) 116 { 117 assert(!timerlist_has_timers(timer_list)); 118 if (timer_list->clock) { 119 QLIST_REMOVE(timer_list, list); 120 } 121 qemu_mutex_destroy(&timer_list->active_timers_lock); 122 g_free(timer_list); 123 } 124 125 static void qemu_clock_init(QEMUClockType type) 126 { 127 QEMUClock *clock = qemu_clock_ptr(type); 128 129 clock->type = type; 130 clock->enabled = true; 131 clock->last = INT64_MIN; 132 QLIST_INIT(&clock->timerlists); 133 notifier_list_init(&clock->reset_notifiers); 134 main_loop_tlg.tl[type] = timerlist_new(type, NULL, NULL); 135 } 136 137 bool qemu_clock_use_for_deadline(QEMUClockType type) 138 { 139 return !(use_icount && (type == QEMU_CLOCK_VIRTUAL)); 140 } 141 142 void qemu_clock_notify(QEMUClockType type) 143 { 144 QEMUTimerList *timer_list; 145 QEMUClock *clock = qemu_clock_ptr(type); 146 QLIST_FOREACH(timer_list, &clock->timerlists, list) { 147 timerlist_notify(timer_list); 148 } 149 } 150 151 /* Disabling the clock will wait for related timerlists to stop 152 * executing qemu_run_timers. Thus, this functions should not 153 * be used from the callback of a timer that is based on @clock. 154 * Doing so would cause a deadlock. 155 * 156 * Caller should hold BQL. 157 */ 158 void qemu_clock_enable(QEMUClockType type, bool enabled) 159 { 160 QEMUClock *clock = qemu_clock_ptr(type); 161 QEMUTimerList *tl; 162 bool old = clock->enabled; 163 clock->enabled = enabled; 164 if (enabled && !old) { 165 qemu_clock_notify(type); 166 } else if (!enabled && old) { 167 QLIST_FOREACH(tl, &clock->timerlists, list) { 168 qemu_event_wait(&tl->timers_done_ev); 169 } 170 } 171 } 172 173 bool timerlist_has_timers(QEMUTimerList *timer_list) 174 { 175 return !!timer_list->active_timers; 176 } 177 178 bool qemu_clock_has_timers(QEMUClockType type) 179 { 180 return timerlist_has_timers( 181 main_loop_tlg.tl[type]); 182 } 183 184 bool timerlist_expired(QEMUTimerList *timer_list) 185 { 186 int64_t expire_time; 187 188 qemu_mutex_lock(&timer_list->active_timers_lock); 189 if (!timer_list->active_timers) { 190 qemu_mutex_unlock(&timer_list->active_timers_lock); 191 return false; 192 } 193 expire_time = timer_list->active_timers->expire_time; 194 qemu_mutex_unlock(&timer_list->active_timers_lock); 195 196 return expire_time < qemu_clock_get_ns(timer_list->clock->type); 197 } 198 199 bool qemu_clock_expired(QEMUClockType type) 200 { 201 return timerlist_expired( 202 main_loop_tlg.tl[type]); 203 } 204 205 /* 206 * As above, but return -1 for no deadline, and do not cap to 2^32 207 * as we know the result is always positive. 208 */ 209 210 int64_t timerlist_deadline_ns(QEMUTimerList *timer_list) 211 { 212 int64_t delta; 213 int64_t expire_time; 214 215 if (!timer_list->clock->enabled) { 216 return -1; 217 } 218 219 /* The active timers list may be modified before the caller uses our return 220 * value but ->notify_cb() is called when the deadline changes. Therefore 221 * the caller should notice the change and there is no race condition. 222 */ 223 qemu_mutex_lock(&timer_list->active_timers_lock); 224 if (!timer_list->active_timers) { 225 qemu_mutex_unlock(&timer_list->active_timers_lock); 226 return -1; 227 } 228 expire_time = timer_list->active_timers->expire_time; 229 qemu_mutex_unlock(&timer_list->active_timers_lock); 230 231 delta = expire_time - qemu_clock_get_ns(timer_list->clock->type); 232 233 if (delta <= 0) { 234 return 0; 235 } 236 237 return delta; 238 } 239 240 /* Calculate the soonest deadline across all timerlists attached 241 * to the clock. This is used for the icount timeout so we 242 * ignore whether or not the clock should be used in deadline 243 * calculations. 244 */ 245 int64_t qemu_clock_deadline_ns_all(QEMUClockType type) 246 { 247 int64_t deadline = -1; 248 QEMUTimerList *timer_list; 249 QEMUClock *clock = qemu_clock_ptr(type); 250 QLIST_FOREACH(timer_list, &clock->timerlists, list) { 251 deadline = qemu_soonest_timeout(deadline, 252 timerlist_deadline_ns(timer_list)); 253 } 254 return deadline; 255 } 256 257 QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list) 258 { 259 return timer_list->clock->type; 260 } 261 262 QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type) 263 { 264 return main_loop_tlg.tl[type]; 265 } 266 267 void timerlist_notify(QEMUTimerList *timer_list) 268 { 269 if (timer_list->notify_cb) { 270 timer_list->notify_cb(timer_list->notify_opaque); 271 } else { 272 qemu_notify_event(); 273 } 274 } 275 276 /* Transition function to convert a nanosecond timeout to ms 277 * This is used where a system does not support ppoll 278 */ 279 int qemu_timeout_ns_to_ms(int64_t ns) 280 { 281 int64_t ms; 282 if (ns < 0) { 283 return -1; 284 } 285 286 if (!ns) { 287 return 0; 288 } 289 290 /* Always round up, because it's better to wait too long than to wait too 291 * little and effectively busy-wait 292 */ 293 ms = (ns + SCALE_MS - 1) / SCALE_MS; 294 295 /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */ 296 if (ms > (int64_t) INT32_MAX) { 297 ms = INT32_MAX; 298 } 299 300 return (int) ms; 301 } 302 303 304 /* qemu implementation of g_poll which uses a nanosecond timeout but is 305 * otherwise identical to g_poll 306 */ 307 int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout) 308 { 309 #ifdef CONFIG_PPOLL 310 if (timeout < 0) { 311 return ppoll((struct pollfd *)fds, nfds, NULL, NULL); 312 } else { 313 struct timespec ts; 314 ts.tv_sec = timeout / 1000000000LL; 315 ts.tv_nsec = timeout % 1000000000LL; 316 return ppoll((struct pollfd *)fds, nfds, &ts, NULL); 317 } 318 #else 319 return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout)); 320 #endif 321 } 322 323 324 void timer_init(QEMUTimer *ts, 325 QEMUTimerList *timer_list, int scale, 326 QEMUTimerCB *cb, void *opaque) 327 { 328 ts->timer_list = timer_list; 329 ts->cb = cb; 330 ts->opaque = opaque; 331 ts->scale = scale; 332 ts->expire_time = -1; 333 } 334 335 void timer_free(QEMUTimer *ts) 336 { 337 g_free(ts); 338 } 339 340 static void timer_del_locked(QEMUTimerList *timer_list, QEMUTimer *ts) 341 { 342 QEMUTimer **pt, *t; 343 344 ts->expire_time = -1; 345 pt = &timer_list->active_timers; 346 for(;;) { 347 t = *pt; 348 if (!t) 349 break; 350 if (t == ts) { 351 *pt = t->next; 352 break; 353 } 354 pt = &t->next; 355 } 356 } 357 358 static bool timer_mod_ns_locked(QEMUTimerList *timer_list, 359 QEMUTimer *ts, int64_t expire_time) 360 { 361 QEMUTimer **pt, *t; 362 363 /* add the timer in the sorted list */ 364 pt = &timer_list->active_timers; 365 for (;;) { 366 t = *pt; 367 if (!timer_expired_ns(t, expire_time)) { 368 break; 369 } 370 pt = &t->next; 371 } 372 ts->expire_time = MAX(expire_time, 0); 373 ts->next = *pt; 374 *pt = ts; 375 376 return pt == &timer_list->active_timers; 377 } 378 379 static void timerlist_rearm(QEMUTimerList *timer_list) 380 { 381 /* Interrupt execution to force deadline recalculation. */ 382 qemu_clock_warp(timer_list->clock->type); 383 timerlist_notify(timer_list); 384 } 385 386 /* stop a timer, but do not dealloc it */ 387 void timer_del(QEMUTimer *ts) 388 { 389 QEMUTimerList *timer_list = ts->timer_list; 390 391 qemu_mutex_lock(&timer_list->active_timers_lock); 392 timer_del_locked(timer_list, ts); 393 qemu_mutex_unlock(&timer_list->active_timers_lock); 394 } 395 396 /* modify the current timer so that it will be fired when current_time 397 >= expire_time. The corresponding callback will be called. */ 398 void timer_mod_ns(QEMUTimer *ts, int64_t expire_time) 399 { 400 QEMUTimerList *timer_list = ts->timer_list; 401 bool rearm; 402 403 qemu_mutex_lock(&timer_list->active_timers_lock); 404 timer_del_locked(timer_list, ts); 405 rearm = timer_mod_ns_locked(timer_list, ts, expire_time); 406 qemu_mutex_unlock(&timer_list->active_timers_lock); 407 408 if (rearm) { 409 timerlist_rearm(timer_list); 410 } 411 } 412 413 /* modify the current timer so that it will be fired when current_time 414 >= expire_time or the current deadline, whichever comes earlier. 415 The corresponding callback will be called. */ 416 void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time) 417 { 418 QEMUTimerList *timer_list = ts->timer_list; 419 bool rearm; 420 421 qemu_mutex_lock(&timer_list->active_timers_lock); 422 if (ts->expire_time == -1 || ts->expire_time > expire_time) { 423 if (ts->expire_time != -1) { 424 timer_del_locked(timer_list, ts); 425 } 426 rearm = timer_mod_ns_locked(timer_list, ts, expire_time); 427 } else { 428 rearm = false; 429 } 430 qemu_mutex_unlock(&timer_list->active_timers_lock); 431 432 if (rearm) { 433 timerlist_rearm(timer_list); 434 } 435 } 436 437 void timer_mod(QEMUTimer *ts, int64_t expire_time) 438 { 439 timer_mod_ns(ts, expire_time * ts->scale); 440 } 441 442 void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time) 443 { 444 timer_mod_anticipate_ns(ts, expire_time * ts->scale); 445 } 446 447 bool timer_pending(QEMUTimer *ts) 448 { 449 return ts->expire_time >= 0; 450 } 451 452 bool timer_expired(QEMUTimer *timer_head, int64_t current_time) 453 { 454 return timer_expired_ns(timer_head, current_time * timer_head->scale); 455 } 456 457 bool timerlist_run_timers(QEMUTimerList *timer_list) 458 { 459 QEMUTimer *ts; 460 int64_t current_time; 461 bool progress = false; 462 QEMUTimerCB *cb; 463 void *opaque; 464 465 qemu_event_reset(&timer_list->timers_done_ev); 466 if (!timer_list->clock->enabled) { 467 goto out; 468 } 469 470 current_time = qemu_clock_get_ns(timer_list->clock->type); 471 for(;;) { 472 qemu_mutex_lock(&timer_list->active_timers_lock); 473 ts = timer_list->active_timers; 474 if (!timer_expired_ns(ts, current_time)) { 475 qemu_mutex_unlock(&timer_list->active_timers_lock); 476 break; 477 } 478 479 /* remove timer from the list before calling the callback */ 480 timer_list->active_timers = ts->next; 481 ts->next = NULL; 482 ts->expire_time = -1; 483 cb = ts->cb; 484 opaque = ts->opaque; 485 qemu_mutex_unlock(&timer_list->active_timers_lock); 486 487 /* run the callback (the timer list can be modified) */ 488 cb(opaque); 489 progress = true; 490 } 491 492 out: 493 qemu_event_set(&timer_list->timers_done_ev); 494 return progress; 495 } 496 497 bool qemu_clock_run_timers(QEMUClockType type) 498 { 499 return timerlist_run_timers(main_loop_tlg.tl[type]); 500 } 501 502 void timerlistgroup_init(QEMUTimerListGroup *tlg, 503 QEMUTimerListNotifyCB *cb, void *opaque) 504 { 505 QEMUClockType type; 506 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 507 tlg->tl[type] = timerlist_new(type, cb, opaque); 508 } 509 } 510 511 void timerlistgroup_deinit(QEMUTimerListGroup *tlg) 512 { 513 QEMUClockType type; 514 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 515 timerlist_free(tlg->tl[type]); 516 } 517 } 518 519 bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg) 520 { 521 QEMUClockType type; 522 bool progress = false; 523 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 524 progress |= timerlist_run_timers(tlg->tl[type]); 525 } 526 return progress; 527 } 528 529 int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg) 530 { 531 int64_t deadline = -1; 532 QEMUClockType type; 533 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 534 if (qemu_clock_use_for_deadline(tlg->tl[type]->clock->type)) { 535 deadline = qemu_soonest_timeout(deadline, 536 timerlist_deadline_ns( 537 tlg->tl[type])); 538 } 539 } 540 return deadline; 541 } 542 543 int64_t qemu_clock_get_ns(QEMUClockType type) 544 { 545 int64_t now, last; 546 QEMUClock *clock = qemu_clock_ptr(type); 547 548 switch (type) { 549 case QEMU_CLOCK_REALTIME: 550 return get_clock(); 551 default: 552 case QEMU_CLOCK_VIRTUAL: 553 if (use_icount) { 554 return cpu_get_icount(); 555 } else { 556 return cpu_get_clock(); 557 } 558 case QEMU_CLOCK_HOST: 559 now = get_clock_realtime(); 560 last = clock->last; 561 clock->last = now; 562 if (now < last) { 563 notifier_list_notify(&clock->reset_notifiers, &now); 564 } 565 return now; 566 } 567 } 568 569 void qemu_clock_register_reset_notifier(QEMUClockType type, 570 Notifier *notifier) 571 { 572 QEMUClock *clock = qemu_clock_ptr(type); 573 notifier_list_add(&clock->reset_notifiers, notifier); 574 } 575 576 void qemu_clock_unregister_reset_notifier(QEMUClockType type, 577 Notifier *notifier) 578 { 579 notifier_remove(notifier); 580 } 581 582 void init_clocks(void) 583 { 584 QEMUClockType type; 585 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 586 qemu_clock_init(type); 587 } 588 589 #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK 590 prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0); 591 #endif 592 } 593 594 uint64_t timer_expire_time_ns(QEMUTimer *ts) 595 { 596 return timer_pending(ts) ? ts->expire_time : -1; 597 } 598 599 bool qemu_clock_run_all_timers(void) 600 { 601 bool progress = false; 602 QEMUClockType type; 603 604 for (type = 0; type < QEMU_CLOCK_MAX; type++) { 605 progress |= qemu_clock_run_timers(type); 606 } 607 608 return progress; 609 } 610