Patchwork qemu-timer: move commonly used timer code to qemu-timer-common

login
register
mail settings
Submitter Blue Swirl
Date Oct. 17, 2010, 1:50 p.m.
Message ID <AANLkTinwpPpQQ2S=HGVSs-ZaHogNWJBHtXoq+OdRosD5@mail.gmail.com>
Download mbox | patch
Permalink /patch/68081/
State New
Headers show

Comments

Blue Swirl - Oct. 17, 2010, 1:50 p.m.
Move timer init functions to a new file, qemu-timer-common.c. Make other
critical timer functions inlined to preserve performance in
qemu-timer.c, also move muldiv64() (used by the inline functions)
to qemu-timer.h.

Adjust block/raw-posix.c and simpletrace.c to use get_clock() directly.
Remove a similar/duplicate definition in qemu-tool.c.

Adjust hw/omap_clk.c to include qemu-timer.h because muldiv64() is used
there.

After this change, tracing can be used also for user code and
simpletrace on Win32.

Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
---
 Makefile            |    6 ++--
 Makefile.objs       |    3 +-
 block/raw-posix.c   |   12 ++++----
 hw/omap_clk.c       |    1 +
 qemu-common.h       |    2 -
 qemu-timer-common.c |   62 ++++++++++++++++++++++++++++++++++++++++++
 qemu-timer.c        |   73 --------------------------------------------------
 qemu-timer.h        |   74 +++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-tool.c         |    7 -----
 simpletrace.c       |   10 +-----
 vl.c                |   24 ----------------
 11 files changed, 150 insertions(+), 124 deletions(-)
 create mode 100644 qemu-timer-common.c

 void qemu_get_timedate(struct tm *tm, int offset)
Stefan Hajnoczi - Oct. 18, 2010, 10:42 a.m.
On Sun, Oct 17, 2010 at 01:50:33PM +0000, Blue Swirl wrote:
> Move timer init functions to a new file, qemu-timer-common.c. Make other
> critical timer functions inlined to preserve performance in
> qemu-timer.c, also move muldiv64() (used by the inline functions)
> to qemu-timer.h.
> 
> Adjust block/raw-posix.c and simpletrace.c to use get_clock() directly.
> Remove a similar/duplicate definition in qemu-tool.c.
> 
> Adjust hw/omap_clk.c to include qemu-timer.h because muldiv64() is used
> there.
> 
> After this change, tracing can be used also for user code and
> simpletrace on Win32.
> 
> Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
> ---
>  Makefile            |    6 ++--
>  Makefile.objs       |    3 +-
>  block/raw-posix.c   |   12 ++++----
>  hw/omap_clk.c       |    1 +
>  qemu-common.h       |    2 -
>  qemu-timer-common.c |   62 ++++++++++++++++++++++++++++++++++++++++++
>  qemu-timer.c        |   73 --------------------------------------------------
>  qemu-timer.h        |   74 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  qemu-tool.c         |    7 -----
>  simpletrace.c       |   10 +-----
>  vl.c                |   24 ----------------
>  11 files changed, 150 insertions(+), 124 deletions(-)
>  create mode 100644 qemu-timer-common.c

Acked-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>

Patch

diff --git a/Makefile b/Makefile
index 252c817..a1434b1 100644
--- a/Makefile
+++ b/Makefile
@@ -129,11 +129,11 @@  version-obj-$(CONFIG_WIN32) += version.o
 qemu-img.o: qemu-img-cmds.h
 qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS)

-qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(trace-obj-y)
$(block-obj-y) $(qobject-obj-y) $(version-obj-y)
+qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(trace-obj-y)
$(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o

-qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(trace-obj-y)
$(block-obj-y) $(qobject-obj-y) $(version-obj-y)
+qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(trace-obj-y)
$(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o

-qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o
$(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y)
+qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o
$(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y)
qemu-timer-common.o

 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@,"  GEN   $@")
diff --git a/Makefile.objs b/Makefile.objs
index 816194a..7e170c0 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -126,7 +126,7 @@  common-obj-y += $(addprefix ui/, $(ui-obj-y))
 common-obj-y += iov.o acl.o
 common-obj-$(CONFIG_THREAD) += qemu-thread.o
 common-obj-y += notify.o event_notifier.o
-common-obj-y += qemu-timer.o
+common-obj-y += qemu-timer.o qemu-timer-common.o

 slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
 slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
@@ -276,6 +276,7 @@  libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o
 trace-obj-y = trace.o
 ifeq ($(TRACE_BACKEND),simple)
 trace-obj-y += simpletrace.o
+user-obj-y += qemu-timer-common.o
 endif

 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/block/raw-posix.c b/block/raw-posix.c
index a5cbb7e..d0393e0 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -97,9 +97,9 @@ 
 #define FTYPE_CD     1
 #define FTYPE_FD     2

-/* if the FD is not accessed during that time (in ms), we try to
+/* if the FD is not accessed during that time (in ns), we try to
    reopen it to see if the disk has been changed */
-#define FD_OPEN_TIMEOUT 1000
+#define FD_OPEN_TIMEOUT (1000000000)

 #define MAX_BLOCKSIZE	4096

@@ -908,7 +908,7 @@  static int fd_open(BlockDriverState *bs)
         return 0;
     last_media_present = (s->fd >= 0);
     if (s->fd >= 0 &&
-        (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
+        (get_clock() - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
         close(s->fd);
         s->fd = -1;
 #ifdef DEBUG_FLOPPY
@@ -917,7 +917,7 @@  static int fd_open(BlockDriverState *bs)
     }
     if (s->fd < 0) {
         if (s->fd_got_error &&
-            (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
+            (get_clock() - s->fd_error_time) < FD_OPEN_TIMEOUT) {
 #ifdef DEBUG_FLOPPY
             printf("No floppy (open delayed)\n");
 #endif
@@ -925,7 +925,7 @@  static int fd_open(BlockDriverState *bs)
         }
         s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK);
         if (s->fd < 0) {
-            s->fd_error_time = qemu_get_clock(rt_clock);
+            s->fd_error_time = get_clock();
             s->fd_got_error = 1;
             if (last_media_present)
                 s->fd_media_changed = 1;
@@ -940,7 +940,7 @@  static int fd_open(BlockDriverState *bs)
     }
     if (!last_media_present)
         s->fd_media_changed = 1;
-    s->fd_open_time = qemu_get_clock(rt_clock);
+    s->fd_open_time = get_clock();
     s->fd_got_error = 0;
     return 0;
 }
diff --git a/hw/omap_clk.c b/hw/omap_clk.c
index 6bcabef..10c9c43 100644
--- a/hw/omap_clk.c
+++ b/hw/omap_clk.c
@@ -20,6 +20,7 @@ 
  */
 #include "hw.h"
 #include "omap.h"
+#include "qemu-timer.h" /* for muldiv64() */

 struct clk {
     const char *name;
diff --git a/qemu-common.h b/qemu-common.h
index 81aafa0..2ca2ac9 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -138,8 +138,6 @@  void qemu_bh_delete(QEMUBH *bh);
 int qemu_bh_poll(void);
 void qemu_bh_update_timeout(int *timeout);

-uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
-
 void qemu_get_timedate(struct tm *tm, int offset);
 int qemu_timedate_diff(struct tm *tm);

diff --git a/qemu-timer-common.c b/qemu-timer-common.c
new file mode 100644
index 0000000..fff4399
--- /dev/null
+++ b/qemu-timer-common.c
@@ -0,0 +1,62 @@ 
+/*
+ * 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 "qemu-timer.h"
+
+/***********************************************************/
+/* real time host monotonic timer */
+
+#ifdef _WIN32
+
+int64_t clock_freq;
+
+static void __attribute__((constructor)) init_get_clock(void)
+{
+    LARGE_INTEGER freq;
+    int ret;
+    ret = QueryPerformanceFrequency(&freq);
+    if (ret == 0) {
+        fprintf(stderr, "Could not calibrate ticks\n");
+        exit(1);
+    }
+    clock_freq = freq.QuadPart;
+}
+
+#else
+
+int use_rt_clock;
+
+static void __attribute__((constructor)) init_get_clock(void)
+{
+    use_rt_clock = 0;
+#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version
>= 500000) \
+    || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+    {
+        struct timespec ts;
+        if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+            use_rt_clock = 1;
+        }
+    }
+#endif
+}
+#endif
diff --git a/qemu-timer.c b/qemu-timer.c
index bc5f207..95814af 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -64,78 +64,6 @@  int64_t qemu_icount_bias;
 static QEMUTimer *icount_rt_timer;
 static QEMUTimer *icount_vm_timer;

-
-/***********************************************************/
-/* real time host monotonic timer */
-
-
-static int64_t get_clock_realtime(void)
-{
-    struct timeval tv;
-
-    gettimeofday(&tv, NULL);
-    return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
-}
-
-#ifdef WIN32
-
-static int64_t clock_freq;
-
-static void init_get_clock(void)
-{
-    LARGE_INTEGER freq;
-    int ret;
-    ret = QueryPerformanceFrequency(&freq);
-    if (ret == 0) {
-        fprintf(stderr, "Could not calibrate ticks\n");
-        exit(1);
-    }
-    clock_freq = freq.QuadPart;
-}
-
-static int64_t get_clock(void)
-{
-    LARGE_INTEGER ti;
-    QueryPerformanceCounter(&ti);
-    return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq);
-}
-
-#else
-
-static int use_rt_clock;
-
-static void init_get_clock(void)
-{
-    use_rt_clock = 0;
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version
>= 500000) \
-    || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
-    {
-        struct timespec ts;
-        if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
-            use_rt_clock = 1;
-        }
-    }
-#endif
-}
-
-static int64_t get_clock(void)
-{
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version
>= 500000) \
-	|| defined(__DragonFly__) || defined(__FreeBSD_kernel__)
-    if (use_rt_clock) {
-        struct timespec ts;
-        clock_gettime(CLOCK_MONOTONIC, &ts);
-        return ts.tv_sec * 1000000000LL + ts.tv_nsec;
-    } else
-#endif
-    {
-        /* XXX: using gettimeofday leads to problems if the date
-           changes, so it should be avoided. */
-        return get_clock_realtime();
-    }
-}
-#endif
-
 /***********************************************************/
 /* guest cycle counter */

