All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop
@ 2011-09-27 16:31 Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 01/12] qemu-timer: remove active_timers array Paolo Bonzini
                   ` (11 more replies)
  0 siblings, 12 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

This patch series makes the QEMU main loop usable out of the executable,
and especially in tools and possibly unit tests.  The series already
starts using the refactored main loop in qemu-nbd.

This is cleaner because it avoids introducing partial transitions to
GIOChannel.  Interfacing with the glib main loop is still possible.

The main loop code is currently split in cpus.c and vl.c.  Moving it
to a new file is easy; the problem is that the main loop depends on the
timer infrastructure in qemu-timer.c, and that file currently contains
the implementation of icount and the vm_clock.  This is bad for the
prospective of linking qemu-timer.c into the tools.  Luckily, it is
relatively easy to untie them and move them out of the way.  This is
what the largest part of the series does (patches 1-8).

Patches 9-12 complete the refactoring and cleanup some surrounding
code.

The series does not include any use yet, but I have a prototype of
using it in qemu-nbd (to support multiple in-flight operations and
AIO support).

Paolo Bonzini (12):
  qemu-timer: remove active_timers array
  qemu-timer: move common code to qemu_rearm_alarm_timer
  qemu-timer: more clock functions
  qemu-timer: move icount to cpus.c
  qemu-timer: do not refer to runstate_is_running()
  qemu-timer: use atexit for quit_timers
  qemu-timer: move more stuff out of qemu-timer.c
  qemu-timer: do not use RunState change handlers
  create main-loop.h
  create main-loop.c
  Revert to a hand-made select loop
  simplify main loop functions

 Makefile.objs    |    2 +-
 async.c          |    1 +
 cpus.c           |  497 ++++++++++++++++++++++++++++++-----------------------
 cpus.h           |    3 +-
 exec-all.h       |   14 ++
 exec.c           |    7 -
 iohandler.c      |   54 +------
 main-loop.c      |  494 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 main-loop.h      |   73 ++++++++
 os-win32.c       |  123 --------------
 qemu-char.h      |   12 +--
 qemu-common.h    |   15 +--
 qemu-os-posix.h  |    4 -
 qemu-os-win32.h  |   15 +--
 qemu-timer.c     |  489 ++++++++++-------------------------------------------
 qemu-timer.h     |   30 +---
 savevm.c         |   25 +++
 slirp/libslirp.h |   11 --
 sysemu.h         |    3 +-
 vl.c             |  190 ++++-----------------
 20 files changed, 1029 insertions(+), 1033 deletions(-)
 create mode 100644 main-loop.c
 create mode 100644 main-loop.h

-- 
1.7.6

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 01/12] qemu-timer: remove active_timers array
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 02/12] qemu-timer: move common code to qemu_rearm_alarm_timer Paolo Bonzini
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

Embed the list in the QEMUClock instead.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-timer.c |   59 +++++++++++++++++++++++++++------------------------------
 1 files changed, 28 insertions(+), 31 deletions(-)

diff --git a/qemu-timer.c b/qemu-timer.c
index ad1fc8b..acf7a15 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -134,6 +134,7 @@ struct QEMUClock {
     int enabled;
 
     QEMUTimer *warp_timer;
+    QEMUTimer *active_timers;
 
     NotifierList reset_notifiers;
     int64_t last;
@@ -352,14 +353,10 @@ next:
     }
 }
 
-#define QEMU_NUM_CLOCKS 3
-
 QEMUClock *rt_clock;
 QEMUClock *vm_clock;
 QEMUClock *host_clock;
 
-static QEMUTimer *active_timers[QEMU_NUM_CLOCKS];
-
 static QEMUClock *qemu_new_clock(int type)
 {
     QEMUClock *clock;
@@ -403,7 +400,7 @@ static void icount_warp_rt(void *opaque)
             int64_t delta = cur_time - cur_icount;
             qemu_icount_bias += MIN(warp_delta, delta);
         }
-        if (qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL],
+        if (qemu_timer_expired(vm_clock->active_timers,
                                qemu_get_clock_ns(vm_clock))) {
             qemu_notify_event();
         }
@@ -434,7 +431,7 @@ void qemu_clock_warp(QEMUClock *clock)
      * the earliest vm_clock timer.
      */
     icount_warp_rt(NULL);
-    if (!all_cpu_threads_idle() || !active_timers[clock->type]) {
+    if (!all_cpu_threads_idle() || !clock->active_timers) {
         qemu_del_timer(clock->warp_timer);
         return;
     }
@@ -489,7 +486,7 @@ void qemu_del_timer(QEMUTimer *ts)
 
     /* NOTE: this code must be signal safe because
        qemu_timer_expired() can be called from a signal. */
-    pt = &active_timers[ts->clock->type];
+    pt = &ts->clock->active_timers;
     for(;;) {
         t = *pt;
         if (!t)
@@ -513,7 +510,7 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
     /* add the timer in the sorted list */
     /* NOTE: this code must be signal safe because
        qemu_timer_expired() can be called from a signal. */
-    pt = &active_timers[ts->clock->type];
+    pt = &ts->clock->active_timers;
     for(;;) {
         t = *pt;
         if (!qemu_timer_expired_ns(t, expire_time)) {
@@ -526,7 +523,7 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
     *pt = ts;
 
     /* Rearm if necessary  */
-    if (pt == &active_timers[ts->clock->type]) {
+    if (pt == &ts->clock->active_timers) {
         if (!alarm_timer->pending) {
             qemu_rearm_alarm_timer(alarm_timer);
         }
@@ -548,7 +545,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
 int qemu_timer_pending(QEMUTimer *ts)
 {
     QEMUTimer *t;
-    for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) {
+    for (t = ts->clock->active_timers; t != NULL; t = t->next) {
         if (t == ts)
             return 1;
     }
@@ -569,7 +566,7 @@ static void qemu_run_timers(QEMUClock *clock)
         return;
 
     current_time = qemu_get_clock_ns(clock);
-    ptimer_head = &active_timers[clock->type];
+    ptimer_head = &clock->active_timers;
     for(;;) {
         ts = *ptimer_head;
         if (!qemu_timer_expired_ns(ts, current_time)) {
@@ -773,8 +770,8 @@ int64_t qemu_next_icount_deadline(void)
     int64_t delta = INT32_MAX;
 
     assert(use_icount);
-    if (active_timers[QEMU_CLOCK_VIRTUAL]) {
-        delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
+    if (vm_clock->active_timers) {
+        delta = vm_clock->active_timers->expire_time -
                      qemu_get_clock_ns(vm_clock);
     }
 
@@ -789,20 +786,20 @@ static int64_t qemu_next_alarm_deadline(void)
     int64_t delta;
     int64_t rtdelta;
 
-    if (!use_icount && active_timers[QEMU_CLOCK_VIRTUAL]) {
-        delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
+    if (!use_icount && vm_clock->active_timers) {
+        delta = vm_clock->active_timers->expire_time -
                      qemu_get_clock_ns(vm_clock);
     } else {
         delta = INT32_MAX;
     }
-    if (active_timers[QEMU_CLOCK_HOST]) {
-        int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
+    if (host_clock->active_timers) {
+        int64_t hdelta = host_clock->active_timers->expire_time -
                  qemu_get_clock_ns(host_clock);
         if (hdelta < delta)
             delta = hdelta;
     }
-    if (active_timers[QEMU_CLOCK_REALTIME]) {
-        rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time -
+    if (rt_clock->active_timers) {
+        rtdelta = (rt_clock->active_timers->expire_time -
                  qemu_get_clock_ns(rt_clock));
         if (rtdelta < delta)
             delta = rtdelta;
@@ -871,9 +868,9 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
     int64_t current_ns;
 
     assert(alarm_has_dynticks(t));
-    if (!active_timers[QEMU_CLOCK_REALTIME] &&
-        !active_timers[QEMU_CLOCK_VIRTUAL] &&
-        !active_timers[QEMU_CLOCK_HOST])
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers)
         return;
 
     nearest_delta_ns = qemu_next_alarm_deadline();
@@ -925,9 +922,9 @@ static void unix_rearm_timer(struct qemu_alarm_timer *t)
     int err;
 
     assert(alarm_has_dynticks(t));
-    if (!active_timers[QEMU_CLOCK_REALTIME] &&
-        !active_timers[QEMU_CLOCK_VIRTUAL] &&
-        !active_timers[QEMU_CLOCK_HOST])
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers)
         return;
 
     nearest_delta_ns = qemu_next_alarm_deadline();
@@ -1022,9 +1019,9 @@ static void mm_rearm_timer(struct qemu_alarm_timer *t)
     int nearest_delta_ms;
 
     assert(alarm_has_dynticks(t));
-    if (!active_timers[QEMU_CLOCK_REALTIME] &&
-        !active_timers[QEMU_CLOCK_VIRTUAL] &&
-        !active_timers[QEMU_CLOCK_HOST]) {
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers) {
         return;
     }
 
@@ -1092,9 +1089,9 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
     BOOLEAN success;
 
     assert(alarm_has_dynticks(t));
-    if (!active_timers[QEMU_CLOCK_REALTIME] &&
-        !active_timers[QEMU_CLOCK_VIRTUAL] &&
-        !active_timers[QEMU_CLOCK_HOST])
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers)
         return;
 
     nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 02/12] qemu-timer: move common code to qemu_rearm_alarm_timer
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 01/12] qemu-timer: remove active_timers array Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 03/12] qemu-timer: more clock functions Paolo Bonzini
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-timer.c |  129 ++++++++++++++++++++++++----------------------------------
 1 files changed, 53 insertions(+), 76 deletions(-)

diff --git a/qemu-timer.c b/qemu-timer.c
index acf7a15..e2551f3 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -153,7 +153,7 @@ struct qemu_alarm_timer {
     char const *name;
     int (*start)(struct qemu_alarm_timer *t);
     void (*stop)(struct qemu_alarm_timer *t);
-    void (*rearm)(struct qemu_alarm_timer *t);
+    void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
 #if defined(__linux__)
     int fd;
     timer_t timer;
@@ -181,12 +181,46 @@ static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
     return !!t->rearm;
 }
 
+static int64_t qemu_next_alarm_deadline(void)
+{
+    int64_t delta;
+    int64_t rtdelta;
+
+    if (!use_icount && vm_clock->active_timers) {
+        delta = vm_clock->active_timers->expire_time -
+                     qemu_get_clock_ns(vm_clock);
+    } else {
+        delta = INT32_MAX;
+    }
+    if (host_clock->active_timers) {
+        int64_t hdelta = host_clock->active_timers->expire_time -
+                 qemu_get_clock_ns(host_clock);
+        if (hdelta < delta) {
+            delta = hdelta;
+        }
+    }
+    if (rt_clock->active_timers) {
+        rtdelta = (rt_clock->active_timers->expire_time -
+                 qemu_get_clock_ns(rt_clock));
+        if (rtdelta < delta) {
+            delta = rtdelta;
+        }
+    }
+
+    return delta;
+}
+
 static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
 {
-    if (!alarm_has_dynticks(t))
+    int64_t nearest_delta_ns;
+    assert(alarm_has_dynticks(t));
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers) {
         return;
-
-    t->rearm(t);
+    }
+    nearest_delta_ns = qemu_next_alarm_deadline();
+    t->rearm(t, nearest_delta_ns);
 }
 
 /* TODO: MIN_TIMER_REARM_NS should be optimized */
@@ -196,23 +230,23 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
 
 static int mm_start_timer(struct qemu_alarm_timer *t);
 static void mm_stop_timer(struct qemu_alarm_timer *t);
-static void mm_rearm_timer(struct qemu_alarm_timer *t);
+static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 static int win32_start_timer(struct qemu_alarm_timer *t);
 static void win32_stop_timer(struct qemu_alarm_timer *t);
-static void win32_rearm_timer(struct qemu_alarm_timer *t);
+static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 #else
 
 static int unix_start_timer(struct qemu_alarm_timer *t);
 static void unix_stop_timer(struct qemu_alarm_timer *t);
-static void unix_rearm_timer(struct qemu_alarm_timer *t);
+static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 #ifdef __linux__
 
 static int dynticks_start_timer(struct qemu_alarm_timer *t);
 static void dynticks_stop_timer(struct qemu_alarm_timer *t);
-static void dynticks_rearm_timer(struct qemu_alarm_timer *t);
+static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 #endif /* __linux__ */
 
@@ -715,8 +749,6 @@ void qemu_run_all_timers(void)
     qemu_run_timers(host_clock);
 }
 
-static int64_t qemu_next_alarm_deadline(void);
-
 #ifdef _WIN32
 static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
 #else
@@ -781,33 +813,6 @@ int64_t qemu_next_icount_deadline(void)
     return delta;
 }
 
-static int64_t qemu_next_alarm_deadline(void)
-{
-    int64_t delta;
-    int64_t rtdelta;
-
-    if (!use_icount && vm_clock->active_timers) {
-        delta = vm_clock->active_timers->expire_time -
-                     qemu_get_clock_ns(vm_clock);
-    } else {
-        delta = INT32_MAX;
-    }
-    if (host_clock->active_timers) {
-        int64_t hdelta = host_clock->active_timers->expire_time -
-                 qemu_get_clock_ns(host_clock);
-        if (hdelta < delta)
-            delta = hdelta;
-    }
-    if (rt_clock->active_timers) {
-        rtdelta = (rt_clock->active_timers->expire_time -
-                 qemu_get_clock_ns(rt_clock));
-        if (rtdelta < delta)
-            delta = rtdelta;
-    }
-
-    return delta;
-}
-
 #if defined(__linux__)
 
 #include "compatfd.h"
@@ -860,20 +865,13 @@ static void dynticks_stop_timer(struct qemu_alarm_timer *t)
     timer_delete(host_timer);
 }
 
-static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
+static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
+                                 int64_t nearest_delta_ns)
 {
     timer_t host_timer = t->timer;
     struct itimerspec timeout;
-    int64_t nearest_delta_ns = INT64_MAX;
     int64_t current_ns;
 
-    assert(alarm_has_dynticks(t));
-    if (!rt_clock->active_timers &&
-        !vm_clock->active_timers &&
-        !host_clock->active_timers)
-        return;
-
-    nearest_delta_ns = qemu_next_alarm_deadline();
     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
         nearest_delta_ns = MIN_TIMER_REARM_NS;
 
@@ -915,19 +913,12 @@ static int unix_start_timer(struct qemu_alarm_timer *t)
     return 0;
 }
 
-static void unix_rearm_timer(struct qemu_alarm_timer *t)
+static void unix_rearm_timer(struct qemu_alarm_timer *t,
+                             int64_t nearest_delta_ns)
 {
     struct itimerval itv;
-    int64_t nearest_delta_ns = INT64_MAX;
     int err;
 
-    assert(alarm_has_dynticks(t));
-    if (!rt_clock->active_timers &&
-        !vm_clock->active_timers &&
-        !host_clock->active_timers)
-        return;
-
-    nearest_delta_ns = qemu_next_alarm_deadline();
     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
         nearest_delta_ns = MIN_TIMER_REARM_NS;
 
@@ -1014,23 +1005,14 @@ static void mm_stop_timer(struct qemu_alarm_timer *t)
     timeEndPeriod(mm_period);
 }
 
-static void mm_rearm_timer(struct qemu_alarm_timer *t)
+static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
 {
-    int nearest_delta_ms;
-
-    assert(alarm_has_dynticks(t));
-    if (!rt_clock->active_timers &&
-        !vm_clock->active_timers &&
-        !host_clock->active_timers) {
-        return;
-    }
-
-    timeKillEvent(mm_timer);
-
-    nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
+    int nearest_delta_ms = (delta + 999999) / 1000000;
     if (nearest_delta_ms < 1) {
         nearest_delta_ms = 1;
     }
+
+    timeKillEvent(mm_timer);
     mm_timer = timeSetEvent(nearest_delta_ms,
                             mm_period,
                             mm_alarm_handler,
@@ -1082,19 +1064,14 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
     }
 }
 
-static void win32_rearm_timer(struct qemu_alarm_timer *t)
+static void win32_rearm_timer(struct qemu_alarm_timer *t,
+                              int64_t nearest_delta_ns)
 {
     HANDLE hTimer = t->timer;
     int nearest_delta_ms;
     BOOLEAN success;
 
-    assert(alarm_has_dynticks(t));
-    if (!rt_clock->active_timers &&
-        !vm_clock->active_timers &&
-        !host_clock->active_timers)
-        return;
-
-    nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
+    nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000;
     if (nearest_delta_ms < 1) {
         nearest_delta_ms = 1;
     }
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 03/12] qemu-timer: more clock functions
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 01/12] qemu-timer: remove active_timers array Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 02/12] qemu-timer: move common code to qemu_rearm_alarm_timer Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-30 10:52   ` Lluís Vilanova
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 04/12] qemu-timer: move icount to cpus.c Paolo Bonzini
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

