Diff for /qemu/qemu-timer.c between versions 1.1.1.4 and 1.1.1.5

version 1.1.1.4, 2018/04/24 19:17:17 version 1.1.1.5, 2018/04/24 19:34:28
Line 29 Line 29
   
 #include "hw/hw.h"  #include "hw/hw.h"
   
 #include <unistd.h>  #include "qemu-timer.h"
 #include <fcntl.h>  
 #include <time.h>  
 #include <errno.h>  
 #include <sys/time.h>  
 #include <signal.h>  
 #ifdef __FreeBSD__  
 #include <sys/param.h>  
 #endif  
   
 #ifdef _WIN32  #ifdef _WIN32
 #include <windows.h>  
 #include <mmsystem.h>  #include <mmsystem.h>
 #endif  #endif
   
 #include "qemu-timer.h"  
   
 /***********************************************************/  /***********************************************************/
 /* timers */  /* timers */
   
Line 54 Line 43
 #define QEMU_CLOCK_HOST     2  #define QEMU_CLOCK_HOST     2
   
 struct QEMUClock {  struct QEMUClock {
     int type;  
     int enabled;  
   
     QEMUTimer *active_timers;      QEMUTimer *active_timers;
   
     NotifierList reset_notifiers;      NotifierList reset_notifiers;
     int64_t last;      int64_t last;
   
       int type;
       bool enabled;
 };  };
   
 struct QEMUTimer {  struct QEMUTimer {
     QEMUClock *clock;  
     int64_t expire_time;        /* in nanoseconds */      int64_t expire_time;        /* in nanoseconds */
     int scale;      QEMUClock *clock;
     QEMUTimerCB *cb;      QEMUTimerCB *cb;
     void *opaque;      void *opaque;
     struct QEMUTimer *next;      QEMUTimer *next;
       int scale;
 };  };
   
 struct qemu_alarm_timer {  struct qemu_alarm_timer {
Line 78  struct qemu_alarm_timer { Line 67  struct qemu_alarm_timer {
     void (*stop)(struct qemu_alarm_timer *t);      void (*stop)(struct qemu_alarm_timer *t);
     void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);      void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
 #if defined(__linux__)  #if defined(__linux__)
     int fd;  
     timer_t timer;      timer_t timer;
       int fd;
 #elif defined(_WIN32)  #elif defined(_WIN32)
     HANDLE timer;      HANDLE timer;
 #endif  #endif
     char expired;      bool expired;
     char pending;      bool pending;
 };  };
   
 static struct qemu_alarm_timer *alarm_timer;  static struct qemu_alarm_timer *alarm_timer;
Line 94  static bool qemu_timer_expired_ns(QEMUTi Line 83  static bool qemu_timer_expired_ns(QEMUTi
     return timer_head && (timer_head->expire_time <= current_time);      return timer_head && (timer_head->expire_time <= current_time);
 }  }
   
 int qemu_alarm_pending(void)  
 {  
     return alarm_timer->pending;  
 }  
   
 static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)  
 {  
     return !!t->rearm;  
 }  
   
 static int64_t qemu_next_alarm_deadline(void)  static int64_t qemu_next_alarm_deadline(void)
 {  {
     int64_t delta;      int64_t delta = INT64_MAX;
     int64_t rtdelta;      int64_t rtdelta;
   
     if (!use_icount && vm_clock->active_timers) {      if (!use_icount && vm_clock->enabled && vm_clock->active_timers) {
         delta = vm_clock->active_timers->expire_time -          delta = vm_clock->active_timers->expire_time -
                      qemu_get_clock_ns(vm_clock);                       qemu_get_clock_ns(vm_clock);
     } else {  
         delta = INT32_MAX;  
     }      }
     if (host_clock->active_timers) {      if (host_clock->enabled && host_clock->active_timers) {
         int64_t hdelta = host_clock->active_timers->expire_time -          int64_t hdelta = host_clock->active_timers->expire_time -
                  qemu_get_clock_ns(host_clock);                   qemu_get_clock_ns(host_clock);
         if (hdelta < delta) {          if (hdelta < delta) {
             delta = hdelta;              delta = hdelta;
         }          }
     }      }
     if (rt_clock->active_timers) {      if (rt_clock->enabled && rt_clock->active_timers) {
         rtdelta = (rt_clock->active_timers->expire_time -          rtdelta = (rt_clock->active_timers->expire_time -
                  qemu_get_clock_ns(rt_clock));                   qemu_get_clock_ns(rt_clock));
         if (rtdelta < delta) {          if (rtdelta < delta) {
Line 136  static int64_t qemu_next_alarm_deadline( Line 113  static int64_t qemu_next_alarm_deadline(
 static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)  static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
 {  {
     int64_t nearest_delta_ns;      int64_t nearest_delta_ns;
     assert(alarm_has_dynticks(t));  
     if (!rt_clock->active_timers &&      if (!rt_clock->active_timers &&
         !vm_clock->active_timers &&          !vm_clock->active_timers &&
         !host_clock->active_timers) {          !host_clock->active_timers) {
Line 263  static QEMUClock *qemu_new_clock(int typ Line 239  static QEMUClock *qemu_new_clock(int typ
   
     clock = g_malloc0(sizeof(QEMUClock));      clock = g_malloc0(sizeof(QEMUClock));
     clock->type = type;      clock->type = type;
     clock->enabled = 1;      clock->enabled = true;
     clock->last = INT64_MIN;      clock->last = INT64_MIN;
     notifier_list_init(&clock->reset_notifiers);      notifier_list_init(&clock->reset_notifiers);
     return clock;      return clock;
 }  }
   
 void qemu_clock_enable(QEMUClock *clock, int enabled)  void qemu_clock_enable(QEMUClock *clock, bool enabled)
 {  {
     bool old = clock->enabled;      bool old = clock->enabled;
     clock->enabled = enabled;      clock->enabled = enabled;
Line 382  void qemu_mod_timer(QEMUTimer *ts, int64 Line 358  void qemu_mod_timer(QEMUTimer *ts, int64
     qemu_mod_timer_ns(ts, expire_time * ts->scale);      qemu_mod_timer_ns(ts, expire_time * ts->scale);
 }  }
   
 int qemu_timer_pending(QEMUTimer *ts)  bool qemu_timer_pending(QEMUTimer *ts)
 {  {
     QEMUTimer *t;      QEMUTimer *t;
     for (t = ts->clock->active_timers; t != NULL; t = t->next) {      for (t = ts->clock->active_timers; t != NULL; t = t->next) {
         if (t == ts)          if (t == ts) {
             return 1;              return true;
           }
     }      }
     return 0;      return false;
 }  }
   
 int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)  bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
 {  {
     return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);      return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
 }  }
   
 static void qemu_run_timers(QEMUClock *clock)  void qemu_run_timers(QEMUClock *clock)
 {  {
     QEMUTimer **ptimer_head, *ts;      QEMUTimer **ptimer_head, *ts;
     int64_t current_time;      int64_t current_time;
Line 453  void qemu_register_clock_reset_notifier( Line 430  void qemu_register_clock_reset_notifier(
   
 void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)  void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
 {  {
     notifier_list_remove(&clock->reset_notifiers, notifier);      notifier_remove(notifier);
 }  }
   
 void init_clocks(void)  void init_clocks(void)
Line 470  uint64_t qemu_timer_expire_time_ns(QEMUT Line 447  uint64_t qemu_timer_expire_time_ns(QEMUT
   
 void qemu_run_all_timers(void)  void qemu_run_all_timers(void)
 {  {
     alarm_timer->pending = 0;      alarm_timer->pending = false;
   
     /* rearm timer, if not periodic */  
     if (alarm_timer->expired) {  
         alarm_timer->expired = 0;  
         qemu_rearm_alarm_timer(alarm_timer);  
     }  
   
     /* vm time timers */      /* vm time timers */
     qemu_run_timers(vm_clock);      qemu_run_timers(vm_clock);
     qemu_run_timers(rt_clock);      qemu_run_timers(rt_clock);
     qemu_run_timers(host_clock);      qemu_run_timers(host_clock);
   
       /* rearm timer, if not periodic */
       if (alarm_timer->expired) {
           alarm_timer->expired = false;
           qemu_rearm_alarm_timer(alarm_timer);
       }
 }  }
   
 #ifdef _WIN32  #ifdef _WIN32
Line 494  static void host_alarm_handler(int host_ Line 471  static void host_alarm_handler(int host_
     if (!t)      if (!t)
         return;          return;
   
 #if 0      t->expired = true;
 #define DISP_FREQ 1000      t->pending = true;
     {      qemu_notify_event();
         static int64_t delta_min = INT64_MAX;  
         static int64_t delta_max, delta_cum, last_clock, delta, ti;  
         static int count;  
         ti = qemu_get_clock_ns(vm_clock);  
         if (last_clock != 0) {  
             delta = ti - last_clock;  
             if (delta < delta_min)  
                 delta_min = delta;  
             if (delta > delta_max)  
                 delta_max = delta;  
             delta_cum += delta;  
             if (++count == DISP_FREQ) {  
                 printf("timer: min=%" PRId64 " us max=%" PRId64 " us avg=%" PRId64 " us avg_freq=%0.3f Hz\n",  
                        muldiv64(delta_min, 1000000, get_ticks_per_sec()),  
                        muldiv64(delta_max, 1000000, get_ticks_per_sec()),  
                        muldiv64(delta_cum, 1000000 / DISP_FREQ, get_ticks_per_sec()),  
                        (double)get_ticks_per_sec() / ((double)delta_cum / DISP_FREQ));  
                 count = 0;  
                 delta_min = INT64_MAX;  
                 delta_max = 0;  
                 delta_cum = 0;  
             }  
         }  
         last_clock = ti;  
     }  
 #endif  
     if (alarm_has_dynticks(t) ||  
         qemu_next_alarm_deadline () <= 0) {  
         t->expired = alarm_has_dynticks(t);  
         t->pending = 1;  
         qemu_notify_event();  
     }  
 }  }
   
 #if defined(__linux__)  #if defined(__linux__)
Line 564  static int dynticks_start_timer(struct q Line 509  static int dynticks_start_timer(struct q
   
     if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {      if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
         perror("timer_create");          perror("timer_create");
   
         /* disable dynticks */  
         fprintf(stderr, "Dynamic Ticks disabled\n");  
   
         return -1;          return -1;
     }      }
   
Line 666  static void unix_stop_timer(struct qemu_ Line 607  static void unix_stop_timer(struct qemu_
 #ifdef _WIN32  #ifdef _WIN32
   
 static MMRESULT mm_timer;  static MMRESULT mm_timer;
 static unsigned mm_period;  static TIMECAPS mm_tc;
   
 static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,  static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
                                       DWORD_PTR dwUser, DWORD_PTR dw1,                                        DWORD_PTR dwUser, DWORD_PTR dw1,
Line 676  static void CALLBACK mm_alarm_handler(UI Line 617  static void CALLBACK mm_alarm_handler(UI
     if (!t) {      if (!t) {
         return;          return;
     }      }
     if (alarm_has_dynticks(t) || qemu_next_alarm_deadline() <= 0) {      t->expired = true;
         t->expired = alarm_has_dynticks(t);      t->pending = true;
         t->pending = 1;      qemu_notify_event();
         qemu_notify_event();  
     }  
 }  }
   
 static int mm_start_timer(struct qemu_alarm_timer *t)  static int mm_start_timer(struct qemu_alarm_timer *t)
 {  {
     TIMECAPS tc;      timeGetDevCaps(&mm_tc, sizeof(mm_tc));
     UINT flags;  
   
     memset(&tc, 0, sizeof(tc));  
     timeGetDevCaps(&tc, sizeof(tc));  
   
     mm_period = tc.wPeriodMin;      timeBeginPeriod(mm_tc.wPeriodMin);
     timeBeginPeriod(mm_period);  
   
     flags = TIME_CALLBACK_FUNCTION;      mm_timer = timeSetEvent(mm_tc.wPeriodMin,   /* interval (ms) */
     if (alarm_has_dynticks(t)) {                              mm_tc.wPeriodMin,   /* resolution */
         flags |= TIME_ONESHOT;  
     } else {  
         flags |= TIME_PERIODIC;  
     }  
   
     mm_timer = timeSetEvent(1,                  /* interval (ms) */  
                             mm_period,          /* resolution */  
                             mm_alarm_handler,   /* function */                              mm_alarm_handler,   /* function */
                             (DWORD_PTR)t,       /* parameter */                              (DWORD_PTR)t,       /* parameter */
                             flags);                              TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
   
     if (!mm_timer) {      if (!mm_timer) {
         fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",          fprintf(stderr, "Failed to initialize win32 alarm timer\n");
                 GetLastError());          timeEndPeriod(mm_tc.wPeriodMin);
         timeEndPeriod(mm_period);  
         return -1;          return -1;
     }      }
   
Line 720  static int mm_start_timer(struct qemu_al Line 646  static int mm_start_timer(struct qemu_al
 static void mm_stop_timer(struct qemu_alarm_timer *t)  static void mm_stop_timer(struct qemu_alarm_timer *t)
 {  {
     timeKillEvent(mm_timer);      timeKillEvent(mm_timer);
     timeEndPeriod(mm_period);      timeEndPeriod(mm_tc.wPeriodMin);
 }  }
   
 static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)  static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
 {  {
     int nearest_delta_ms = (delta + 999999) / 1000000;      int64_t nearest_delta_ms = delta / 1000000;
     if (nearest_delta_ms < 1) {      if (nearest_delta_ms < mm_tc.wPeriodMin) {
         nearest_delta_ms = 1;          nearest_delta_ms = mm_tc.wPeriodMin;
       } else if (nearest_delta_ms > mm_tc.wPeriodMax) {
           nearest_delta_ms = mm_tc.wPeriodMax;
     }      }
   
     timeKillEvent(mm_timer);      timeKillEvent(mm_timer);
     mm_timer = timeSetEvent(nearest_delta_ms,      mm_timer = timeSetEvent((UINT)nearest_delta_ms,
                             mm_period,                              mm_tc.wPeriodMin,
                             mm_alarm_handler,                              mm_alarm_handler,
                             (DWORD_PTR)t,                              (DWORD_PTR)t,
                             TIME_ONESHOT | TIME_CALLBACK_FUNCTION);                              TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
   
     if (!mm_timer) {      if (!mm_timer) {
         fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n",          fprintf(stderr, "Failed to re-arm win32 alarm timer\n");
                 GetLastError());          timeEndPeriod(mm_tc.wPeriodMin);
   
         timeEndPeriod(mm_period);  
         exit(1);          exit(1);
     }      }
 }  }
Line 760  static int win32_start_timer(struct qemu Line 686  static int win32_start_timer(struct qemu
                           host_alarm_handler,                            host_alarm_handler,
                           t,                            t,
                           1,                            1,
                           alarm_has_dynticks(t) ? 3600000 : 1,                            3600000,
                           WT_EXECUTEINTIMERTHREAD);                            WT_EXECUTEINTIMERTHREAD);
   
     if (!success) {      if (!success) {
Line 786  static void win32_rearm_timer(struct qem Line 712  static void win32_rearm_timer(struct qem
                               int64_t nearest_delta_ns)                                int64_t nearest_delta_ns)
 {  {
     HANDLE hTimer = t->timer;      HANDLE hTimer = t->timer;
     int nearest_delta_ms;      int64_t nearest_delta_ms;
     BOOLEAN success;      BOOLEAN success;
   
     nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000;      nearest_delta_ms = nearest_delta_ns / 1000000;
     if (nearest_delta_ms < 1) {      if (nearest_delta_ms < 1) {
         nearest_delta_ms = 1;          nearest_delta_ms = 1;
     }      }
       /* ULONG_MAX can be 32 bit */
       if (nearest_delta_ms > ULONG_MAX) {
           nearest_delta_ms = ULONG_MAX;
       }
     success = ChangeTimerQueueTimer(NULL,      success = ChangeTimerQueueTimer(NULL,
                                     hTimer,                                      hTimer,
                                     nearest_delta_ms,                                      (unsigned long) nearest_delta_ms,
                                     3600000);                                      3600000);
   
     if (!success) {      if (!success) {
Line 835  int init_timer_alarm(void) Line 765  int init_timer_alarm(void)
   
     /* first event is at time 0 */      /* first event is at time 0 */
     atexit(quit_timers);      atexit(quit_timers);
     t->pending = 1;      t->pending = true;
     alarm_timer = t;      alarm_timer = t;
   
     return 0;      return 0;
Line 844  fail: Line 774  fail:
     return err;      return err;
 }  }
   
 int qemu_calculate_timeout(void)  
 {  
     return 1000;  
 }  
   

Removed from v.1.1.1.4  
changed lines
  Added in v.1.1.1.5


unix.superglobalmegacorp.com