@@ -614,7 +542,6 @@  int64_t qemu_get_clock_ns(QEMUClock *clock)

 void init_clocks(void)
 {
-    init_get_clock();
     rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
     vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
     host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
diff --git a/qemu-timer.h b/qemu-timer.h
index 1494f79..299e387 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -2,6 +2,13 @@ 
 #define QEMU_TIMER_H

 #include "qemu-common.h"
+#include <time.h>
+#include <sys/time.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#include <mmsystem.h>
+#endif

 /* timers */

@@ -52,6 +59,73 @@  static inline int64_t get_ticks_per_sec(void)
     return 1000000000LL;
 }

+/* compute with 96 bit intermediate result: (a*b)/c */
+static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+    union {
+        uint64_t ll;
+        struct {
+#ifdef HOST_WORDS_BIGENDIAN
+            uint32_t high, low;
+#else
+            uint32_t low, high;
+#endif
+        } l;
+    } u, res;
+    uint64_t rl, rh;
+
+    u.ll = a;
+    rl = (uint64_t)u.l.low * (uint64_t)b;
+    rh = (uint64_t)u.l.high * (uint64_t)b;
+    rh += (rl >> 32);
+    res.l.high = rh / c;
+    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+    return res.ll;
+}
+
+/* real time host monotonic timer */
+static inline int64_t get_clock_realtime(void)
+{
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
+}
+
+/* Warning: don't insert tracepoints into these functions, they are
+   also used by simpletrace backend and tracepoints would cause
+   an infinite recursion! */
+#ifdef _WIN32
+extern int64_t clock_freq;
+
+static inline int64_t get_clock(void)
+{
+    LARGE_INTEGER ti;
+    QueryPerformanceCounter(&ti);
+    return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq);
+}
+
+#else
+
+extern int use_rt_clock;
+
+static inline int64_t get_clock(void)
+{
+#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version
>= 500000) \
+    || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+    if (use_rt_clock) {
+        struct timespec ts;
+        clock_gettime(CLOCK_MONOTONIC, &ts);
+        return ts.tv_sec * 1000000000LL + ts.tv_nsec;
+    } else
+#endif
+    {
+        /* XXX: using gettimeofday leads to problems if the date
+           changes, so it should be avoided. */
+        return get_clock_realtime();
+    }
+}
+#endif

 void qemu_get_timer(QEMUFile *f, QEMUTimer *ts);
 void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