These will be used when moving icount accounting to cpus.c.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-timer.c |   25 +++++++++++++++++++++++++
 qemu-timer.h |    3 +++
 2 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/qemu-timer.c b/qemu-timer.c
index e2551f3..ebb5089 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -495,6 +495,31 @@ void qemu_clock_warp(QEMUClock *clock)
     }
 }
 
+int64_t qemu_clock_has_timers(QEMUClock *clock)
+{
+    return !!clock->active_timers;
+}
+
+int64_t qemu_clock_expired(QEMUClock *clock)
+{
+    return (clock->active_timers &&
+            clock->active_timers->expire_time < qemu_get_clock_ns(clock));
+}
+
+int64_t qemu_clock_deadline(QEMUClock *clock)
+{
+    /* To avoid problems with overflow limit this to 2^32.  */
+    int64_t delta = INT32_MAX;
+
+    if (clock->active_timers) {
+        delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
+    }
+    if (delta < 0) {
+        delta = 0;
+    }
+    return delta;
+}
+
 QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
                           QEMUTimerCB *cb, void *opaque)
 {
diff --git a/qemu-timer.h b/qemu-timer.h
index 0a43469..4578075 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -38,6 +38,9 @@ extern QEMUClock *vm_clock;
 extern QEMUClock *host_clock;
 
 int64_t qemu_get_clock_ns(QEMUClock *clock);
+int64_t qemu_clock_has_timers(QEMUClock *clock);
+int64_t qemu_clock_expired(QEMUClock *clock);
+int64_t qemu_clock_deadline(QEMUClock *clock);
 void qemu_clock_enable(QEMUClock *clock, int enabled);
 void qemu_clock_warp(QEMUClock *clock);
 
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 04/12] qemu-timer: move icount to cpus.c
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
                   ` (2 preceding siblings ...)
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 03/12] qemu-timer: more clock functions Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 05/12] qemu-timer: do not refer to runstate_is_running() Paolo Bonzini
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

None of this is needed by tools, and most of it can even be made static
inside cpus.c.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cpus.c        |  296 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 exec-all.h    |   14 +++
 exec.c        |    7 --
 qemu-common.h |    4 +
 qemu-timer.c  |  279 -----------------------------------------------------
 qemu-timer.h  |   24 +-----
 6 files changed, 297 insertions(+), 327 deletions(-)

diff --git a/cpus.c b/cpus.c
index 8978779..58d353f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -65,6 +65,282 @@
 static CPUState *next_cpu;
 
 /***********************************************************/
+/* guest cycle counter */
+
+/* Conversion factor from emulated instructions to virtual clock ticks.  */
+static int icount_time_shift;
+/* Arbitrarily pick 1MIPS as the minimum allowable speed.  */
+#define MAX_ICOUNT_SHIFT 10
+/* Compensate for varying guest execution speed.  */
+static int64_t qemu_icount_bias;
+static QEMUTimer *icount_rt_timer;
+static QEMUTimer *icount_vm_timer;
+static QEMUTimer *icount_warp_timer;
+static int64_t vm_clock_warp_start;
+int64_t qemu_icount;
+int use_icount;
+
+typedef struct TimersState {
+    int64_t cpu_ticks_prev;
+    int64_t cpu_ticks_offset;
+    int64_t cpu_clock_offset;
+    int32_t cpu_ticks_enabled;
+    int64_t dummy;
+} TimersState;
+
+TimersState timers_state;
+
+/* Return the virtual CPU time, based on the instruction counter.  */
+int64_t cpu_get_icount(void)
+{
+    int64_t icount;
+    CPUState *env = cpu_single_env;;
+
+    icount = qemu_icount;
+    if (env) {
+        if (!can_do_io(env)) {
+            fprintf(stderr, "Bad clock read\n");
+        }
+        icount -= (env->icount_decr.u16.low + env->icount_extra);
+    }
+    return qemu_icount_bias + (icount << icount_time_shift);
+}
+
+/* return the host CPU cycle counter and handle stop/restart */
+int64_t cpu_get_ticks(void)
+{
+    if (use_icount) {
+        return cpu_get_icount();
+    }
+    if (!timers_state.cpu_ticks_enabled) {
+        return timers_state.cpu_ticks_offset;
+    } else {
+        int64_t ticks;
+        ticks = cpu_get_real_ticks();
+        if (timers_state.cpu_ticks_prev > ticks) {
+            /* Note: non increasing ticks may happen if the host uses
+               software suspend */
+            timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
+        }
+        timers_state.cpu_ticks_prev = ticks;
+        return ticks + timers_state.cpu_ticks_offset;
+    }
+}
+
+/* return the host CPU monotonic timer and handle stop/restart */
+int64_t cpu_get_clock(void)
+{
+    int64_t ti;
+    if (!timers_state.cpu_ticks_enabled) {
+        return timers_state.cpu_clock_offset;
+    } else {
+        ti = get_clock();
+        return ti + timers_state.cpu_clock_offset;
+    }
+}
+
+/* enable cpu_get_ticks() */
+void cpu_enable_ticks(void)
+{
+    if (!timers_state.cpu_ticks_enabled) {
+        timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
+        timers_state.cpu_clock_offset -= get_clock();
+        timers_state.cpu_ticks_enabled = 1;
+    }
+}
+
+/* disable cpu_get_ticks() : the clock is stopped. You must not call
+   cpu_get_ticks() after that.  */
+void cpu_disable_ticks(void)
+{
+    if (timers_state.cpu_ticks_enabled) {
+        timers_state.cpu_ticks_offset = cpu_get_ticks();
+        timers_state.cpu_clock_offset = cpu_get_clock();
+        timers_state.cpu_ticks_enabled = 0;
+    }
+}
+
+/* Correlation between real and virtual time is always going to be
+   fairly approximate, so ignore small variation.
+   When the guest is idle real and virtual time will be aligned in
+   the IO wait loop.  */
+#define ICOUNT_WOBBLE (get_ticks_per_sec() / 10)
+
+static void icount_adjust(void)
+{
+    int64_t cur_time;
+    int64_t cur_icount;
+    int64_t delta;
+    static int64_t last_delta;
+    /* If the VM is not running, then do nothing.  */
+    if (!runstate_is_running()) {
+        return;
+    }
+    cur_time = cpu_get_clock();
+    cur_icount = qemu_get_clock_ns(vm_clock);
+    delta = cur_icount - cur_time;
+    /* FIXME: This is a very crude algorithm, somewhat prone to oscillation.  */
+    if (delta > 0
+        && last_delta + ICOUNT_WOBBLE < delta * 2
+        && icount_time_shift > 0) {
+        /* The guest is getting too far ahead.  Slow time down.  */
+        icount_time_shift--;
+    }
+    if (delta < 0
+        && last_delta - ICOUNT_WOBBLE > delta * 2
+        && icount_time_shift < MAX_ICOUNT_SHIFT) {
+        /* The guest is getting too far behind.  Speed time up.  */
+        icount_time_shift++;
+    }
+    last_delta = delta;
+    qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift);
+}
+
+static void icount_adjust_rt(void *opaque)
+{
+    qemu_mod_timer(icount_rt_timer,
+                   qemu_get_clock_ms(rt_clock) + 1000);
+    icount_adjust();
+}
+
+static void icount_adjust_vm(void *opaque)
+{
+    qemu_mod_timer(icount_vm_timer,
+                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
+    icount_adjust();
+}
+
+static int64_t qemu_icount_round(int64_t count)
+{
+    return (count + (1 << icount_time_shift) - 1) >> icount_time_shift;
+}
+
+static void icount_warp_rt(void *opaque)
+{
+    if (vm_clock_warp_start == -1) {
+        return;
+    }
+
+    if (runstate_is_running()) {
+        int64_t clock = qemu_get_clock_ns(rt_clock);
+        int64_t warp_delta = clock - vm_clock_warp_start;
+        if (use_icount == 1) {
+            qemu_icount_bias += warp_delta;
+        } else {
+            /*
+             * In adaptive mode, do not let the vm_clock run too
+             * far ahead of real time.
+             */
+            int64_t cur_time = cpu_get_clock();
+            int64_t cur_icount = qemu_get_clock_ns(vm_clock);
+            int64_t delta = cur_time - cur_icount;
+            qemu_icount_bias += MIN(warp_delta, delta);
+        }
+        if (qemu_clock_expired(vm_clock)) {
+            qemu_notify_event();
+        }
+    }
+    vm_clock_warp_start = -1;
+}
+
+void qemu_clock_warp(QEMUClock *clock)
+{
+    int64_t deadline;
+
+    /*
+     * There are too many global variables to make the "warp" behavior
+     * applicable to other clocks.  But a clock argument removes the
+     * need for if statements all over the place.
+     */
+    if (clock != vm_clock || !use_icount) {
+        return;
+    }
+
+    /*
+     * If the CPUs have been sleeping, advance the vm_clock timer now.  This
+     * ensures that the deadline for the timer is computed correctly below.
+     * This also makes sure that the insn counter is synchronized before the
+     * CPU starts running, in case the CPU is woken by an event other than
+     * the earliest vm_clock timer.
+     */
+    icount_warp_rt(NULL);
+    if (!all_cpu_threads_idle() || !qemu_clock_has_timers(vm_clock)) {
+        qemu_del_timer(icount_warp_timer);
+        return;
+    }
+
+    vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
+    deadline = qemu_clock_deadline(vm_clock);
+    if (deadline > 0) {
+        /*
+         * Ensure the vm_clock proceeds even when the virtual CPU goes to
+         * sleep.  Otherwise, the CPU might be waiting for a future timer
+         * interrupt to wake it up, but the interrupt never comes because
+         * the vCPU isn't running any insns and thus doesn't advance the
+         * vm_clock.
+         *
+         * An extreme solution for this problem would be to never let VCPUs
+         * sleep in icount mode if there is a pending vm_clock timer; rather
+         * time could just advance to the next vm_clock event.  Instead, we
+         * do stop VCPUs and only advance vm_clock after some "real" time,
+         * (related to the time left until the next event) has passed.  This
+         * rt_clock timer will do this.  This avoids that the warps are too
+         * visible externally---for example, you will not be sending network
+         * packets continously instead of every 100ms.
+         */
+        qemu_mod_timer(icount_warp_timer, vm_clock_warp_start + deadline);
+    } else {
+        qemu_notify_event();
+    }
+}
+
+static const VMStateDescription vmstate_timers = {
+    .name = "timer",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT64(cpu_ticks_offset, TimersState),
+        VMSTATE_INT64(dummy, TimersState),
+        VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void configure_icount(const char *option)
+{
+    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
+    if (!option) {
+        return;
+    }
+
+    icount_warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL);
+    if (strcmp(option, "auto") != 0) {
+        icount_time_shift = strtol(option, NULL, 0);
+        use_icount = 1;
+        return;
+    }
+
+    use_icount = 2;
+
+    /* 125MIPS seems a reasonable initial guess at the guest speed.
+       It will be corrected fairly quickly anyway.  */
+    icount_time_shift = 3;
+
+    /* Have both realtime and virtual time triggers for speed adjustment.
+       The realtime trigger catches emulated time passing too slowly,
+       the virtual time trigger catches emulated time passing too fast.
+       Realtime triggers occur even when idle, so use them less frequently
+       than VM triggers.  */
+    icount_rt_timer = qemu_new_timer_ms(rt_clock, icount_adjust_rt, NULL);
+    qemu_mod_timer(icount_rt_timer,
+                   qemu_get_clock_ms(rt_clock) + 1000);
+    icount_vm_timer = qemu_new_timer_ns(vm_clock, icount_adjust_vm, NULL);
+    qemu_mod_timer(icount_vm_timer,
+                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
+}
+
+/***********************************************************/
 void hw_error(const char *fmt, ...)
 {
     va_list ap;
@@ -686,7 +962,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
 
     while (1) {
         cpu_exec_all();
-        if (use_icount && qemu_next_icount_deadline() <= 0) {
+        if (use_icount && qemu_clock_deadline(vm_clock) <= 0) {
             qemu_notify_event();
         }
         qemu_tcg_wait_io_event();
@@ -903,7 +1179,7 @@ static int tcg_cpu_exec(CPUState *env)
         qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
         env->icount_decr.u16.low = 0;
         env->icount_extra = 0;
-        count = qemu_icount_round(qemu_next_icount_deadline());
+        count = qemu_icount_round(qemu_clock_deadline(vm_clock));
         qemu_icount += count;
         decr = (count > 0xffff) ? 0xffff : count;
         count -= decr;
@@ -995,22 +1271,6 @@ void set_cpu_log_filename(const char *optarg)
     cpu_set_log_filename(optarg);
 }
 
-/* Return the virtual CPU time, based on the instruction counter.  */
-int64_t cpu_get_icount(void)
-{
-    int64_t icount;
-    CPUState *env = cpu_single_env;;
-
-    icount = qemu_icount;
-    if (env) {
-        if (!can_do_io(env)) {
-            fprintf(stderr, "Bad clock read\n");
-        }
-        icount -= (env->icount_decr.u16.low + env->icount_extra);
-    }
-    return qemu_icount_bias + (icount << icount_time_shift);
-}
-
 void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
 {
     /* XXX: implement xxx_cpu_list for targets that still miss it */
diff --git a/exec-all.h b/exec-all.h
index 9b8d62c..1f32b37 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -344,4 +344,18 @@ extern int singlestep;
 /* cpu-exec.c */
 extern volatile sig_atomic_t exit_request;
 
+/* Deterministic execution requires that IO only be performed on the last
+   instruction of a TB so that interrupts take effect immediately.  */
+static inline int can_do_io(CPUState *env)
+{
+    if (!use_icount) {
+        return 1;
+    }
+    /* If not executing code then assume we are ok.  */
+    if (!env->current_tb) {
+        return 1;
+    }
+    return env->can_do_io != 0;
+}
+
 #endif
diff --git a/exec.c b/exec.c
index 1e6f732..368e507 100644
--- a/exec.c
+++ b/exec.c
@@ -121,13 +121,6 @@ CPUState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
    cpu_exec() */
 CPUState *cpu_single_env;
-/* 0 = Do not count executed instructions.
-   1 = Precise instruction counting.
-   2 = Adaptive rate instruction counting.  */
-int use_icount = 0;
-/* Current instruction counter.  While executing translated code this may
-   include some instructions that have not yet been executed.  */
-int64_t qemu_icount;
 
 typedef struct PageDesc {
     /* list of TBs intersecting this ram page */
diff --git a/qemu-common.h b/qemu-common.h
index b1b8053..b1d2f0f 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -96,6 +96,10 @@ static inline char *realpath(const char *path, char *resolved_path)
 }
 #endif
 
+/* icount */
+void configure_icount(const char *option);
+extern int use_icount;
+
 /* FIXME: Remove NEED_CPU_H.  */
 #ifndef NEED_CPU_H
 
diff --git a/qemu-timer.c b/qemu-timer.c
index ebb5089..8129af6 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -46,82 +46,6 @@
 
 #include "qemu-timer.h"
 
-/* Conversion factor from emulated instructions to virtual clock ticks.  */
-int icount_time_shift;
-/* Arbitrarily pick 1MIPS as the minimum allowable speed.  */
-#define MAX_ICOUNT_SHIFT 10
-/* Compensate for varying guest execution speed.  */
-int64_t qemu_icount_bias;
-static QEMUTimer *icount_rt_timer;
-static QEMUTimer *icount_vm_timer;
-
-/***********************************************************/
-/* guest cycle counter */
-
-typedef struct TimersState {
-    int64_t cpu_ticks_prev;
-    int64_t cpu_ticks_offset;
-    int64_t cpu_clock_offset;
-    int32_t cpu_ticks_enabled;
-    int64_t dummy;
-} TimersState;
-
-TimersState timers_state;
-
-/* return the host CPU cycle counter and handle stop/restart */
-int64_t cpu_get_ticks(void)
-{
-    if (use_icount) {
-        return cpu_get_icount();
-    }
-    if (!timers_state.cpu_ticks_enabled) {
-        return timers_state.cpu_ticks_offset;
-    } else {
-        int64_t ticks;
-        ticks = cpu_get_real_ticks();
-        if (timers_state.cpu_ticks_prev > ticks) {
-            /* Note: non increasing ticks may happen if the host uses
-               software suspend */
-            timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
-        }
-        timers_state.cpu_ticks_prev = ticks;
-        return ticks + timers_state.cpu_ticks_offset;
-    }
-}
-
-/* return the host CPU monotonic timer and handle stop/restart */
-static int64_t cpu_get_clock(void)
-{
-    int64_t ti;
-    if (!timers_state.cpu_ticks_enabled) {
-        return timers_state.cpu_clock_offset;
-    } else {
-        ti = get_clock();
-        return ti + timers_state.cpu_clock_offset;
-    }
-}
-
-/* enable cpu_get_ticks() */
-void cpu_enable_ticks(void)
-{
-    if (!timers_state.cpu_ticks_enabled) {
-        timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
-        timers_state.cpu_clock_offset -= get_clock();
-        timers_state.cpu_ticks_enabled = 1;
-    }
-}
-
-/* disable cpu_get_ticks() : the clock is stopped. You must not call
-   cpu_get_ticks() after that.  */
-void cpu_disable_ticks(void)
-{
-    if (timers_state.cpu_ticks_enabled) {
-        timers_state.cpu_ticks_offset = cpu_get_ticks();
-        timers_state.cpu_clock_offset = cpu_get_clock();
-        timers_state.cpu_ticks_enabled = 0;
-    }
-}
-
 /***********************************************************/
 /* timers */
 
@@ -133,7 +57,6 @@ struct QEMUClock {
     int type;
     int enabled;
 
-    QEMUTimer *warp_timer;
     QEMUTimer *active_timers;
 
     NotifierList reset_notifiers;
@@ -252,61 +175,6 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 #endif /* _WIN32 */
 
-/* Correlation between real and virtual time is always going to be
-   fairly approximate, so ignore small variation.
-   When the guest is idle real and virtual time will be aligned in
-   the IO wait loop.  */
-#define ICOUNT_WOBBLE (get_ticks_per_sec() / 10)
-
-static void icount_adjust(void)
-{
-    int64_t cur_time;
-    int64_t cur_icount;
-    int64_t delta;
-    static int64_t last_delta;
-    /* If the VM is not running, then do nothing.  */
-    if (!runstate_is_running())
-        return;
-
-    cur_time = cpu_get_clock();
-    cur_icount = qemu_get_clock_ns(vm_clock);
-    delta = cur_icount - cur_time;
-    /* FIXME: This is a very crude algorithm, somewhat prone to oscillation.  */
-    if (delta > 0
-        && last_delta + ICOUNT_WOBBLE < delta * 2
-        && icount_time_shift > 0) {
-        /* The guest is getting too far ahead.  Slow time down.  */
-        icount_time_shift--;
-    }
-    if (delta < 0
-        && last_delta - ICOUNT_WOBBLE > delta * 2
-        && icount_time_shift < MAX_ICOUNT_SHIFT) {
-        /* The guest is getting too far behind.  Speed time up.  */
-        icount_time_shift++;
-    }
-    last_delta = delta;
-    qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift);
-}
-
-static void icount_adjust_rt(void * opaque)
-{
-    qemu_mod_timer(icount_rt_timer,
-                   qemu_get_clock_ms(rt_clock) + 1000);
-    icount_adjust();
-}
-
-static void icount_adjust_vm(void * opaque)
-{
-    qemu_mod_timer(icount_vm_timer,
-                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
-    icount_adjust();
-}
-
-int64_t qemu_icount_round(int64_t count)
-{
-    return (count + (1 << icount_time_shift) - 1) >> icount_time_shift;
-}
-
 static struct qemu_alarm_timer alarm_timers[] = {
 #ifndef _WIN32
 #ifdef __linux__
@@ -411,90 +279,6 @@ void qemu_clock_enable(QEMUClock *clock, int enabled)
     clock->enabled = enabled;
 }
 
-static int64_t vm_clock_warp_start;
-
-static void icount_warp_rt(void *opaque)
-{
-    if (vm_clock_warp_start == -1) {
-        return;
-    }
-
-    if (runstate_is_running()) {
-        int64_t clock = qemu_get_clock_ns(rt_clock);
-        int64_t warp_delta = clock - vm_clock_warp_start;
-        if (use_icount == 1) {
-            qemu_icount_bias += warp_delta;
-        } else {
-            /*
-             * In adaptive mode, do not let the vm_clock run too
-             * far ahead of real time.
-             */
-            int64_t cur_time = cpu_get_clock();
-            int64_t cur_icount = qemu_get_clock_ns(vm_clock);
-            int64_t delta = cur_time - cur_icount;
-            qemu_icount_bias += MIN(warp_delta, delta);
-        }
-        if (qemu_timer_expired(vm_clock->active_timers,
-                               qemu_get_clock_ns(vm_clock))) {
-            qemu_notify_event();
-        }
-    }
-    vm_clock_warp_start = -1;
-}
-
-void qemu_clock_warp(QEMUClock *clock)
-{
-    int64_t deadline;
-
-    if (!clock->warp_timer) {
-        return;
-    }
-
-    /*
-     * There are too many global variables to make the "warp" behavior
-     * applicable to other clocks.  But a clock argument removes the
-     * need for if statements all over the place.
-     */
-    assert(clock == vm_clock);
-
-    /*
-     * If the CPUs have been sleeping, advance the vm_clock timer now.  This
-     * ensures that the deadline for the timer is computed correctly below.
-     * This also makes sure that the insn counter is synchronized before the
-     * CPU starts running, in case the CPU is woken by an event other than
-     * the earliest vm_clock timer.
-     */
-    icount_warp_rt(NULL);
-    if (!all_cpu_threads_idle() || !clock->active_timers) {
-        qemu_del_timer(clock->warp_timer);
-        return;
-    }
-
-    vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
-    deadline = qemu_next_icount_deadline();
-    if (deadline > 0) {
-        /*
-         * Ensure the vm_clock proceeds even when the virtual CPU goes to
-         * sleep.  Otherwise, the CPU might be waiting for a future timer
-         * interrupt to wake it up, but the interrupt never comes because
-         * the vCPU isn't running any insns and thus doesn't advance the
-         * vm_clock.
-         *
-         * An extreme solution for this problem would be to never let VCPUs
-         * sleep in icount mode if there is a pending vm_clock timer; rather
-         * time could just advance to the next vm_clock event.  Instead, we
-         * do stop VCPUs and only advance vm_clock after some "real" time,
-         * (related to the time left until the next event) has passed.  This
-         * rt_clock timer will do this.  This avoids that the warps are too
-         * visible externally---for example, you will not be sending network
-         * packets continously instead of every 100ms.
-         */
-        qemu_mod_timer(clock->warp_timer, vm_clock_warp_start + deadline);
-    } else {
-        qemu_notify_event();
-    }
-}
-
 int64_t qemu_clock_has_timers(QEMUClock *clock)
 {
     return !!clock->active_timers;
@@ -709,52 +493,6 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
     }
 }
 
-static const VMStateDescription vmstate_timers = {
-    .name = "timer",
-    .version_id = 2,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_INT64(cpu_ticks_offset, TimersState),
-        VMSTATE_INT64(dummy, TimersState),
-        VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-void configure_icount(const char *option)
-{
-    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
-    if (!option)
-        return;
-
-    vm_clock->warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL);
-
-    if (strcmp(option, "auto") != 0) {
-        icount_time_shift = strtol(option, NULL, 0);
-        use_icount = 1;
-        return;
-    }
-
-    use_icount = 2;
-
-    /* 125MIPS seems a reasonable initial guess at the guest speed.
-       It will be corrected fairly quickly anyway.  */
-    icount_time_shift = 3;
-
-    /* Have both realtime and virtual time triggers for speed adjustment.
-       The realtime trigger catches emulated time passing too slowly,
-       the virtual time trigger catches emulated time passing too fast.
-       Realtime triggers occur even when idle, so use them less frequently
-       than VM triggers.  */
-    icount_rt_timer = qemu_new_timer_ms(rt_clock, icount_adjust_rt, NULL);
-    qemu_mod_timer(icount_rt_timer,
-                   qemu_get_clock_ms(rt_clock) + 1000);
-    icount_vm_timer = qemu_new_timer_ns(vm_clock, icount_adjust_vm, NULL);
-    qemu_mod_timer(icount_vm_timer,
-                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
-}
-
 void qemu_run_all_timers(void)
 {
     alarm_timer->pending = 0;
@@ -821,23 +559,6 @@ static void host_alarm_handler(int host_signum)
     }
 }
 
-int64_t qemu_next_icount_deadline(void)
-{
-    /* To avoid problems with overflow limit this to 2^32.  */
-    int64_t delta = INT32_MAX;
-
-    assert(use_icount);
-    if (vm_clock->active_timers) {
-        delta = vm_clock->active_timers->expire_time -
-                     qemu_get_clock_ns(vm_clock);
-    }
-
-    if (delta < 0)
-        delta = 0;
-
-    return delta;
-}
-
 #if defined(__linux__)
 
 #include "compatfd.h"
diff --git a/qemu-timer.h b/qemu-timer.h
index 4578075..ce576b9 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -58,9 +58,7 @@ int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
 
 void qemu_run_all_timers(void);
 int qemu_alarm_pending(void);
-int64_t qemu_next_icount_deadline(void);
 void configure_alarms(char const *opt);
-void configure_icount(const char *option);
 int qemu_calculate_timeout(void);
 void init_clocks(void);
 int init_timer_alarm(void);
@@ -153,12 +151,8 @@ void ptimer_run(ptimer_state *s, int oneshot);
 void ptimer_stop(ptimer_state *s);
 
 /* icount */
-int64_t qemu_icount_round(int64_t count);
-extern int64_t qemu_icount;
-extern int use_icount;
-extern int icount_time_shift;
-extern int64_t qemu_icount_bias;
 int64_t cpu_get_icount(void);
+int64_t cpu_get_clock(void);
 
 /*******************************************/
 /* host CPU ticks (if available) */
@@ -314,22 +308,6 @@ static inline int64_t cpu_get_real_ticks (void)
 }
 #endif
 
-#ifdef NEED_CPU_H
-/* Deterministic execution requires that IO only be performed on the last
-   instruction of a TB so that interrupts take effect immediately.  */
-static inline int can_do_io(CPUState *env)
-{
-    if (!use_icount)
-        return 1;
-
-    /* If not executing code then assume we are ok.  */
-    if (!env->current_tb)
-        return 1;
-
-    return env->can_do_io != 0;
-}
-#endif
-
 #ifdef CONFIG_PROFILER
 static inline int64_t profile_getclock(void)
 {
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 05/12] qemu-timer: do not refer to runstate_is_running()
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
                   ` (3 preceding siblings ...)
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 04/12] qemu-timer: move icount to cpus.c Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 06/12] qemu-timer: use atexit for quit_timers Paolo Bonzini
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cpus.c       |    1 +
 qemu-timer.c |    5 +----
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/cpus.c b/cpus.c
index 58d353f..751833d 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1060,6 +1060,7 @@ void pause_all_vcpus(void)
 {
     CPUState *penv = first_cpu;
 
+    qemu_clock_enable(vm_clock, false);
     while (penv) {
         penv->stop = 1;
         qemu_cpu_kick(penv);
diff --git a/qemu-timer.c b/qemu-timer.c
index 8129af6..d8507e3 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -504,10 +504,7 @@ void qemu_run_all_timers(void)
     }
 
     /* vm time timers */
-    if (runstate_is_running()) {
-        qemu_run_timers(vm_clock);
-    }
-
+    qemu_run_timers(vm_clock);
     qemu_run_timers(rt_clock);
     qemu_run_timers(host_clock);
 }
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 06/12] qemu-timer: use atexit for quit_timers
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
                   ` (4 preceding siblings ...)
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 05/12] qemu-timer: do not refer to runstate_is_running() Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 07/12] qemu-timer: move more stuff out of qemu-timer.c Paolo Bonzini
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-timer.c |   15 ++++++++-------
 qemu-timer.h |    1 -
 vl.c         |    1 -
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/qemu-timer.c b/qemu-timer.c
index d8507e3..7fa81e1 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -840,6 +840,13 @@ static void alarm_timer_on_change_state_rearm(void *opaque, int running,
         qemu_rearm_alarm_timer((struct qemu_alarm_timer *) opaque);
 }
 
+static void quit_timers(void)
+{
+    struct qemu_alarm_timer *t = alarm_timer;
+    alarm_timer = NULL;
+    t->stop(t);
+}
+
 int init_timer_alarm(void)
 {
     struct qemu_alarm_timer *t = NULL;
@@ -859,6 +866,7 @@ int init_timer_alarm(void)
     }
 
     /* first event is at time 0 */
+    atexit(quit_timers);
     t->pending = 1;
     alarm_timer = t;
     qemu_add_vm_change_state_handler(alarm_timer_on_change_state_rearm, t);
@@ -869,13 +877,6 @@ fail:
     return err;
 }
 
-void quit_timers(void)
-{
-    struct qemu_alarm_timer *t = alarm_timer;
-    alarm_timer = NULL;
-    t->stop(t);
-}
-
 int qemu_calculate_timeout(void)
 {
     return 1000;
diff --git a/qemu-timer.h b/qemu-timer.h
index ce576b9..b4ea201 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -62,7 +62,6 @@ void configure_alarms(char const *opt);
 int qemu_calculate_timeout(void);
 void init_clocks(void);
 int init_timer_alarm(void);
-void quit_timers(void);
 
 int64_t cpu_get_ticks(void);
 void cpu_enable_ticks(void);
diff --git a/vl.c b/vl.c
index bd4a5ce..8ae6468 100644
--- a/vl.c
+++ b/vl.c
@@ -3572,7 +3572,6 @@ int main(int argc, char **argv, char **envp)
     os_setup_post();
 
     main_loop();
-    quit_timers();
     net_cleanup();
     res_free();
 
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 07/12] qemu-timer: move more stuff out of qemu-timer.c
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
                   ` (5 preceding siblings ...)
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 06/12] qemu-timer: use atexit for quit_timers Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 08/12] qemu-timer: do not use RunState change handlers Paolo Bonzini
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-timer.c |   35 ++++-------------------------------
 qemu-timer.h |    2 ++
 savevm.c     |   25 +++++++++++++++++++++++++
 vl.c         |    1 +
 4 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/qemu-timer.c b/qemu-timer.c
