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 <stefanha@linux.vnet.ibm.com> Acked-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
2b2e59e6c9
commit
c57c846a80
6
Makefile
6
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 $@")
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
#include "hw.h"
|
||||
#include "omap.h"
|
||||
#include "qemu-timer.h" /* for muldiv64() */
|
||||
|
||||
struct clk {
|
||||
const char *name;
|
||||
|
@ -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);
|
||||
|
||||
|
62
qemu-timer-common.c
Normal file
62
qemu-timer-common.c
Normal file
@ -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
|
73
qemu-timer.c
73
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);
|
||||
|
74
qemu-timer.h
74
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
24
vl.c
24
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)
|
||||
|
Loading…
Reference in New Issue
Block a user