Annotation of qemu/qemu-timer.c, revision 1.1.1.5

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

unix.superglobalmegacorp.com