index 7fa81e1..58926dd 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -266,11 +266,8 @@ static QEMUClock *qemu_new_clock(int type)
     clock = g_malloc0(sizeof(QEMUClock));
     clock->type = type;
     clock->enabled = 1;
+    clock->last = INT64_MIN;
     notifier_list_init(&clock->reset_notifiers);
-    /* required to detect & report backward jumps */
-    if (type == QEMU_CLOCK_HOST) {
-        clock->last = get_clock_realtime();
-    }
     return clock;
 }
 
@@ -344,7 +341,7 @@ void qemu_del_timer(QEMUTimer *ts)
 
 /* modify the current timer so that it will be fired when current_time
    >= expire_time. The corresponding callback will be called. */
-static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
+void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
 {
     QEMUTimer **pt, *t;
 
@@ -378,8 +375,6 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
     }
 }
 
-/* modify the current timer so that it will be fired when current_time
-   >= expire_time. The corresponding callback will be called. */
 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
 {
     qemu_mod_timer_ns(ts, expire_time * ts->scale);
@@ -464,33 +459,11 @@ void init_clocks(void)
     rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
     vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
     host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
-
-    rtc_clock = host_clock;
 }
 
-/* save a timer */
-void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
+uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
 {
-    uint64_t expire_time;
-
-    if (qemu_timer_pending(ts)) {
-        expire_time = ts->expire_time;
-    } else {
-        expire_time = -1;
-    }
-    qemu_put_be64(f, expire_time);
-}
-
-void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
-{
-    uint64_t expire_time;
-
-    expire_time = qemu_get_be64(f);
-    if (expire_time != -1) {
-        qemu_mod_timer_ns(ts, expire_time);
-    } else {
-        qemu_del_timer(ts);
-    }
+    return qemu_timer_pending(ts) ? ts->expire_time : -1;
 }
 
 void qemu_run_all_timers(void)
