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.h" 26 #include "net.h" 27 #include "monitor.h" 28 #include "console.h" 29 30 #include "hw/hw.h" 31 32 #include "qemu-timer.h" 33 34 #ifdef __FreeBSD__ 35 #include <sys/param.h> 36 #endif 37 38 #ifdef _WIN32 39 #include <mmsystem.h> 40 #endif 41 42 /***********************************************************/ 43 /* timers */ 44 45 #define QEMU_CLOCK_REALTIME 0 46 #define QEMU_CLOCK_VIRTUAL 1 47 #define QEMU_CLOCK_HOST 2 48 49 struct QEMUClock { 50 QEMUTimer *active_timers; 51 52 NotifierList reset_notifiers; 53 int64_t last; 54 55 int type; 56 bool enabled; 57 }; 58 59 struct QEMUTimer { 60 int64_t expire_time; /* in nanoseconds */ 61 QEMUClock *clock; 62 QEMUTimerCB *cb; 63 void *opaque; 64 QEMUTimer *next; 65 int scale; 66 }; 67 68 struct qemu_alarm_timer { 69 char const *name; 70 int (*start)(struct qemu_alarm_timer *t); 71 void (*stop)(struct qemu_alarm_timer *t); 72 void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns); 73 #if defined(__linux__) 74 timer_t timer; 75 int fd; 76 #elif defined(_WIN32) 77 HANDLE timer; 78 #endif 79 bool expired; 80 bool pending; 81 }; 82 83 static struct qemu_alarm_timer *alarm_timer; 84 85 static bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time) 86 { 87 return timer_head && (timer_head->expire_time <= current_time); 88 } 89 90 static int64_t qemu_next_alarm_deadline(void) 91 { 92 int64_t delta = INT64_MAX; 93 int64_t rtdelta; 94 95 if (!use_icount && vm_clock->enabled && vm_clock->active_timers) { 96 delta = vm_clock->active_timers->expire_time - 97 qemu_get_clock_ns(vm_clock); 98 } 99 if (host_clock->enabled && host_clock->active_timers) { 100 int64_t hdelta = host_clock->active_timers->expire_time - 101 qemu_get_clock_ns(host_clock); 102 if (hdelta < delta) { 103 delta = hdelta; 104 } 105 } 106 if (rt_clock->enabled && rt_clock->active_timers) { 107 rtdelta = (rt_clock->active_timers->expire_time - 108 qemu_get_clock_ns(rt_clock)); 109 if (rtdelta < delta) { 110 delta = rtdelta; 111 } 112 } 113 114 return delta; 115 } 116 117 static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t) 118 { 119 int64_t nearest_delta_ns; 120 if (!rt_clock->active_timers && 121 !vm_clock->active_timers && 122 !host_clock->active_timers) { 123 return; 124 } 125 nearest_delta_ns = qemu_next_alarm_deadline(); 126 t->rearm(t, nearest_delta_ns); 127 } 128 129 /* TODO: MIN_TIMER_REARM_NS should be optimized */ 130 #define MIN_TIMER_REARM_NS 250000 131 132 #ifdef _WIN32 133 134 static int mm_start_timer(struct qemu_alarm_timer *t); 135 static void mm_stop_timer(struct qemu_alarm_timer *t); 136 static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); 137 138 static int win32_start_timer(struct qemu_alarm_timer *t); 139 static void win32_stop_timer(struct qemu_alarm_timer *t); 140 static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); 141 142 #else 143 144 static int unix_start_timer(struct qemu_alarm_timer *t); 145 static void unix_stop_timer(struct qemu_alarm_timer *t); 146 static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); 147 148 #ifdef __linux__ 149 150 static int dynticks_start_timer(struct qemu_alarm_timer *t); 151 static void dynticks_stop_timer(struct qemu_alarm_timer *t); 152 static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta); 153 154 #endif /* __linux__ */ 155 156 #endif /* _WIN32 */ 157 158 static struct qemu_alarm_timer alarm_timers[] = { 159 #ifndef _WIN32 160 #ifdef __linux__ 161 {"dynticks", dynticks_start_timer, 162 dynticks_stop_timer, dynticks_rearm_timer}, 163 #endif 164 {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer}, 165 #else 166 {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer}, 167 {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer}, 168 #endif 169 {NULL, } 170 }; 171 172 static void show_available_alarms(void) 173 { 174 int i; 175 176 printf("Available alarm timers, in order of precedence:\n"); 177 for (i = 0; alarm_timers[i].name; i++) 178 printf("%s\n", alarm_timers[i].name); 179 } 180 181 void configure_alarms(char const *opt) 182 { 183 int i; 184 int cur = 0; 185 int count = ARRAY_SIZE(alarm_timers) - 1; 186 char *arg; 187 char *name; 188 struct qemu_alarm_timer tmp; 189 190 if (!strcmp(opt, "?")) { 191 show_available_alarms(); 192 exit(0); 193 } 194 195 arg = g_strdup(opt); 196 197 /* Reorder the array */ 198 name = strtok(arg, ","); 199 while (name) { 200 for (i = 0; i < count && alarm_timers[i].name; i++) { 201 if (!strcmp(alarm_timers[i].name, name)) 202 break; 203 } 204 205 if (i == count) { 206 fprintf(stderr, "Unknown clock %s\n", name); 207 goto next; 208 } 209 210 if (i < cur) 211 /* Ignore */ 212 goto next; 213 214 /* Swap */ 215 tmp = alarm_timers[i]; 216 alarm_timers[i] = alarm_timers[cur]; 217 alarm_timers[cur] = tmp; 218 219 cur++; 220 next: 221 name = strtok(NULL, ","); 222 } 223 224 g_free(arg); 225 226 if (cur) { 227 /* Disable remaining timers */ 228 for (i = cur; i < count; i++) 229 alarm_timers[i].name = NULL; 230 } else { 231 show_available_alarms(); 232 exit(1); 233 } 234 } 235 236 QEMUClock *rt_clock; 237 QEMUClock *vm_clock; 238 QEMUClock *host_clock; 239 240 static QEMUClock *qemu_new_clock(int type) 241 { 242 QEMUClock *clock; 243 244 clock = g_malloc0(sizeof(QEMUClock)); 245 clock->type = type; 246 clock->enabled = true; 247 clock->last = INT64_MIN; 248 notifier_list_init(&clock->reset_notifiers); 249 return clock; 250 } 251 252 void qemu_clock_enable(QEMUClock *clock, bool enabled) 253 { 254 bool old = clock->enabled; 255 clock->enabled = enabled; 256 if (enabled && !old) { 257 qemu_rearm_alarm_timer(alarm_timer); 258 } 259 } 260 261 int64_t qemu_clock_has_timers(QEMUClock *clock) 262 { 263 return !!clock->active_timers; 264 } 265 266 int64_t qemu_clock_expired(QEMUClock *clock) 267 { 268 return (clock->active_timers && 269 clock->active_timers->expire_time < qemu_get_clock_ns(clock)); 270 } 271 272 int64_t qemu_clock_deadline(QEMUClock *clock) 273 { 274 /* To avoid problems with overflow limit this to 2^32. */ 275 int64_t delta = INT32_MAX; 276 277 if (clock->active_timers) { 278 delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock); 279 } 280 if (delta < 0) { 281 delta = 0; 282 } 283 return delta; 284 } 285 286 QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale, 287 QEMUTimerCB *cb, void *opaque) 288 { 289 QEMUTimer *ts; 290 291 ts = g_malloc0(sizeof(QEMUTimer)); 292 ts->clock = clock; 293 ts->cb = cb; 294 ts->opaque = opaque; 295 ts->scale = scale; 296 return ts; 297 } 298 299 void qemu_free_timer(QEMUTimer *ts) 300 { 301 g_free(ts); 302 } 303 304 /* stop a timer, but do not dealloc it */ 305 void qemu_del_timer(QEMUTimer *ts) 306 { 307 QEMUTimer **pt, *t; 308 309 /* NOTE: this code must be signal safe because 310 qemu_timer_expired() can be called from a signal. */ 311 pt = &ts->clock->active_timers; 312 for(;;) { 313 t = *pt; 314 if (!t) 315 break; 316 if (t == ts) { 317 *pt = t->next; 318 break; 319 } 320 pt = &t->next; 321 } 322 } 323 324 /* modify the current timer so that it will be fired when current_time 325 >= expire_time. The corresponding callback will be called. */ 326 void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) 327 { 328 QEMUTimer **pt, *t; 329 330 qemu_del_timer(ts); 331 332 /* add the timer in the sorted list */ 333 /* NOTE: this code must be signal safe because 334 qemu_timer_expired() can be called from a signal. */ 335 pt = &ts->clock->active_timers; 336 for(;;) { 337 t = *pt; 338 if (!qemu_timer_expired_ns(t, expire_time)) { 339 break; 340 } 341 pt = &t->next; 342 } 343 ts->expire_time = expire_time; 344 ts->next = *pt; 345 *pt = ts; 346 347 /* Rearm if necessary */ 348 if (pt == &ts->clock->active_timers) { 349 if (!alarm_timer->pending) { 350 qemu_rearm_alarm_timer(alarm_timer); 351 } 352 /* Interrupt execution to force deadline recalculation. */ 353 qemu_clock_warp(ts->clock); 354 if (use_icount) { 355 qemu_notify_event(); 356 } 357 } 358 } 359 360 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) 361 { 362 qemu_mod_timer_ns(ts, expire_time * ts->scale); 363 } 364 365 bool qemu_timer_pending(QEMUTimer *ts) 366 { 367 QEMUTimer *t; 368 for (t = ts->clock->active_timers; t != NULL; t = t->next) { 369 if (t == ts) { 370 return true; 371 } 372 } 373 return false; 374 } 375 376 bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) 377 { 378 return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale); 379 } 380 381 void qemu_run_timers(QEMUClock *clock) 382 { 383 QEMUTimer **ptimer_head, *ts; 384 int64_t current_time; 385 386 if (!clock->enabled) 387 return; 388 389 current_time = qemu_get_clock_ns(clock); 390 ptimer_head = &clock->active_timers; 391 for(;;) { 392 ts = *ptimer_head; 393 if (!qemu_timer_expired_ns(ts, current_time)) { 394 break; 395 } 396 /* remove timer from the list before calling the callback */ 397 *ptimer_head = ts->next; 398 ts->next = NULL; 399 400 /* run the callback (the timer list can be modified) */ 401 ts->cb(ts->opaque); 402 } 403 } 404 405 int64_t qemu_get_clock_ns(QEMUClock *clock) 406 { 407 int64_t now, last; 408 409 switch(clock->type) { 410 case QEMU_CLOCK_REALTIME: 411 return get_clock(); 412 default: 413 case QEMU_CLOCK_VIRTUAL: 414 if (use_icount) { 415 return cpu_get_icount(); 416 } else { 417 return cpu_get_clock(); 418 } 419 case QEMU_CLOCK_HOST: 420 now = get_clock_realtime(); 421 last = clock->last; 422 clock->last = now; 423 if (now < last) { 424 notifier_list_notify(&clock->reset_notifiers, &now); 425 } 426 return now; 427 } 428 } 429 430 void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier) 431 { 432 notifier_list_add(&clock->reset_notifiers, notifier); 433 } 434 435 void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier) 436 { 437 notifier_remove(notifier); 438 } 439 440 void init_clocks(void) 441 { 442 rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME); 443 vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL); 444 host_clock = qemu_new_clock(QEMU_CLOCK_HOST); 445 } 446 447 uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts) 448 { 449 return qemu_timer_pending(ts) ? ts->expire_time : -1; 450 } 451 452 void qemu_run_all_timers(void) 453 { 454 alarm_timer->pending = false; 455 456 /* vm time timers */ 457 qemu_run_timers(vm_clock); 458 qemu_run_timers(rt_clock); 459 qemu_run_timers(host_clock); 460 461 /* rearm timer, if not periodic */ 462 if (alarm_timer->expired) { 463 alarm_timer->expired = false; 464 qemu_rearm_alarm_timer(alarm_timer); 465 } 466 } 467 468 #ifdef _WIN32 469 static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused) 470 #else 471 static void host_alarm_handler(int host_signum) 472 #endif 473 { 474 struct qemu_alarm_timer *t = alarm_timer; 475 if (!t) 476 return; 477 478 t->expired = true; 479 t->pending = true; 480 qemu_notify_event(); 481 } 482 483 #if defined(__linux__) 484 485 #include "compatfd.h" 486 487 static int dynticks_start_timer(struct qemu_alarm_timer *t) 488 { 489 struct sigevent ev; 490 timer_t host_timer; 491 struct sigaction act; 492 493 sigfillset(&act.sa_mask); 494 act.sa_flags = 0; 495 act.sa_handler = host_alarm_handler; 496 497 sigaction(SIGALRM, &act, NULL); 498 499 /* 500 * Initialize ev struct to 0 to avoid valgrind complaining 501 * about uninitialized data in timer_create call 502 */ 503 memset(&ev, 0, sizeof(ev)); 504 ev.sigev_value.sival_int = 0; 505 ev.sigev_notify = SIGEV_SIGNAL; 506 #ifdef SIGEV_THREAD_ID 507 if (qemu_signalfd_available()) { 508 ev.sigev_notify = SIGEV_THREAD_ID; 509 ev._sigev_un._tid = qemu_get_thread_id(); 510 } 511 #endif /* SIGEV_THREAD_ID */ 512 ev.sigev_signo = SIGALRM; 513 514 if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) { 515 perror("timer_create"); 516 return -1; 517 } 518 519 t->timer = host_timer; 520 521 return 0; 522 } 523 524 static void dynticks_stop_timer(struct qemu_alarm_timer *t) 525 { 526 timer_t host_timer = t->timer; 527 528 timer_delete(host_timer); 529 } 530 531 static void dynticks_rearm_timer(struct qemu_alarm_timer *t, 532 int64_t nearest_delta_ns) 533 { 534 timer_t host_timer = t->timer; 535 struct itimerspec timeout; 536 int64_t current_ns; 537 538 if (nearest_delta_ns < MIN_TIMER_REARM_NS) 539 nearest_delta_ns = MIN_TIMER_REARM_NS; 540 541 /* check whether a timer is already running */ 542 if (timer_gettime(host_timer, &timeout)) { 543 perror("gettime"); 544 fprintf(stderr, "Internal timer error: aborting\n"); 545 exit(1); 546 } 547 current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec; 548 if (current_ns && current_ns <= nearest_delta_ns) 549 return; 550 551 timeout.it_interval.tv_sec = 0; 552 timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */ 553 timeout.it_value.tv_sec = nearest_delta_ns / 1000000000; 554 timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000; 555 if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) { 556 perror("settime"); 557 fprintf(stderr, "Internal timer error: aborting\n"); 558 exit(1); 559 } 560 } 561 562 #endif /* defined(__linux__) */ 563 564 #if !defined(_WIN32) 565 566 static int unix_start_timer(struct qemu_alarm_timer *t) 567 { 568 struct sigaction act; 569 570 /* timer signal */ 571 sigfillset(&act.sa_mask); 572 act.sa_flags = 0; 573 act.sa_handler = host_alarm_handler; 574 575 sigaction(SIGALRM, &act, NULL); 576 return 0; 577 } 578 579 static void unix_rearm_timer(struct qemu_alarm_timer *t, 580 int64_t nearest_delta_ns) 581 { 582 struct itimerval itv; 583 int err; 584 585 if (nearest_delta_ns < MIN_TIMER_REARM_NS) 586 nearest_delta_ns = MIN_TIMER_REARM_NS; 587 588 itv.it_interval.tv_sec = 0; 589 itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */ 590 itv.it_value.tv_sec = nearest_delta_ns / 1000000000; 591 itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000; 592 err = setitimer(ITIMER_REAL, &itv, NULL); 593 if (err) { 594 perror("setitimer"); 595 fprintf(stderr, "Internal timer error: aborting\n"); 596 exit(1); 597 } 598 } 599 600 static void unix_stop_timer(struct qemu_alarm_timer *t) 601 { 602 struct itimerval itv; 603 604 memset(&itv, 0, sizeof(itv)); 605 setitimer(ITIMER_REAL, &itv, NULL); 606 } 607 608 #endif /* !defined(_WIN32) */ 609 610 611 #ifdef _WIN32 612 613 static MMRESULT mm_timer; 614 static TIMECAPS mm_tc; 615 616 static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg, 617 DWORD_PTR dwUser, DWORD_PTR dw1, 618 DWORD_PTR dw2) 619 { 620 struct qemu_alarm_timer *t = alarm_timer; 621 if (!t) { 622 return; 623 } 624 t->expired = true; 625 t->pending = true; 626 qemu_notify_event(); 627 } 628 629 static int mm_start_timer(struct qemu_alarm_timer *t) 630 { 631 timeGetDevCaps(&mm_tc, sizeof(mm_tc)); 632 633 timeBeginPeriod(mm_tc.wPeriodMin); 634 635 mm_timer = timeSetEvent(mm_tc.wPeriodMin, /* interval (ms) */ 636 mm_tc.wPeriodMin, /* resolution */ 637 mm_alarm_handler, /* function */ 638 (DWORD_PTR)t, /* parameter */ 639 TIME_ONESHOT | TIME_CALLBACK_FUNCTION); 640 641 if (!mm_timer) { 642 fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", 643 GetLastError()); 644 timeEndPeriod(mm_tc.wPeriodMin); 645 return -1; 646 } 647 648 return 0; 649 } 650 651 static void mm_stop_timer(struct qemu_alarm_timer *t) 652 { 653 timeKillEvent(mm_timer); 654 timeEndPeriod(mm_tc.wPeriodMin); 655 } 656 657 static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta) 658 { 659 int64_t nearest_delta_ms = delta / 1000000; 660 if (nearest_delta_ms < mm_tc.wPeriodMin) { 661 nearest_delta_ms = mm_tc.wPeriodMin; 662 } else if (nearest_delta_ms > mm_tc.wPeriodMax) { 663 nearest_delta_ms = mm_tc.wPeriodMax; 664 } 665 666 timeKillEvent(mm_timer); 667 mm_timer = timeSetEvent((UINT)nearest_delta_ms, 668 mm_tc.wPeriodMin, 669 mm_alarm_handler, 670 (DWORD_PTR)t, 671 TIME_ONESHOT | TIME_CALLBACK_FUNCTION); 672 673 if (!mm_timer) { 674 fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n", 675 GetLastError()); 676 677 timeEndPeriod(mm_tc.wPeriodMin); 678 exit(1); 679 } 680 } 681 682 static int win32_start_timer(struct qemu_alarm_timer *t) 683 { 684 HANDLE hTimer; 685 BOOLEAN success; 686 687 /* If you call ChangeTimerQueueTimer on a one-shot timer (its period 688 is zero) that has already expired, the timer is not updated. Since 689 creating a new timer is relatively expensive, set a bogus one-hour 690 interval in the dynticks case. */ 691 success = CreateTimerQueueTimer(&hTimer, 692 NULL, 693 host_alarm_handler, 694 t, 695 1, 696 3600000, 697 WT_EXECUTEINTIMERTHREAD); 698 699 if (!success) { 700 fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", 701 GetLastError()); 702 return -1; 703 } 704 705 t->timer = hTimer; 706 return 0; 707 } 708 709 static void win32_stop_timer(struct qemu_alarm_timer *t) 710 { 711 HANDLE hTimer = t->timer; 712 713 if (hTimer) { 714 DeleteTimerQueueTimer(NULL, hTimer, NULL); 715 } 716 } 717 718 static void win32_rearm_timer(struct qemu_alarm_timer *t, 719 int64_t nearest_delta_ns) 720 { 721 HANDLE hTimer = t->timer; 722 int64_t nearest_delta_ms; 723 BOOLEAN success; 724 725 nearest_delta_ms = nearest_delta_ns / 1000000; 726 if (nearest_delta_ms < 1) { 727 nearest_delta_ms = 1; 728 } 729 /* ULONG_MAX can be 32 bit */ 730 if (nearest_delta_ms > ULONG_MAX) { 731 nearest_delta_ms = ULONG_MAX; 732 } 733 success = ChangeTimerQueueTimer(NULL, 734 hTimer, 735 (unsigned long) nearest_delta_ms, 736 3600000); 737 738 if (!success) { 739 fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n", 740 GetLastError()); 741 exit(-1); 742 } 743 744 } 745 746 #endif /* _WIN32 */ 747 748 static void quit_timers(void) 749 { 750 struct qemu_alarm_timer *t = alarm_timer; 751 alarm_timer = NULL; 752 t->stop(t); 753 } 754 755 int init_timer_alarm(void) 756 { 757 struct qemu_alarm_timer *t = NULL; 758 int i, err = -1; 759 760 for (i = 0; alarm_timers[i].name; i++) { 761 t = &alarm_timers[i]; 762 763 err = t->start(t); 764 if (!err) 765 break; 766 } 767 768 if (err) { 769 err = -ENOENT; 770 goto fail; 771 } 772 773 /* first event is at time 0 */ 774 atexit(quit_timers); 775 t->pending = true; 776 alarm_timer = t; 777 778 return 0; 779 780 fail: 781 return err; 782 } 783 784