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 unsigned mm_period; 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 TIMECAPS tc; 632 633 memset(&tc, 0, sizeof(tc)); 634 timeGetDevCaps(&tc, sizeof(tc)); 635 636 mm_period = tc.wPeriodMin; 637 timeBeginPeriod(mm_period); 638 639 mm_timer = timeSetEvent(1, /* interval (ms) */ 640 mm_period, /* resolution */ 641 mm_alarm_handler, /* function */ 642 (DWORD_PTR)t, /* parameter */ 643 TIME_ONESHOT | TIME_CALLBACK_FUNCTION); 644 645 if (!mm_timer) { 646 fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", 647 GetLastError()); 648 timeEndPeriod(mm_period); 649 return -1; 650 } 651 652 return 0; 653 } 654 655 static void mm_stop_timer(struct qemu_alarm_timer *t) 656 { 657 timeKillEvent(mm_timer); 658 timeEndPeriod(mm_period); 659 } 660 661 static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta) 662 { 663 int64_t nearest_delta_ms = delta / 1000000; 664 if (nearest_delta_ms < 1) { 665 nearest_delta_ms = 1; 666 } 667 /* UINT_MAX can be 32 bit */ 668 if (nearest_delta_ms > UINT_MAX) { 669 nearest_delta_ms = UINT_MAX; 670 } 671 672 timeKillEvent(mm_timer); 673 mm_timer = timeSetEvent((unsigned int) nearest_delta_ms, 674 mm_period, 675 mm_alarm_handler, 676 (DWORD_PTR)t, 677 TIME_ONESHOT | TIME_CALLBACK_FUNCTION); 678 679 if (!mm_timer) { 680 fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n", 681 GetLastError()); 682 683 timeEndPeriod(mm_period); 684 exit(1); 685 } 686 } 687 688 static int win32_start_timer(struct qemu_alarm_timer *t) 689 { 690 HANDLE hTimer; 691 BOOLEAN success; 692 693 /* If you call ChangeTimerQueueTimer on a one-shot timer (its period 694 is zero) that has already expired, the timer is not updated. Since 695 creating a new timer is relatively expensive, set a bogus one-hour 696 interval in the dynticks case. */ 697 success = CreateTimerQueueTimer(&hTimer, 698 NULL, 699 host_alarm_handler, 700 t, 701 1, 702 3600000, 703 WT_EXECUTEINTIMERTHREAD); 704 705 if (!success) { 706 fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", 707 GetLastError()); 708 return -1; 709 } 710 711 t->timer = hTimer; 712 return 0; 713 } 714 715 static void win32_stop_timer(struct qemu_alarm_timer *t) 716 { 717 HANDLE hTimer = t->timer; 718 719 if (hTimer) { 720 DeleteTimerQueueTimer(NULL, hTimer, NULL); 721 } 722 } 723 724 static void win32_rearm_timer(struct qemu_alarm_timer *t, 725 int64_t nearest_delta_ns) 726 { 727 HANDLE hTimer = t->timer; 728 int64_t nearest_delta_ms; 729 BOOLEAN success; 730 731 nearest_delta_ms = nearest_delta_ns / 1000000; 732 if (nearest_delta_ms < 1) { 733 nearest_delta_ms = 1; 734 } 735 /* ULONG_MAX can be 32 bit */ 736 if (nearest_delta_ms > ULONG_MAX) { 737 nearest_delta_ms = ULONG_MAX; 738 } 739 success = ChangeTimerQueueTimer(NULL, 740 hTimer, 741 (unsigned long) nearest_delta_ms, 742 3600000); 743 744 if (!success) { 745 fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n", 746 GetLastError()); 747 exit(-1); 748 } 749 750 } 751 752 #endif /* _WIN32 */ 753 754 static void quit_timers(void) 755 { 756 struct qemu_alarm_timer *t = alarm_timer; 757 alarm_timer = NULL; 758 t->stop(t); 759 } 760 761 int init_timer_alarm(void) 762 { 763 struct qemu_alarm_timer *t = NULL; 764 int i, err = -1; 765 766 for (i = 0; alarm_timers[i].name; i++) { 767 t = &alarm_timers[i]; 768 769 err = t->start(t); 770 if (!err) 771 break; 772 } 773 774 if (err) { 775 err = -ENOENT; 776 goto fail; 777 } 778 779 /* first event is at time 0 */ 780 atexit(quit_timers); 781 t->pending = true; 782 alarm_timer = t; 783 784 return 0; 785 786 fail: 787 return err; 788 } 789 790