diff --git a/qemu-tool.c b/qemu-tool.c
index b39af86..9ccca65 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -110,10 +110,3 @@  int qemu_set_fd_handler2(int fd,
 {
     return 0;
 }
-
-int64_t qemu_get_clock(QEMUClock *clock)
-{
-    qemu_timeval tv;
-    qemu_gettimeofday(&tv);
-    return (tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000)) / 1000000;
-}
diff --git a/simpletrace.c b/simpletrace.c
index b488d51..9ea0d1f 100644
--- a/simpletrace.c
+++ b/simpletrace.c
@@ -12,6 +12,7 @@ 
 #include <stdint.h>
 #include <stdio.h>
 #include <time.h>
+#include "qemu-timer.h"
 #include "trace.h"

 /** Trace file header event ID */
@@ -140,20 +141,13 @@  static void trace(TraceEventID event, uint64_t
x1, uint64_t x2, uint64_t x3,
                   uint64_t x4, uint64_t x5, uint64_t x6)
 {
     TraceRecord *rec = &trace_buf[trace_idx];
-    struct timespec ts;
-
-    /* TODO Windows?  It would be good to use qemu-timer here but that isn't
-     * linked into qemu-tools.  Also we should avoid recursion in the tracing
-     * code, therefore it is useful to be self-contained.
-     */
-    clock_gettime(CLOCK_MONOTONIC, &ts);

     if (!trace_list[event].state) {
         return;
     }

     rec->event = event;
-    rec->timestamp_ns = ts.tv_sec * 1000000000LL + ts.tv_nsec;
+    rec->timestamp_ns = get_clock();
     rec->x1 = x1;
     rec->x2 = x2;
     rec->x3 = x3;
diff --git a/vl.c b/vl.c
index df414ef..7038952 100644
--- a/vl.c
+++ b/vl.c
@@ -289,30 +289,6 @@  static int default_driver_check(QemuOpts *opts,
void *opaque)
 /***********************************************************/
 /* real time host monotonic timer */

-/* compute with 96 bit intermediate result: (a*b)/c */
-uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
-{
-    union {
-        uint64_t ll;
-        struct {
-#ifdef HOST_WORDS_BIGENDIAN
-            uint32_t high, low;
-#else
-            uint32_t low, high;
-#endif
-        } l;
-    } u, res;
-    uint64_t rl, rh;
-
-    u.ll = a;
-    rl = (uint64_t)u.l.low * (uint64_t)b;
-    rh = (uint64_t)u.l.high * (uint64_t)b;
-    rh += (rl >> 32);
-    res.l.high = rh / c;
-    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
-    return res.ll;
-}
-
 /***********************************************************/
 /* host time/date access */