diff --git a/qemu-timer.h b/qemu-timer.h
index b4ea201..9f4ffed 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -52,9 +52,11 @@ QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
                           QEMUTimerCB *cb, void *opaque);
 void qemu_free_timer(QEMUTimer *ts);
 void qemu_del_timer(QEMUTimer *ts);
+void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
 int qemu_timer_pending(QEMUTimer *ts);
 int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
+uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
 
 void qemu_run_all_timers(void);
 int qemu_alarm_pending(void);
diff --git a/savevm.c b/savevm.c
index 46f2447..eb0ccfd 100644
--- a/savevm.c
+++ b/savevm.c
@@ -81,6 +81,7 @@
 #include "migration.h"
 #include "qemu_socket.h"
 #include "qemu-queue.h"
+#include "qemu-timer.h"
 #include "cpus.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
@@ -674,6 +675,30 @@ uint64_t qemu_get_be64(QEMUFile *f)
     return v;
 }
 
+
+/* timer */
+
+void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
+{
+    uint64_t expire_time;
+
+    expire_time = qemu_timer_expire_time_ns(ts);
+    qemu_put_be64(f, expire_time);
+}
+
+void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
+{
+    uint64_t expire_time;
+
+    expire_time = qemu_get_be64(f);
+    if (expire_time != -1) {
+        qemu_mod_timer_ns(ts, expire_time);
+    } else {
+        qemu_del_timer(ts);
+    }
+}
+
+
 /* bool */
 
 static int get_bool(QEMUFile *f, void *pv, size_t size)
