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-img-cmds.h
|
||||||
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS)
|
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
|
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
|
||||||
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $@")
|
$(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_THREAD) += qemu-thread.o
|
||||||
common-obj-$(CONFIG_IOTHREAD) += compatfd.o
|
common-obj-$(CONFIG_IOTHREAD) += compatfd.o
|
||||||
common-obj-y += notify.o event_notifier.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 = 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
|
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
|
trace-obj-y = trace.o
|
||||||
ifeq ($(TRACE_BACKEND),simple)
|
ifeq ($(TRACE_BACKEND),simple)
|
||||||
trace-obj-y += simpletrace.o
|
trace-obj-y += simpletrace.o
|
||||||
|
user-obj-y += qemu-timer-common.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
|
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
|
||||||
|
@ -97,9 +97,9 @@
|
|||||||
#define FTYPE_CD 1
|
#define FTYPE_CD 1
|
||||||
#define FTYPE_FD 2
|
#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 */
|
reopen it to see if the disk has been changed */
|
||||||
#define FD_OPEN_TIMEOUT 1000
|
#define FD_OPEN_TIMEOUT (1000000000)
|
||||||
|
|
||||||
#define MAX_BLOCKSIZE 4096
|
#define MAX_BLOCKSIZE 4096
|
||||||
|
|
||||||
@ -908,7 +908,7 @@ static int fd_open(BlockDriverState *bs)
|
|||||||
return 0;
|
return 0;
|
||||||
last_media_present = (s->fd >= 0);
|
last_media_present = (s->fd >= 0);
|
||||||
if (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);
|
close(s->fd);
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
#ifdef DEBUG_FLOPPY
|
#ifdef DEBUG_FLOPPY
|
||||||
@ -917,7 +917,7 @@ static int fd_open(BlockDriverState *bs)
|
|||||||
}
|
}
|
||||||
if (s->fd < 0) {
|
if (s->fd < 0) {
|
||||||
if (s->fd_got_error &&
|
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
|
#ifdef DEBUG_FLOPPY
|
||||||
printf("No floppy (open delayed)\n");
|
printf("No floppy (open delayed)\n");
|
||||||
#endif
|
#endif
|
||||||
@ -925,7 +925,7 @@ static int fd_open(BlockDriverState *bs)
|
|||||||
}
|
}
|
||||||
s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK);
|
s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK);
|
||||||
if (s->fd < 0) {
|
if (s->fd < 0) {
|
||||||
s->fd_error_time = qemu_get_clock(rt_clock);
|
s->fd_error_time = get_clock();
|
||||||
s->fd_got_error = 1;
|
s->fd_got_error = 1;
|
||||||
if (last_media_present)
|
if (last_media_present)
|
||||||
s->fd_media_changed = 1;
|
s->fd_media_changed = 1;
|
||||||
@ -940,7 +940,7 @@ static int fd_open(BlockDriverState *bs)
|
|||||||
}
|
}
|
||||||
if (!last_media_present)
|
if (!last_media_present)
|
||||||
s->fd_media_changed = 1;
|
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;
|
s->fd_got_error = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "omap.h"
|
#include "omap.h"
|
||||||
|
#include "qemu-timer.h" /* for muldiv64() */
|
||||||
|
|
||||||
struct clk {
|
struct clk {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -133,8 +133,6 @@ void qemu_bh_delete(QEMUBH *bh);
|
|||||||
int qemu_bh_poll(void);
|
int qemu_bh_poll(void);
|
||||||
void qemu_bh_update_timeout(int *timeout);
|
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);
|
void qemu_get_timedate(struct tm *tm, int offset);
|
||||||
int qemu_timedate_diff(struct tm *tm);
|
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_rt_timer;
|
||||||
static QEMUTimer *icount_vm_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 */
|
/* guest cycle counter */
|
||||||
|
|
||||||
@ -614,7 +542,6 @@ int64_t qemu_get_clock_ns(QEMUClock *clock)
|
|||||||
|
|
||||||
void init_clocks(void)
|
void init_clocks(void)
|
||||||
{
|
{
|
||||||
init_get_clock();
|
|
||||||
rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
|
rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
|
||||||
vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
|
vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
|
||||||
host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
|
host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
|
||||||
|
74
qemu-timer.h
74
qemu-timer.h
@ -2,6 +2,13 @@
|
|||||||
#define QEMU_TIMER_H
|
#define QEMU_TIMER_H
|
||||||
|
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* timers */
|
/* timers */
|
||||||
|
|
||||||
@ -52,6 +59,73 @@ static inline int64_t get_ticks_per_sec(void)
|
|||||||
return 1000000000LL;
|
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_get_timer(QEMUFile *f, QEMUTimer *ts);
|
||||||
void qemu_put_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;
|
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 <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "qemu-timer.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
/** Trace file header event ID */
|
/** 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)
|
uint64_t x4, uint64_t x5, uint64_t x6)
|
||||||
{
|
{
|
||||||
TraceRecord *rec = &trace_buf[trace_idx];
|
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) {
|
if (!trace_list[event].state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec->event = event;
|
rec->event = event;
|
||||||
rec->timestamp_ns = ts.tv_sec * 1000000000LL + ts.tv_nsec;
|
rec->timestamp_ns = get_clock();
|
||||||
rec->x1 = x1;
|
rec->x1 = x1;
|
||||||
rec->x2 = x2;
|
rec->x2 = x2;
|
||||||
rec->x3 = x3;
|
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 */
|
/* 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 */
|
/* host time/date access */
|
||||||
void qemu_get_timedate(struct tm *tm, int offset)
|
void qemu_get_timedate(struct tm *tm, int offset)
|
||||||
|
Loading…
Reference in New Issue
Block a user