#ifndef QEMU_TIMER_H
#define QEMU_TIMER_H
-#include "qemu/typedefs.h"
#include "qemu-common.h"
#include "qemu/notify.h"
+#include "qemu/host-utils.h"
+
+#define NANOSECONDS_PER_SECOND 1000000000LL
/* timers */
* @QEMU_CLOCK_REALTIME: Real time clock
*
* The real time clock should be used only for stuff which does not
- * change the virtual machine state, as it is run even if the virtual
- * machine is stopped. The real time clock has a frequency of 1000
- * Hz.
+ * change the virtual machine state, as it runs even if the virtual
+ * machine is stopped.
*
* @QEMU_CLOCK_VIRTUAL: virtual clock
*
- * The virtual clock is only run during the emulation. It is stopped
- * when the virtual machine is stopped. Virtual timers use a high
- * precision clock, usually cpu cycles (use ticks_per_sec).
+ * The virtual clock only runs during the emulation. It stops
+ * when the virtual machine is stopped.
*
* @QEMU_CLOCK_HOST: host clock
*
- * The host clock should be use for device models that emulate accurate
+ * The host clock should be used for device models that emulate accurate
* real time sources. It will continue to run when the virtual machine
* is suspended, and it will reflect system time changes the host may
- * undergo (e.g. due to NTP). The host clock has the same precision as
- * the virtual clock.
+ * undergo (e.g. due to NTP).
*
* @QEMU_CLOCK_VIRTUAL_RT: realtime clock used for icount warp
*
};
typedef void QEMUTimerCB(void *opaque);
-typedef void QEMUTimerListNotifyCB(void *opaque);
+typedef void QEMUTimerListNotifyCB(void *opaque, QEMUClockType type);
struct QEMUTimer {
int64_t expire_time; /* in nanoseconds */
extern QEMUTimerListGroup main_loop_tlg;
-/*
- * QEMUClockType
- */
-
/*
* qemu_clock_get_ns;
* @type: the clock type
* @type: the clock type
*
* Determines whether a clock's default timer list
- * has an expired clock.
+ * has an expired timer.
*
* Returns: true if the clock's default timer list has
* an expired timer
* qemu_clock_get_main_loop_timerlist:
* @type: the clock type
*
- * Return the default timer list assocatiated with a clock.
+ * Return the default timer list associated with a clock.
*
* Returns: the default timer list
*/
void qemu_clock_enable(QEMUClockType type, bool enabled);
/**
- * qemu_clock_warp:
- * @type: the clock type
+ * qemu_start_warp_timer:
*
- * Warp a clock to a new value
+ * Starts a timer for virtual clock update
*/
-void qemu_clock_warp(QEMUClockType type);
+void qemu_start_warp_timer(void);
/**
* qemu_clock_register_reset_notifier:
/**
* timer_init:
+ * @ts: the timer to be initialised
* @type: the clock to associate with the timer
* @scale: the scale value for the timer
* @cb: the callback to call when the timer expires
/**
* timer_init_ns:
+ * @ts: the timer to be initialised
* @type: the clock to associate with the timer
* @cb: the callback to call when the timer expires
* @opaque: the opaque pointer to pass to the callback
/**
* timer_init_us:
+ * @ts: the timer to be initialised
* @type: the clock to associate with the timer
* @cb: the callback to call when the timer expires
* @opaque: the opaque pointer to pass to the callback
/**
* timer_init_ms:
+ * @ts: the timer to be initialised
* @type: the clock to associate with the timer
* @cb: the callback to call when the timer expires
* @opaque: the opaque pointer to pass to the callback
* @cb: the callback to be called when the timer expires
* @opaque: the opaque pointer to be passed to the callback
*
- * Creeate a new timer and associate it with @timer_list.
+ * Create a new timer and associate it with @timer_list.
* The memory is allocated by the function.
*
* This is not the preferred interface unless you know you
* @cb: the callback to be called when the timer expires
* @opaque: the opaque pointer to be passed to the callback
*
- * Creeate a new timer and associate it with the default
+ * Create a new timer and associate it with the default
* timer list for the clock type @type.
*
+ * The default timer list has one special feature: in icount mode,
+ * %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is
+ * not true of other timer lists, which are typically associated
+ * with an AioContext---each of them runs its timer callbacks in its own
+ * AioContext thread.
+ *
* Returns: a pointer to the timer
*/
static inline QEMUTimer *timer_new(QEMUClockType type, int scale,
/**
* timer_new_ns:
- * @clock: the clock to associate with the timer
- * @callback: the callback to call when the timer expires
+ * @type: the clock type to associate with the timer
+ * @cb: the callback to call when the timer expires
* @opaque: the opaque pointer to pass to the callback
*
* Create a new timer with nanosecond scale on the default timer list
* associated with the clock.
*
+ * The default timer list has one special feature: in icount mode,
+ * %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is
+ * not true of other timer lists, which are typically associated
+ * with an AioContext---each of them runs its timer callbacks in its own
+ * AioContext thread.
+ *
* Returns: a pointer to the newly created timer
*/
static inline QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb,
/**
* timer_new_us:
- * @clock: the clock to associate with the timer
- * @callback: the callback to call when the timer expires
+ * @type: the clock type to associate with the timer
+ * @cb: the callback to call when the timer expires
* @opaque: the opaque pointer to pass to the callback
*
+ * The default timer list has one special feature: in icount mode,
+ * %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is
+ * not true of other timer lists, which are typically associated
+ * with an AioContext---each of them runs its timer callbacks in its own
+ * AioContext thread.
+ *
* Create a new timer with microsecond scale on the default timer list
* associated with the clock.
*
/**
* timer_new_ms:
- * @clock: the clock to associate with the timer
- * @callback: the callback to call when the timer expires
+ * @type: the clock type to associate with the timer
+ * @cb: the callback to call when the timer expires
* @opaque: the opaque pointer to pass to the callback
*
+ * The default timer list has one special feature: in icount mode,
+ * %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is
+ * not true of other timer lists, which are typically associated
+ * with an AioContext---each of them runs its timer callbacks in its own
+ * AioContext thread.
+ *
* Create a new timer with millisecond scale on the default timer list
* associated with the clock.
*
*
* Free a timer (it must not be on the active list)
*/
-void timer_free(QEMUTimer *ts);
+static inline void timer_free(QEMUTimer *ts)
+{
+ g_free(ts);
+}
/**
* timer_del:
/**
* timer_expired:
* @ts: the timer
+ * @current_time: the current time
*
* Determines whether a timer has expired.
*
*
* Initialise the clock & timer infrastructure
*/
-void init_clocks(void);
+void init_clocks(QEMUTimerListNotifyCB *notify_cb);
int64_t cpu_get_ticks(void);
/* Caller must hold BQL */
/* Caller must hold BQL */
void cpu_disable_ticks(void);
-static inline int64_t get_ticks_per_sec(void)
+static inline int64_t get_max_clock_jump(void)
{
- return 1000000000LL;
+ /* This should be small enough to prevent excessive interrupts from being
+ * generated by the RTC on clock jumps, but large enough to avoid frequent
+ * unnecessary resets in idle VMs.
+ */
+ return 60 * NANOSECONDS_PER_SECOND;
}
/*
* Low level clock functions
*/
-/* real time host monotonic timer */
+/* get host real time in nanosecond */
static inline int64_t get_clock_realtime(void)
{
struct timeval tv;
{
LARGE_INTEGER ti;
QueryPerformanceCounter(&ti);
- return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq);
+ return muldiv64(ti.QuadPart, NANOSECONDS_PER_SECOND, clock_freq);
}
#else
int64_t cpu_get_icount_raw(void);
int64_t cpu_get_icount(void);
int64_t cpu_get_clock(void);
-int64_t cpu_get_clock_offset(void);
int64_t cpu_icount_to_ns(int64_t icount);
+void cpu_update_icount(CPUState *cpu);
/*******************************************/
/* host CPU ticks (if available) */
#if defined(_ARCH_PPC)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int64_t retval;
#ifdef _ARCH_PPC64
#elif defined(__i386__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int64_t val;
asm volatile ("rdtsc" : "=A" (val));
#elif defined(__x86_64__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
uint32_t low,high;
int64_t val;
#elif defined(__hppa__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int val;
asm volatile ("mfctl %%cr16, %0" : "=r"(val));
#elif defined(__ia64)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int64_t val;
asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
#elif defined(__s390__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int64_t val;
asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
#elif defined(__sparc__)
-static inline int64_t cpu_get_real_ticks (void)
+static inline int64_t cpu_get_host_ticks (void)
{
#if defined(_LP64)
uint64_t rval;
: "=r" (value)); \
}
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
/* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
uint32_t count;
#elif defined(__alpha__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
uint64_t cc;
uint32_t cur, ofs;
/* The host CPU doesn't have an easily accessible cycle counter.
Just return a monotonically increasing value. This will be
totally wrong, but hopefully better than nothing. */
-static inline int64_t cpu_get_real_ticks (void)
+static inline int64_t cpu_get_host_ticks(void)
{
- static int64_t ticks = 0;
- return ticks++;
+ return get_clock();
}
#endif
#ifdef CONFIG_PROFILER
static inline int64_t profile_getclock(void)
{
- return cpu_get_real_ticks();
+ return get_clock();
}
-extern int64_t qemu_time, qemu_time_start;
-extern int64_t tlb_flush_time;
+extern int64_t tcg_time;
extern int64_t dev_time;
#endif