diff --git a/vl.c b/vl.c
index 8ae6468..19e7169 100644
--- a/vl.c
+++ b/vl.c
@@ -2322,6 +2322,7 @@ int main(int argc, char **argv, char **envp)
     runstate_init();
 
     init_clocks();
+    rtc_clock = host_clock;
 
     qemu_cache_utils_init(envp);
 
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 08/12] qemu-timer: do not use RunState change handlers
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
                   ` (6 preceding siblings ...)
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 07/12] qemu-timer: move more stuff out of qemu-timer.c Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 09/12] create main-loop.h Paolo Bonzini
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-timer.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/qemu-timer.c b/qemu-timer.c
index 58926dd..f11a28d 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -273,7 +273,11 @@ static QEMUClock *qemu_new_clock(int type)
 
 void qemu_clock_enable(QEMUClock *clock, int enabled)
 {
+    bool old = clock->enabled;
     clock->enabled = enabled;
+    if (enabled && !old) {
+        qemu_rearm_alarm_timer(alarm_timer);
+    }
 }
 
 int64_t qemu_clock_has_timers(QEMUClock *clock)
@@ -806,13 +810,6 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t,
 
 #endif /* _WIN32 */
 
-static void alarm_timer_on_change_state_rearm(void *opaque, int running,
-                                              RunState state)
-{
-    if (running)
-        qemu_rearm_alarm_timer((struct qemu_alarm_timer *) opaque);
-}
-
 static void quit_timers(void)
 {
     struct qemu_alarm_timer *t = alarm_timer;
@@ -842,7 +839,6 @@ int init_timer_alarm(void)
     atexit(quit_timers);
     t->pending = 1;
     alarm_timer = t;
-    qemu_add_vm_change_state_handler(alarm_timer_on_change_state_rearm, t);
 
     return 0;
 
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 09/12] create main-loop.h
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
                   ` (7 preceding siblings ...)
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 08/12] qemu-timer: do not use RunState change handlers Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 10/12] create main-loop.c Paolo Bonzini
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 async.c       |    1 +
 cpus.c        |    7 +----
 cpus.h        |    1 -
 main-loop.h   |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-char.h   |   12 +--------
 qemu-common.h |   11 --------
 sysemu.h      |    3 +-
 vl.c          |    1 +
 8 files changed, 78 insertions(+), 31 deletions(-)
 create mode 100644 main-loop.h

diff --git a/async.c b/async.c
index ca13962..332d511 100644
--- a/async.c
+++ b/async.c
@@ -24,6 +24,7 @@
 
 #include "qemu-common.h"
 #include "qemu-aio.h"
+#include "main-loop.h"
 
 /* Anchor of the list of Bottom Halves belonging to the context */
 static struct QEMUBH *first_bh;
diff --git a/cpus.c b/cpus.c
index 751833d..8684423 100644
--- a/cpus.c
+++ b/cpus.c
@@ -33,17 +33,12 @@
 
 #include "qemu-thread.h"
 #include "cpus.h"
+#include "main-loop.h"
 
 #ifndef _WIN32
 #include "compatfd.h"
 #endif
 
-#ifdef SIGRTMIN
-#define SIG_IPI (SIGRTMIN+4)
-#else
-#define SIG_IPI SIGUSR1
-#endif
-
 #ifdef CONFIG_LINUX
 
 #include <sys/prctl.h>
diff --git a/cpus.h b/cpus.h
index 5885885..4ccf986 100644
--- a/cpus.h
+++ b/cpus.h
@@ -2,7 +2,6 @@
 #define QEMU_CPUS_H
 
 /* cpus.c */
-int qemu_init_main_loop(void);
 void qemu_main_loop_start(void);
 void resume_all_vcpus(void);
 void pause_all_vcpus(void);
diff --git a/main-loop.h b/main-loop.h
new file mode 100644
index 0000000..7b2e675
--- /dev/null
+++ b/main-loop.h
@@ -0,0 +1,73 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_MAIN_LOOP_H
+#define QEMU_MAIN_LOOP_H 1
+
+#ifdef SIGRTMIN
+#define SIG_IPI (SIGRTMIN+4)
+#else
+#define SIG_IPI SIGUSR1
+#endif
+
+int qemu_init_main_loop(void);
+int main_loop_wait(int nonblocking);
+
+/* Force QEMU to process pending events */
+void qemu_notify_event(void);
+
+#ifdef _WIN32
+/* return TRUE if no sleep should be done afterwards */
+typedef int PollingFunc(void *opaque);
+
+int qemu_add_polling_cb(PollingFunc *func, void *opaque);
+void qemu_del_polling_cb(PollingFunc *func, void *opaque);
+
+/* Wait objects handling */
+typedef void WaitObjectFunc(void *opaque);
+
+int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+#endif
+
+/* async I/O support */
+
+typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
+typedef int IOCanReadHandler(void *opaque);
+typedef void IOHandler(void *opaque);
+
+void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
+void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc);
+
+int qemu_set_fd_handler2(int fd,
+                         IOCanReadHandler *fd_read_poll,
+                         IOHandler *fd_read,
+                         IOHandler *fd_write,
+                         void *opaque);
+int qemu_set_fd_handler(int fd,
+                        IOHandler *fd_read,
+                        IOHandler *fd_write,
+                        void *opaque);
+
+#endif
diff --git a/qemu-char.h b/qemu-char.h
index eebbdd8..7efcf99 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -7,6 +7,7 @@
 #include "qemu-config.h"
 #include "qobject.h"
 #include "qstring.h"
+#include "main-loop.h"
 
 /* character device */
 
@@ -237,15 +238,4 @@ void qemu_chr_close_mem(CharDriverState *chr);
 QString *qemu_chr_mem_to_qs(CharDriverState *chr);
 size_t qemu_chr_mem_osize(const CharDriverState *chr);
 
-/* async I/O support */
-
-int qemu_set_fd_handler2(int fd,
-                         IOCanReadHandler *fd_read_poll,
-                         IOHandler *fd_read,
-                         IOHandler *fd_write,
-                         void *opaque);
-int qemu_set_fd_handler(int fd,
-                        IOHandler *fd_read,
-                        IOHandler *fd_write,
-                        void *opaque);
 #endif
diff --git a/qemu-common.h b/qemu-common.h
index b1d2f0f..23794a3 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -218,14 +218,6 @@ int qemu_sendv(int sockfd, struct iovec *iov, int len, int iov_offset);
 
 void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
 
-/* IO callbacks.  */
-typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
-typedef int IOCanReadHandler(void *opaque);
-typedef void IOHandler(void *opaque);
-
-void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
-void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc);
-
 struct ParallelIOArg {
     void *buffer;
     int count;
@@ -287,9 +279,6 @@ void cpu_exec_init_all(void);
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
 
-/* Force QEMU to process pending events */
-void qemu_notify_event(void);
-
 /* Unblock cpu */
 void qemu_cpu_kick(void *env);
 void qemu_cpu_kick_self(void);
diff --git a/sysemu.h b/sysemu.h
index 43ff546..592f165 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -7,6 +7,7 @@
 #include "qemu-queue.h"
 #include "qemu-timer.h"
 #include "notify.h"
+#include "main-loop.h"
 
 /* vl.c */
 
@@ -81,8 +82,6 @@ void do_info_snapshots(Monitor *mon);
 
 void qemu_announce_self(void);
 
-int main_loop_wait(int nonblocking);
-
 bool qemu_savevm_state_blocked(Monitor *mon);
 int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
                             int shared);
diff --git a/vl.c b/vl.c
index 19e7169..8e8cbf2 100644
--- a/vl.c
+++ b/vl.c
@@ -147,6 +147,7 @@ int main(int argc, char **argv)
 #include "qemu-config.h"
 #include "qemu-objects.h"
 #include "qemu-options.h"
