File:  [Qemu by Fabrice Bellard] / qemu / qemu-timer.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:17:17 2018 UTC (3 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, HEAD
qemu 1.0.1

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

unix.superglobalmegacorp.com