From c57c846a80f9306aa2c6cf7efdef45ed42723fac Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sat, 23 Oct 2010 15:24:07 +0000 Subject: qemu-timer: move commonly used timer code to qemu-timer-common 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 Acked-by: Stefan Hajnoczi Signed-off-by: Blue Swirl --- 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 diff --git a/Makefile b/Makefile index 252c817d27..a1434b1bd9 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 6e6f60a3af..f07fb01bc3 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -127,7 +127,7 @@ common-obj-y += iov.o acl.o common-obj-$(CONFIG_THREAD) += qemu-thread.o common-obj-$(CONFIG_IOTHREAD) += compatfd.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 @@ -278,6 +278,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 a5cbb7e929..d0393e0c44 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 6bcabef8ac..10c9c4308c 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 d5ae42020e..2fbc27f9f0 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -133,8 +133,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 0000000000..fff43996d8 --- /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 bc5f207bb6..95814af798 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 1494f79406..299e387768 100644 --- a/qemu-timer.h +++ b/qemu-timer.h @@ -2,6 +2,13 @@ #define QEMU_TIMER_H #include "qemu-common.h" +#include +#include + +#ifdef _WIN32 +#include +#include +#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 b39af86e01..9ccca655ef 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 b488d51766..9ea0d1f984 100644 --- a/simpletrace.c +++ b/simpletrace.c @@ -12,6 +12,7 @@ #include #include #include +#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 df414ef5ac..7038952dc6 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 */ void qemu_get_timedate(struct tm *tm, int offset) -- cgit v1.2.3