+#include "main-loop.h"
 #ifdef CONFIG_VIRTFS
 #include "fsdev/qemu-fsdev.h"
 #endif
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 10/12] create main-loop.c
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
                   ` (8 preceding siblings ...)
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 09/12] create main-loop.h Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 11/12] Revert to a hand-made select loop Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 12/12] simplify main loop functions Paolo Bonzini
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile.objs    |    2 +-
 cpus.c           |  188 +--------------------
 cpus.h           |    1 +
 main-loop.c      |  494 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 os-win32.c       |  123 --------------
 qemu-os-posix.h  |    4 -
 qemu-os-win32.h  |   15 +--
 slirp/libslirp.h |   11 --
 vl.c             |  123 +--------------
 9 files changed, 499 insertions(+), 462 deletions(-)
 create mode 100644 main-loop.c

diff --git a/Makefile.objs b/Makefile.objs
index f658989..f22fee4 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -81,7 +81,7 @@ common-obj-y += $(oslib-obj-y)
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
 
-common-obj-y += tcg-runtime.o host-utils.o
+common-obj-y += tcg-runtime.o host-utils.o main-loop.o
 common-obj-y += irq.o ioport.o input.o
 common-obj-$(CONFIG_PTIMER) += ptimer.o
 common-obj-$(CONFIG_MAX7310) += max7310.o
diff --git a/cpus.c b/cpus.c
index 8684423..826c88b 100644
--- a/cpus.c
+++ b/cpus.c
@@ -543,143 +543,10 @@ static void qemu_kvm_eat_signals(CPUState *env)
 #endif /* !CONFIG_LINUX */
 
 #ifndef _WIN32
-static int io_thread_fd = -1;
-
-static void qemu_event_increment(void)
-{
-    /* Write 8 bytes to be compatible with eventfd.  */
-    static const uint64_t val = 1;
-    ssize_t ret;
-
-    if (io_thread_fd == -1) {
-        return;
-    }
-    do {
-        ret = write(io_thread_fd, &val, sizeof(val));
-    } while (ret < 0 && errno == EINTR);
-
-    /* EAGAIN is fine, a read must be pending.  */
-    if (ret < 0 && errno != EAGAIN) {
-        fprintf(stderr, "qemu_event_increment: write() failed: %s\n",
-                strerror(errno));
-        exit (1);
-    }
-}
-
-static void qemu_event_read(void *opaque)
-{
-    int fd = (intptr_t)opaque;
-    ssize_t len;
-    char buffer[512];
-
-    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
-    do {
-        len = read(fd, buffer, sizeof(buffer));
-    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
-}
-
-static int qemu_event_init(void)
-{
-    int err;
-    int fds[2];
-
-    err = qemu_eventfd(fds);
-    if (err == -1) {
-        return -errno;
-    }
-    err = fcntl_setfl(fds[0], O_NONBLOCK);
-    if (err < 0) {
-        goto fail;
-    }
-    err = fcntl_setfl(fds[1], O_NONBLOCK);
-    if (err < 0) {
-        goto fail;
-    }
-    qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
-                         (void *)(intptr_t)fds[0]);
-
-    io_thread_fd = fds[1];
-    return 0;
-
-fail:
-    close(fds[0]);
-    close(fds[1]);
-    return err;
-}
-
 static void dummy_signal(int sig)
 {
 }
 
-/* If we have signalfd, we mask out the signals we want to handle and then
- * use signalfd to listen for them.  We rely on whatever the current signal
- * handler is to dispatch the signals when we receive them.
- */
-static void sigfd_handler(void *opaque)
-{
-    int fd = (intptr_t)opaque;
-    struct qemu_signalfd_siginfo info;
-    struct sigaction action;
-    ssize_t len;
-
-    while (1) {
-        do {
-            len = read(fd, &info, sizeof(info));
-        } while (len == -1 && errno == EINTR);
-
-        if (len == -1 && errno == EAGAIN) {
-            break;
-        }
-
-        if (len != sizeof(info)) {
-            printf("read from sigfd returned %zd: %m\n", len);
-            return;
-        }
-
-        sigaction(info.ssi_signo, NULL, &action);
-        if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
-            action.sa_sigaction(info.ssi_signo,
-                                (siginfo_t *)&info, NULL);
-        } else if (action.sa_handler) {
-            action.sa_handler(info.ssi_signo);
-        }
-    }
-}
-
-static int qemu_signal_init(void)
-{
-    int sigfd;
-    sigset_t set;
-
-    /*
-     * SIG_IPI must be blocked in the main thread and must not be caught
-     * by sigwait() in the signal thread. Otherwise, the cpu thread will
-     * not catch it reliably.
-     */
-    sigemptyset(&set);
-    sigaddset(&set, SIG_IPI);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-    sigemptyset(&set);
-    sigaddset(&set, SIGIO);
-    sigaddset(&set, SIGALRM);
-    sigaddset(&set, SIGBUS);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-    sigfd = qemu_signalfd(&set);
-    if (sigfd == -1) {
-        fprintf(stderr, "failed to create signalfd\n");
-        return -errno;
-    }
-
-    fcntl_setfl(sigfd, O_NONBLOCK);
-
-    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
-                         (void *)(intptr_t)sigfd);
-
-    return 0;
-}
-
 static void qemu_kvm_init_cpu_signals(CPUState *env)
 {
     int r;
@@ -723,38 +590,6 @@ static void qemu_tcg_init_cpu_signals(void)
 }
 
 #else /* _WIN32 */
-
-HANDLE qemu_event_handle;
-
-static void dummy_event_handler(void *opaque)
-{
-}
-
-static int qemu_event_init(void)
-{
-    qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (!qemu_event_handle) {
-        fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError());
-        return -1;
-    }
-    qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
-    return 0;
-}
-
-static void qemu_event_increment(void)
-{
-    if (!SetEvent(qemu_event_handle)) {
-        fprintf(stderr, "qemu_event_increment: SetEvent failed: %ld\n",
-                GetLastError());
-        exit (1);
-    }
-}
-
-static int qemu_signal_init(void)
-{
-    return 0;
-}
-
 static void qemu_kvm_init_cpu_signals(CPUState *env)
 {
     abort();
@@ -780,23 +615,9 @@ static QemuCond qemu_cpu_cond;
 static QemuCond qemu_pause_cond;
 static QemuCond qemu_work_cond;
 
-int qemu_init_main_loop(void)
+void qemu_init_cpu_loop(void)
 {
-    int ret;
-
     qemu_init_sigbus();
-
-    ret = qemu_signal_init();
-    if (ret) {
-        return ret;
-    }
-
-    /* Note eventfd must be drained before signalfd handlers run */
-    ret = qemu_event_init();
-    if (ret) {
-        return ret;
-    }
-
     qemu_cond_init(&qemu_cpu_cond);
     qemu_cond_init(&qemu_pause_cond);
     qemu_cond_init(&qemu_work_cond);
@@ -805,8 +626,6 @@ int qemu_init_main_loop(void)
     qemu_mutex_lock(&qemu_global_mutex);
 
     qemu_thread_get_self(&io_thread);
-
-    return 0;
 }
 
 void qemu_main_loop_start(void)
@@ -1130,11 +949,6 @@ void qemu_init_vcpu(void *_env)
     }
 }
 
-void qemu_notify_event(void)
-{
-    qemu_event_increment();
-}
-
 void cpu_stop_current(void)
 {
     if (cpu_single_env) {
diff --git a/cpus.h b/cpus.h
index 4ccf986..7422584 100644
--- a/cpus.h
+++ b/cpus.h
@@ -2,6 +2,7 @@
 #define QEMU_CPUS_H
 
 /* cpus.c */
+void qemu_init_cpu_loop(void);
 void qemu_main_loop_start(void);
 void resume_all_vcpus(void);
 void pause_all_vcpus(void);
diff --git a/main-loop.c b/main-loop.c
new file mode 100644
index 0000000..f337aa3
--- /dev/null
+++ b/main-loop.c
@@ -0,0 +1,494 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "config-host.h"
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <stdbool.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include "compatfd.h"
+#endif
+
+#include <glib.h>
+
+#include "main-loop.h"
+#include "qemu-timer.h"
+#include "slirp/libslirp.h"
+
+#ifndef _WIN32
+
+static int io_thread_fd = -1;
+
+void qemu_notify_event(void)
+{
+    /* Write 8 bytes to be compatible with eventfd.  */
+    static const uint64_t val = 1;
+    ssize_t ret;
+
+    if (io_thread_fd == -1) {
+        return;
+    }
+    do {
+        ret = write(io_thread_fd, &val, sizeof(val));
+    } while (ret < 0 && errno == EINTR);
+
+    /* EAGAIN is fine, a read must be pending.  */
+    if (ret < 0 && errno != EAGAIN) {
+        fprintf(stderr, "qemu_notify_event: write() failed: %s\n",
+                strerror(errno));
+        exit(1);
+    }
+}
+
+static void qemu_event_read(void *opaque)
+{
+    int fd = (intptr_t)opaque;
+    ssize_t len;
+    char buffer[512];
+
+    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
+    do {
+        len = read(fd, buffer, sizeof(buffer));
+    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
+}
+
+static int qemu_event_init(void)
+{
+    int err;
+    int fds[2];
+
+    err = qemu_eventfd(fds);
+    if (err == -1) {
+        return -errno;
+    }
+    err = fcntl_setfl(fds[0], O_NONBLOCK);
+    if (err < 0) {
+        goto fail;
+    }
+    err = fcntl_setfl(fds[1], O_NONBLOCK);
+    if (err < 0) {
+        goto fail;
+    }
+    qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
+                         (void *)(intptr_t)fds[0]);
+
+    io_thread_fd = fds[1];
+    return 0;
+
+fail:
+    close(fds[0]);
+    close(fds[1]);
+    return err;
+}
+
+/* If we have signalfd, we mask out the signals we want to handle and then
+ * use signalfd to listen for them.  We rely on whatever the current signal
+ * handler is to dispatch the signals when we receive them.
+ */
+static void sigfd_handler(void *opaque)
+{
+    int fd = (intptr_t)opaque;
+    struct qemu_signalfd_siginfo info;
+    struct sigaction action;
+    ssize_t len;
+
+    while (1) {
+        do {
+            len = read(fd, &info, sizeof(info));
+        } while (len == -1 && errno == EINTR);
+
+        if (len == -1 && errno == EAGAIN) {
+            break;
+        }
+
+        if (len != sizeof(info)) {
+            printf("read from sigfd returned %zd: %m\n", len);
+            return;
+        }
+
+        sigaction(info.ssi_signo, NULL, &action);
+        if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
+            action.sa_sigaction(info.ssi_signo,
+                                (siginfo_t *)&info, NULL);
+        } else if (action.sa_handler) {
+            action.sa_handler(info.ssi_signo);
+        }
+    }
+}
+
+static int qemu_signal_init(void)
+{
+    int sigfd;
+    sigset_t set;
+
+    /*
+     * SIG_IPI must be blocked in the main thread and must not be caught
+     * by sigwait() in the signal thread. Otherwise, the cpu thread will
+     * not catch it reliably.
+     */
+    sigemptyset(&set);
+    sigaddset(&set, SIG_IPI);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGIO);
+    sigaddset(&set, SIGALRM);
+    sigaddset(&set, SIGBUS);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+    sigfd = qemu_signalfd(&set);
+    if (sigfd == -1) {
+        fprintf(stderr, "failed to create signalfd\n");
+        return -errno;
+    }
+
+    fcntl_setfl(sigfd, O_NONBLOCK);
+
+    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
+                         (void *)(intptr_t)sigfd);
+
+    return 0;
+}
+
+#else /* _WIN32 */
+
+HANDLE qemu_event_handle;
+
+static void dummy_event_handler(void *opaque)
+{
+}
+
+static int qemu_event_init(void)
+{
+    qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (!qemu_event_handle) {
+        fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError());
+        return -1;
+    }
+    qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
+    return 0;
+}
+
+void qemu_notify_event(void)
+{
+    if (!SetEvent(qemu_event_handle)) {
+        fprintf(stderr, "qemu_notify_event: SetEvent failed: %ld\n",
+                GetLastError());
+        exit(1);
+    }
+}
+
+static int qemu_signal_init(void)
+{
+    return 0;
+}
+#endif
+
+int qemu_init_main_loop(void)
+{
+    int ret;
+
+    ret = qemu_signal_init();
+    if (ret) {
+        return ret;
+    }
+
+    /* Note eventfd must be drained before signalfd handlers run */
+    ret = qemu_event_init();
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+
+static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
+static int n_poll_fds;
+static int max_priority;
+
+static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
+                             fd_set *xfds, struct timeval *tv)
+{
+    GMainContext *context = g_main_context_default();
+    int i;
+    int timeout = 0, cur_timeout;
+
+    g_main_context_prepare(context, &max_priority);
+
+    n_poll_fds = g_main_context_query(context, max_priority, &timeout,
+                                      poll_fds, ARRAY_SIZE(poll_fds));
+    g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
+
+    for (i = 0; i < n_poll_fds; i++) {
+        GPollFD *p = &poll_fds[i];
+
+        if ((p->events & G_IO_IN)) {
+            FD_SET(p->fd, rfds);
+            *max_fd = MAX(*max_fd, p->fd);
+        }
+        if ((p->events & G_IO_OUT)) {
+            FD_SET(p->fd, wfds);
+            *max_fd = MAX(*max_fd, p->fd);
+        }
+        if ((p->events & G_IO_ERR)) {
+            FD_SET(p->fd, xfds);
+            *max_fd = MAX(*max_fd, p->fd);
+        }
+    }
+
+    cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000);
+    if (timeout >= 0 && timeout < cur_timeout) {
+        tv->tv_sec = timeout / 1000;
+        tv->tv_usec = (timeout % 1000) * 1000;
+    }
+}
+
+static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds,
+                             bool err)
+{
+    GMainContext *context = g_main_context_default();
+
+    if (!err) {
+        int i;
+
+        for (i = 0; i < n_poll_fds; i++) {
+            GPollFD *p = &poll_fds[i];
+
+            if ((p->events & G_IO_IN) && FD_ISSET(p->fd, rfds)) {
+                p->revents |= G_IO_IN;
+            }
+            if ((p->events & G_IO_OUT) && FD_ISSET(p->fd, wfds)) {
+                p->revents |= G_IO_OUT;
+            }
+            if ((p->events & G_IO_ERR) && FD_ISSET(p->fd, xfds)) {
+                p->revents |= G_IO_ERR;
+            }
+        }
+    }
+
+    if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) {
+        g_main_context_dispatch(context);
+    }
+}
+
+#ifdef _WIN32
+/***********************************************************/
+/* Polling handling */
+
+typedef struct PollingEntry {
+    PollingFunc *func;
+    void *opaque;
+    struct PollingEntry *next;
+} PollingEntry;
+
+static PollingEntry *first_polling_entry;
+
+int qemu_add_polling_cb(PollingFunc *func, void *opaque)
+{
+    PollingEntry **ppe, *pe;
+    pe = g_malloc0(sizeof(PollingEntry));
+    pe->func = func;
+    pe->opaque = opaque;
+    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
+    *ppe = pe;
+    return 0;
+}
+
+void qemu_del_polling_cb(PollingFunc *func, void *opaque)
+{
+    PollingEntry **ppe, *pe;
+    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
+        pe = *ppe;
+        if (pe->func == func && pe->opaque == opaque) {
+            *ppe = pe->next;
+            g_free(pe);
+            break;
+        }
+    }
+}
+
+/***********************************************************/
+/* Wait objects support */
+typedef struct WaitObjects {
+    int num;
+    HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
+    WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
+    void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
+} WaitObjects;
+
+static WaitObjects wait_objects = {0};
+
+int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
+{
+    WaitObjects *w = &wait_objects;
+    if (w->num >= MAXIMUM_WAIT_OBJECTS) {
+        return -1;
+    }
+    w->events[w->num] = handle;
+    w->func[w->num] = func;
+    w->opaque[w->num] = opaque;
+    w->num++;
+    return 0;
+}
+
+void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
+{
+    int i, found;
+    WaitObjects *w = &wait_objects;
+
+    found = 0;
+    for (i = 0; i < w->num; i++) {
+        if (w->events[i] == handle) {
+            found = 1;
+        }
+        if (found) {
+            w->events[i] = w->events[i + 1];
+            w->func[i] = w->func[i + 1];
+            w->opaque[i] = w->opaque[i + 1];
+        }
+    }
+    if (found) {
+        w->num--;
+    }
+}
+
+static void os_host_main_loop_wait(int *timeout)
+{
+    int ret, ret2, i;
+    PollingEntry *pe;
+
+    /* XXX: need to suppress polling by better using win32 events */
+    ret = 0;
+    for (pe = first_polling_entry; pe != NULL; pe = pe->next) {
+        ret |= pe->func(pe->opaque);
+    }
+    if (ret == 0) {
+        int err;
+        WaitObjects *w = &wait_objects;
+
+        qemu_mutex_unlock_iothread();
+        ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
+        qemu_mutex_lock_iothread();
+        if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
+            if (w->func[ret - WAIT_OBJECT_0]) {
+                w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
+            }
+
+            /* Check for additional signaled events */
+            for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
+                /* Check if event is signaled */
+                ret2 = WaitForSingleObject(w->events[i], 0);
+                if (ret2 == WAIT_OBJECT_0) {
+                    if (w->func[i]) {
+                        w->func[i](w->opaque[i]);
+                    }
+                } else if (ret2 != WAIT_TIMEOUT) {
+                    err = GetLastError();
+                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
+                }
+            }
+        } else if (ret != WAIT_TIMEOUT) {
+            err = GetLastError();
+            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
+        }
+    }
+
+    *timeout = 0;
+}
+#else
+static inline void os_host_main_loop_wait(int *timeout)
+{
+}
+#endif
+
+int main_loop_wait(int nonblocking)
+{
+    fd_set rfds, wfds, xfds;
+    int ret, nfds;
+    struct timeval tv;
+    int timeout;
+
+    if (nonblocking) {
+        timeout = 0;
+    } else {
+        timeout = qemu_calculate_timeout();
+        qemu_bh_update_timeout(&timeout);
+    }
+
+    os_host_main_loop_wait(&timeout);
+
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
+
+    /* poll any events */
+    /* XXX: separate device handlers from system ones */
+    nfds = -1;
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    FD_ZERO(&xfds);
+
+#ifdef CONFIG_SLIRP
+    slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
+#endif
+    qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
+    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv);
+
+    if (timeout > 0) {
+        qemu_mutex_unlock_iothread();
+    }
+
+    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+
+    if (timeout > 0) {
+        qemu_mutex_lock_iothread();
+    }
+
+    glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+    qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
+#ifdef CONFIG_SLIRP
+    slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+#endif
+
+    qemu_run_all_timers();
+
+    /* Check bottom-halves last in case any of the earlier events triggered
+       them.  */
+    qemu_bh_poll();
+
+    return ret;
+}
diff --git a/os-win32.c b/os-win32.c
index f09f01f..7909401 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -48,129 +48,6 @@ int setenv(const char *name, const char *value, int overwrite)
     return result;
 }
 
-/***********************************************************/
-/* Polling handling */
-
-typedef struct PollingEntry {
-    PollingFunc *func;
-    void *opaque;
-    struct PollingEntry *next;
-} PollingEntry;
-
-static PollingEntry *first_polling_entry;
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque)
-{
-    PollingEntry **ppe, *pe;
-    pe = g_malloc0(sizeof(PollingEntry));
-    pe->func = func;
-    pe->opaque = opaque;
-    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
-    *ppe = pe;
-    return 0;
-}
-
-void qemu_del_polling_cb(PollingFunc *func, void *opaque)
-{
-    PollingEntry **ppe, *pe;
-    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
-        pe = *ppe;
-        if (pe->func == func && pe->opaque == opaque) {
-            *ppe = pe->next;
-            g_free(pe);
-            break;
-        }
-    }
-}
-
-/***********************************************************/
-/* Wait objects support */
-typedef struct WaitObjects {
-    int num;
-    HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
-    WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
-    void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
-} WaitObjects;
-
-static WaitObjects wait_objects = {0};
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
-    WaitObjects *w = &wait_objects;
-
-    if (w->num >= MAXIMUM_WAIT_OBJECTS)
-        return -1;
-    w->events[w->num] = handle;
-    w->func[w->num] = func;
-    w->opaque[w->num] = opaque;
-    w->num++;
-    return 0;
-}
-
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
-    int i, found;
-    WaitObjects *w = &wait_objects;
-
-    found = 0;
-    for (i = 0; i < w->num; i++) {
-        if (w->events[i] == handle)
-            found = 1;
-        if (found) {
-            w->events[i] = w->events[i + 1];
-            w->func[i] = w->func[i + 1];
-            w->opaque[i] = w->opaque[i + 1];
-        }
-    }
-    if (found)
-        w->num--;
-}
-
-void os_host_main_loop_wait(int *timeout)
-{
-    int ret, ret2, i;
-    PollingEntry *pe;
-
-    /* XXX: need to suppress polling by better using win32 events */
-    ret = 0;
-    for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
-        ret |= pe->func(pe->opaque);
-    }
-    if (ret == 0) {
-        int err;
-        WaitObjects *w = &wait_objects;
-
-        qemu_mutex_unlock_iothread();
-        ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
-        qemu_mutex_lock_iothread();
-        if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
-            if (w->func[ret - WAIT_OBJECT_0])
-                w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-
-            /* Check for additional signaled events */
-            for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-
-                /* Check if event is signaled */
-                ret2 = WaitForSingleObject(w->events[i], 0);
-                if(ret2 == WAIT_OBJECT_0) {
-                    if (w->func[i])
-                        w->func[i](w->opaque[i]);
-                } else if (ret2 == WAIT_TIMEOUT) {
-                } else {
-                    err = GetLastError();
-                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
-                }
-            }
-        } else if (ret == WAIT_TIMEOUT) {
-        } else {
-            err = GetLastError();
-            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
-        }
-    }
-
-    *timeout = 0;
-}
-
 static BOOL WINAPI qemu_ctrl_handler(DWORD type)
 {
     exit(STATUS_CONTROL_C_EXIT);
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 81fd9ab..920499d 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -26,10 +26,6 @@
 #ifndef QEMU_OS_POSIX_H
 #define QEMU_OS_POSIX_H
 
-static inline void os_host_main_loop_wait(int *timeout)
-{
-}
-
 void os_set_line_buffering(void);
 void os_set_proc_name(const char *s);
 void os_setup_signal_handling(void);
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 8a069d7..84e4d35 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -28,26 +28,13 @@
 
 #include <windows.h>
 #include <winsock2.h>
+#include "main-loop.h"
 
 /* Declaration of ffs() is missing in MinGW's strings.h. */
 int ffs(int i);
 
 /* Polling handling */
 
-/* return TRUE if no sleep should be done afterwards */
-typedef int PollingFunc(void *opaque);
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque);
-void qemu_del_polling_cb(PollingFunc *func, void *opaque);
-
-/* Wait objects handling */
-typedef void WaitObjectFunc(void *opaque);
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
-
-void os_host_main_loop_wait(int *timeout);
-
 static inline void os_setup_signal_handling(void) {}
 static inline void os_daemonize(void) {}
 static inline void os_setup_post(void) {}
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index a755123..890fd86 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -3,8 +3,6 @@
 
 #include "qemu-common.h"
 
-#ifdef CONFIG_SLIRP
-
 struct Slirp;
 typedef struct Slirp Slirp;
 
@@ -44,13 +42,4 @@ void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr,
 size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
                              int guest_port);
 
-#else /* !CONFIG_SLIRP */
-
-static inline void slirp_select_fill(int *pnfds, fd_set *readfds,
-                                     fd_set *writefds, fd_set *xfds) { }
-
-static inline void slirp_select_poll(fd_set *readfds, fd_set *writefds,
-                                     fd_set *xfds, int select_error) { }
-#endif /* !CONFIG_SLIRP */
-
 #endif
diff --git a/vl.c b/vl.c
index 8e8cbf2..530afeb 100644
--- a/vl.c
+++ b/vl.c
@@ -1437,128 +1437,6 @@ void qemu_system_vmstop_request(RunState state)
     qemu_notify_event();
 }
 
-static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
-static int n_poll_fds;
-static int max_priority;
-
-static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
-                             fd_set *xfds, struct timeval *tv)
-{
-    GMainContext *context = g_main_context_default();
-    int i;
-    int timeout = 0, cur_timeout;
-
-    g_main_context_prepare(context, &max_priority);
-
-    n_poll_fds = g_main_context_query(context, max_priority, &timeout,
-                                      poll_fds, ARRAY_SIZE(poll_fds));
-    g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
-
-    for (i = 0; i < n_poll_fds; i++) {
-        GPollFD *p = &poll_fds[i];
-
-        if ((p->events & G_IO_IN)) {
-            FD_SET(p->fd, rfds);
-            *max_fd = MAX(*max_fd, p->fd);
-        }
-        if ((p->events & G_IO_OUT)) {
-            FD_SET(p->fd, wfds);
-            *max_fd = MAX(*max_fd, p->fd);
-        }
-        if ((p->events & G_IO_ERR)) {
-            FD_SET(p->fd, xfds);
-            *max_fd = MAX(*max_fd, p->fd);
-        }
-    }
-
-    cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000);
-    if (timeout >= 0 && timeout < cur_timeout) {
-        tv->tv_sec = timeout / 1000;
-        tv->tv_usec = (timeout % 1000) * 1000;
-    }
-}
-
-static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds,
-                             bool err)
-{
-    GMainContext *context = g_main_context_default();
-
-    if (!err) {
-        int i;
-
-        for (i = 0; i < n_poll_fds; i++) {
-            GPollFD *p = &poll_fds[i];
-
-            if ((p->events & G_IO_IN) && FD_ISSET(p->fd, rfds)) {
-                p->revents |= G_IO_IN;
-            }
-            if ((p->events & G_IO_OUT) && FD_ISSET(p->fd, wfds)) {
-                p->revents |= G_IO_OUT;
-            }
-            if ((p->events & G_IO_ERR) && FD_ISSET(p->fd, xfds)) {
-                p->revents |= G_IO_ERR;
-            }
-        }
-    }
-
-    if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) {
-        g_main_context_dispatch(context);
-    }
-}
-
-int main_loop_wait(int nonblocking)
-{
-    fd_set rfds, wfds, xfds;
-    int ret, nfds;
-    struct timeval tv;
-    int timeout;
-
-    if (nonblocking)
-        timeout = 0;
-    else {
-        timeout = qemu_calculate_timeout();
-        qemu_bh_update_timeout(&timeout);
-    }
-
-    os_host_main_loop_wait(&timeout);
-
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
-
-    /* poll any events */
-    /* XXX: separate device handlers from system ones */
-    nfds = -1;
-    FD_ZERO(&rfds);
-    FD_ZERO(&wfds);
-    FD_ZERO(&xfds);
-
-    qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
-    slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
-    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv);
-
-    if (timeout > 0) {
-        qemu_mutex_unlock_iothread();
-    }
-
-    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
-
-    if (timeout > 0) {
-        qemu_mutex_lock_iothread();
-    }
-
-    qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
-    slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
-    glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
-
-    qemu_run_all_timers();
-
-    /* Check bottom-halves last in case any of the earlier events triggered
-       them.  */
-    qemu_bh_poll();
-
-    return ret;
-}
-
 qemu_irq qemu_system_powerdown;
 
 static void main_loop(void)
@@ -3301,6 +3179,7 @@ int main(int argc, char **argv, char **envp)
 
     configure_accelerator();
 
+    qemu_init_cpu_loop();
     if (qemu_init_main_loop()) {
         fprintf(stderr, "qemu_init_main_loop failed\n");
         exit(1);
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 11/12] Revert to a hand-made select loop
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
                   ` (9 preceding siblings ...)
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 10/12] create main-loop.c Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 12/12] simplify main loop functions Paolo Bonzini
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

