[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 35/62] icount: implement a new icount_sleep mode togg
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 35/62] icount: implement a new icount_sleep mode toggleing real-time cpu sleep |
Date: |
Fri, 5 Jun 2015 17:15:36 +0200 |
From: Victor CLEMENT <address@hidden>
When the icount_sleep mode is disabled, the QEMU_VIRTUAL_CLOCK runs at the
maximum possible speed by warping the sleep times of the virtual cpu to the
soonest clock deadline. The virtual clock will be updated only according
the instruction counter.
Signed-off-by: Victor CLEMENT <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
cpus.c | 70 +++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 44 insertions(+), 26 deletions(-)
diff --git a/cpus.c b/cpus.c
index de6469f..688eb73 100644
--- a/cpus.c
+++ b/cpus.c
@@ -105,6 +105,7 @@ static bool all_cpu_threads_idle(void)
/* Protected by TimersState seqlock */
+static bool icount_sleep = true;
static int64_t vm_clock_warp_start = -1;
/* Conversion factor from emulated instructions to virtual clock ticks. */
static int icount_time_shift;
@@ -393,15 +394,18 @@ void qemu_clock_warp(QEMUClockType type)
return;
}
- /*
- * If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer now.
- * This ensures that the deadline for the timer is computed correctly
below.
- * This also makes sure that the insn counter is synchronized before the
- * CPU starts running, in case the CPU is woken by an event other than
- * the earliest QEMU_CLOCK_VIRTUAL timer.
- */
- icount_warp_rt(NULL);
- timer_del(icount_warp_timer);
+ if (icount_sleep) {
+ /*
+ * If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer
now.
+ * This ensures that the deadline for the timer is computed correctly
+ * below.
+ * This also makes sure that the insn counter is synchronized before
+ * the CPU starts running, in case the CPU is woken by an event other
+ * than the earliest QEMU_CLOCK_VIRTUAL timer.
+ */
+ icount_warp_rt(NULL);
+ timer_del(icount_warp_timer);
+ }
if (!all_cpu_threads_idle()) {
return;
}
@@ -425,23 +429,35 @@ void qemu_clock_warp(QEMUClockType type)
* interrupt to wake it up, but the interrupt never comes because
* the vCPU isn't running any insns and thus doesn't advance the
* QEMU_CLOCK_VIRTUAL.
- *
- * An extreme solution for this problem would be to never let VCPUs
- * sleep in icount mode if there is a pending QEMU_CLOCK_VIRTUAL
- * timer; rather time could just advance to the next QEMU_CLOCK_VIRTUAL
- * event. Instead, we do stop VCPUs and only advance
QEMU_CLOCK_VIRTUAL
- * after some "real" time, (related to the time left until the next
- * event) has passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this.
- * This avoids that the warps are visible externally; for example,
- * you will not be sending network packets continuously instead of
- * every 100ms.
*/
- seqlock_write_lock(&timers_state.vm_clock_seqlock);
- if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
- vm_clock_warp_start = clock;
+ if (!icount_sleep) {
+ /*
+ * We never let VCPUs sleep in no sleep icount mode.
+ * If there is a pending QEMU_CLOCK_VIRTUAL timer we just advance
+ * to the next QEMU_CLOCK_VIRTUAL event and notify it.
+ * It is useful when we want a deterministic execution time,
+ * isolated from host latencies.
+ */
+ seqlock_write_lock(&timers_state.vm_clock_seqlock);
+ timers_state.qemu_icount_bias += deadline;
+ seqlock_write_unlock(&timers_state.vm_clock_seqlock);
+ qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
+ } else {
+ /*
+ * We do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL after some
+ * "real" time, (related to the time left until the next event) has
+ * passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this.
+ * This avoids that the warps are visible externally; for example,
+ * you will not be sending network packets continuously instead of
+ * every 100ms.
+ */
+ seqlock_write_lock(&timers_state.vm_clock_seqlock);
+ if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
+ vm_clock_warp_start = clock;
+ }
+ seqlock_write_unlock(&timers_state.vm_clock_seqlock);
+ timer_mod_anticipate(icount_warp_timer, clock + deadline);
}
- seqlock_write_unlock(&timers_state.vm_clock_seqlock);
- timer_mod_anticipate(icount_warp_timer, clock + deadline);
} else if (deadline == 0) {
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
}
@@ -504,9 +520,11 @@ void configure_icount(QemuOpts *opts, Error **errp)
}
return;
}
+ if (icount_sleep) {
+ icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
+ icount_warp_rt, NULL);
+ }
icount_align_option = qemu_opt_get_bool(opts, "align", false);
- icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
- icount_warp_rt, NULL);
if (strcmp(option, "auto") != 0) {
errno = 0;
icount_time_shift = strtol(option, &rem_str, 0);
--
2.4.1
- [Qemu-devel] [PULL 25/62] exec: invert return value of cpu_physical_memory_get_clean, rename, (continued)
- [Qemu-devel] [PULL 25/62] exec: invert return value of cpu_physical_memory_get_clean, rename, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 26/62] exec: only check relevant bitmaps for cleanliness, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 27/62] memory: do not touch code dirty bitmap unless TCG is enabled, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 28/62] bitmap: add atomic set functions, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 29/62] bitmap: add atomic test and clear, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 30/62] memory: use atomic ops for setting dirty memory bits, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 31/62] migration: move dirty bitmap sync to ram_addr.h, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 33/62] memory: make cpu_physical_memory_sync_dirty_bitmap() fully atomic, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 32/62] memory: replace cpu_physical_memory_reset_dirty() with test-and-clear, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 34/62] memory: use mr->ram_addr in "is this RAM?" assertions, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 35/62] icount: implement a new icount_sleep mode toggleing real-time cpu sleep,
Paolo Bonzini <=
- [Qemu-devel] [PULL 36/62] icount: add sleep parameter to the icount option to set icount_sleep mode, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 37/62] icount: print a warning if there is no more deadline in sleep=no mode, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 38/62] target-i386: introduce cpu_get_mem_attrs, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 40/62] target-i386: Use correct memory attributes for ioport accesses, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 41/62] target-i386: mask NMIs on entry to SMM, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 42/62] target-i386: set G=1 in SMM big real mode selectors, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 43/62] target-i386: wake up processors that receive an SMI, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 44/62] pflash_cfi01: change big-endian property to BIT type, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 45/62] pflash_cfi01: change to new-style MMIO accessors, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 39/62] target-i386: Use correct memory attributes for memory accesses, Paolo Bonzini, 2015/06/05