This reverts commit c82dc29a9112f34e0a51cad9a412cf6d9d05dfb2
and 4d88a2ac8643265108ef1fb47ceee5d7b28e19f2.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 iohandler.c |   54 +-----------------------------------------------------
 1 files changed, 1 insertions(+), 53 deletions(-)

diff --git a/iohandler.c b/iohandler.c
index 4cc1c5a..4deae1e 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -80,64 +80,12 @@ int qemu_set_fd_handler2(int fd,
     return 0;
 }
 
-typedef struct IOTrampoline
-{
-    GIOChannel *chan;
-    IOHandler *fd_read;
-    IOHandler *fd_write;
-    void *opaque;
-    guint tag;
-} IOTrampoline;
-
-static gboolean fd_trampoline(GIOChannel *chan, GIOCondition cond, gpointer opaque)
-{
-    IOTrampoline *tramp = opaque;
-
-    if ((cond & G_IO_IN) && tramp->fd_read) {
-        tramp->fd_read(tramp->opaque);
-    }
-
-    if ((cond & G_IO_OUT) && tramp->fd_write) {
-        tramp->fd_write(tramp->opaque);
-    }
-
-    return TRUE;
-}
-
 int qemu_set_fd_handler(int fd,
                         IOHandler *fd_read,
                         IOHandler *fd_write,
                         void *opaque)
 {
-    static IOTrampoline fd_trampolines[FD_SETSIZE];
-    IOTrampoline *tramp = &fd_trampolines[fd];
-
-    if (tramp->tag != 0) {
-        g_io_channel_unref(tramp->chan);
-        g_source_remove(tramp->tag);
-        tramp->tag = 0;
-    }
-
-    if (fd_read || fd_write || opaque) {
-        GIOCondition cond = 0;
-
-        tramp->fd_read = fd_read;
-        tramp->fd_write = fd_write;
-        tramp->opaque = opaque;
-
-        if (fd_read) {
-            cond |= G_IO_IN | G_IO_ERR;
-        }
-
-        if (fd_write) {
-            cond |= G_IO_OUT | G_IO_ERR;
-        }
-
-        tramp->chan = g_io_channel_unix_new(fd);
-        tramp->tag = g_io_add_watch(tramp->chan, cond, fd_trampoline, tramp);
-    }
-
-    return 0;
+    return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
 }
 
 void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds)
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 12/12] simplify main loop functions
  2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
                   ` (10 preceding siblings ...)
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 11/12] Revert to a hand-made select loop Paolo Bonzini
@ 2011-09-27 16:31 ` Paolo Bonzini
  11 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-27 16:31 UTC (permalink / raw)
  To: qemu-devel

Provide a clean example of how to use the main loop in the tools.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cpus.c |    5 ----
 cpus.h |    1 -
 vl.c   |   80 +++++++++++++++++++++++++++++++++------------------------------
 3 files changed, 42 insertions(+), 44 deletions(-)

diff --git a/cpus.c b/cpus.c
index 826c88b..d1e2817 100644
--- a/cpus.c
+++ b/cpus.c
@@ -628,11 +628,6 @@ void qemu_init_cpu_loop(void)
     qemu_thread_get_self(&io_thread);
 }
 
-void qemu_main_loop_start(void)
-{
-    resume_all_vcpus();
-}
-
 void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
 {
     struct qemu_work_item wi;
diff --git a/cpus.h b/cpus.h
index 7422584..3525375 100644
--- a/cpus.h
+++ b/cpus.h
@@ -3,7 +3,6 @@
 
 /* cpus.c */
 void qemu_init_cpu_loop(void);
-void qemu_main_loop_start(void);
 void resume_all_vcpus(void);
 void pause_all_vcpus(void);
 void cpu_stop_current(void);
diff --git a/vl.c b/vl.c
index 530afeb..3efeb1a 100644
--- a/vl.c
+++ b/vl.c
@@ -1439,18 +1439,50 @@ void qemu_system_vmstop_request(RunState state)
 
 qemu_irq qemu_system_powerdown;
 
+static bool main_loop_should_exit(void)
+{
+    int r;
+    if (qemu_debug_requested()) {
+        vm_stop(RSTATE_DEBUG);
+    }
+    if (qemu_shutdown_requested()) {
+        qemu_kill_report();
+        monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
+        if (no_shutdown) {
+            vm_stop(RSTATE_SHUTDOWN);
+        } else {
+            return true;
+        }
+    }
+    if (qemu_reset_requested()) {
+        pause_all_vcpus();
+        cpu_synchronize_all_states();
+        qemu_system_reset(VMRESET_REPORT);
+        resume_all_vcpus();
+        if (runstate_check(RSTATE_PANICKED) ||
+            runstate_check(RSTATE_SHUTDOWN)) {
+            runstate_set(RSTATE_PAUSED);
+        }
+    }
+    if (qemu_powerdown_requested()) {
+        monitor_protocol_event(QEVENT_POWERDOWN, NULL);
+        qemu_irq_raise(qemu_system_powerdown);
+    }
+    r = qemu_vmstop_requested();
+    if (r) {
+        vm_stop(r);
+    }
+    return false;
+}
+
 static void main_loop(void)
 {
     bool nonblocking;
-    int last_io __attribute__ ((unused)) = 0;
+    int last_io = 0;
 #ifdef CONFIG_PROFILER
     int64_t ti;
 #endif
-    int r;
-
-    qemu_main_loop_start();
-
-    for (;;) {
+    do {
         nonblocking = !kvm_enabled() && last_io > 0;
 #ifdef CONFIG_PROFILER
         ti = profile_getclock();
@@ -1459,38 +1491,7 @@ static void main_loop(void)
 #ifdef CONFIG_PROFILER
         dev_time += profile_getclock() - ti;
 #endif
-
-        if (qemu_debug_requested()) {
-            vm_stop(RSTATE_DEBUG);
-        }
-        if (qemu_shutdown_requested()) {
-            qemu_kill_report();
-            monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
-            if (no_shutdown) {
-                vm_stop(RSTATE_SHUTDOWN);
-            } else
-                break;
-        }
-        if (qemu_reset_requested()) {
-            pause_all_vcpus();
-            cpu_synchronize_all_states();
-            qemu_system_reset(VMRESET_REPORT);
-            resume_all_vcpus();
-            if (runstate_check(RSTATE_PANICKED) ||
-                runstate_check(RSTATE_SHUTDOWN)) {
-                runstate_set(RSTATE_PAUSED);
-            }
-        }
-        if (qemu_powerdown_requested()) {
-            monitor_protocol_event(QEVENT_POWERDOWN, NULL);
-            qemu_irq_raise(qemu_system_powerdown);
-        }
-        if ((r = qemu_vmstop_requested())) {
-            vm_stop(r);
-        }
-    }
-    bdrv_close_all();
-    pause_all_vcpus();
+    } while (!main_loop_should_exit());
 }
 
 static void version(void)
@@ -3452,7 +3453,10 @@ int main(int argc, char **argv, char **envp)
 
     os_setup_post();
 
+    resume_all_vcpus();
     main_loop();
+    bdrv_close_all();
+    pause_all_vcpus();
     net_cleanup();
     res_free();
 
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 03/12] qemu-timer: more clock functions
  2011-09-27 16:31 ` [Qemu-devel] [PATCH 03/12] qemu-timer: more clock functions Paolo Bonzini
@ 2011-09-30 10:52   ` Lluís Vilanova
  2011-09-30 11:03     ` Paolo Bonzini
  0 siblings, 1 reply; 16+ messages in thread
From: Lluís Vilanova @ 2011-09-30 10:52 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Paolo Bonzini writes:

> These will be used when moving icount accounting to cpus.c.

I have something related to this kind of refactoring. While trying to understand
all the timing facilities in QEMU, I wrote some (unfinished) patches that try to
disentangle much of the code in qemu-timer into two new files:

- qemu-htime: Provides routines related to time in the host.
- qemu-vtime: Provides routines related to time in the guest.

These patches also try to sanitize some routine names by making their domain and
units explicit (e.g., get_clock becomes qemu_htime_nsec and cpu_get_ticks
becomes qemu_vtime_tsc). The patches also make the frequency explicit (adds
qemu_htime_freq and qemu_vtime_freq).

The result should provide code that makes it very clear on which time domain and
frequency the code is operating on.

The routines in qemu-timer should be already moved into the corresponding
qemu-*time files (I no longer remember on which state I left it), but the
routine name sanitizing is not finished, mostly because I still had to clear out
some details about how the current deadline calculation works.

Does this kind of refactoring sound interesting?


Thanks,
   Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 03/12] qemu-timer: more clock functions
  2011-09-30 10:52   ` Lluís Vilanova
@ 2011-09-30 11:03     ` Paolo Bonzini
  2011-09-30 12:15       ` Lluís Vilanova
  0 siblings, 1 reply; 16+ messages in thread
From: Paolo Bonzini @ 2011-09-30 11:03 UTC (permalink / raw)
  To: qemu-devel

On 09/30/2011 12:52 PM, Lluís Vilanova wrote:
> Paolo Bonzini writes:
>
>> These will be used when moving icount accounting to cpus.c.
>
> I have something related to this kind of refactoring. While trying to understand
> all the timing facilities in QEMU, I wrote some (unfinished) patches that try to
> disentangle much of the code in qemu-timer into two new files:
>
> - qemu-htime: Provides routines related to time in the host.
> - qemu-vtime: Provides routines related to time in the guest.
>
> These patches also try to sanitize some routine names by making their domain and
> units explicit (e.g., get_clock becomes qemu_htime_nsec and cpu_get_ticks
> becomes qemu_vtime_tsc).

That's almost unnecessary, get_clock should be just 
qemu_get_clock_ns(host_clock) or something like that.  The problem is 
that the clock names are impossible to remember. :)

However, making it clear from the name whether get_clock refers to the 
host_clock or rt_clock can be a useful cleanup.

> The patches also make the frequency explicit (adds
> qemu_htime_freq and qemu_vtime_freq).

The frequency of the clocks is now always explicit in the function names 
(using _ns or _ms).

> The routines in qemu-timer should be already moved into the corresponding
> qemu-*time files (I no longer remember on which state I left it), but the
> routine name sanitizing is not finished, mostly because I still had to clear out
> some details about how the current deadline calculation works.

I think after my series there is already a similar split, with 
qemu-timer.c doing everything except the guest clock, and cpus.c taking 
care of the guest clock.

I have a few more cleanups pending in this area, but I'll submit them 
probably after 1.0 since I have enough stuff on my plate already.

> Does this kind of refactoring sound interesting?

Renaming the host_clock and rt_clock to something more easily remembered 
is trivial, but still useful.

It is also useful to make a dummy vmclock (with primitives like "get", 
"set", "advance to the next deadline") available outside qemu proper for 
use in unit tests.  I'm not sure how close we are to unit testing of 
device models, but anything that makes us closer is worthwhile.

Paolo

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 03/12] qemu-timer: more clock functions
  2011-09-30 11:03     ` Paolo Bonzini
@ 2011-09-30 12:15       ` Lluís Vilanova
  0 siblings, 0 replies; 16+ messages in thread
From: Lluís Vilanova @ 2011-09-30 12:15 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Paolo Bonzini writes:

> On 09/30/2011 12:52 PM, Lluís Vilanova wrote:
>> Paolo Bonzini writes:
>> 
>>> These will be used when moving icount accounting to cpus.c.
>> 
>> I have something related to this kind of refactoring. While trying to understand
>> all the timing facilities in QEMU, I wrote some (unfinished) patches that try to
>> disentangle much of the code in qemu-timer into two new files:
>> 
>> - qemu-htime: Provides routines related to time in the host.
>> - qemu-vtime: Provides routines related to time in the guest.
>> 
>> These patches also try to sanitize some routine names by making their domain and
>> units explicit (e.g., get_clock becomes qemu_htime_nsec and cpu_get_ticks
>> becomes qemu_vtime_tsc).

> That's almost unnecessary, get_clock should be just
> qemu_get_clock_ns(host_clock) or something like that.  The problem is that the
> clock names are impossible to remember. :)

Yes, that was the main point of my refactoring :)


> However, making it clear from the name whether get_clock refers to the
> host_clock or rt_clock can be a useful cleanup.

Well, then maybe I will resume that work after 1.0.


Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2011-09-30 12:15 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-27 16:31 [Qemu-devel] [PATCH 00/12] allow tools to use the QEMU main loop Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 01/12] qemu-timer: remove active_timers array Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 02/12] qemu-timer: move common code to qemu_rearm_alarm_timer Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 03/12] qemu-timer: more clock functions Paolo Bonzini
2011-09-30 10:52   ` Lluís Vilanova
2011-09-30 11:03     ` Paolo Bonzini
2011-09-30 12:15       ` Lluís Vilanova
2011-09-27 16:31 ` [Qemu-devel] [PATCH 04/12] qemu-timer: move icount to cpus.c Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 05/12] qemu-timer: do not refer to runstate_is_running() Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 06/12] qemu-timer: use atexit for quit_timers Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 07/12] qemu-timer: move more stuff out of qemu-timer.c Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 08/12] qemu-timer: do not use RunState change handlers Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 09/12] create main-loop.h Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 10/12] create main-loop.c Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 11/12] Revert to a hand-made select loop Paolo Bonzini
2011-09-27 16:31 ` [Qemu-devel] [PATCH 12/12] simplify main loop functions Paolo Bonzini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.