aboutsummaryrefslogtreecommitdiff
path: root/cpus.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2011-04-13 10:03:44 +0200
committerEdgar E. Iglesias <edgar.iglesias@gmail.com>2011-04-15 09:27:56 +0200
commitab33fcda9f96b9195dfb3fcf5bd9bb5383caeaea (patch)
tree97a1a32a03b69a15fb4f23f7a5eb5e880d036980 /cpus.c
parent3b2319a30b5ae528787bf3769b1a28a863b53252 (diff)
downloadqemu-ab33fcda9f96b9195dfb3fcf5bd9bb5383caeaea.zip
qemu-ab33fcda9f96b9195dfb3fcf5bd9bb5383caeaea.tar.gz
qemu-ab33fcda9f96b9195dfb3fcf5bd9bb5383caeaea.tar.bz2
enable vm_clock to "warp" in the iothread+icount case
The previous patch however is not enough, because if the virtual CPU goes to sleep waiting for a future timer interrupt to wake it up, qemu deadlocks. The timer interrupt never comes because time is driven by icount, but the vCPU doesn't run any insns. You could say that VCPUs should never go to sleep in icount mode if there is a pending vm_clock timer; rather time should just warp to the next vm_clock event with no sleep ever taking place. Even better, you can sleep for some time related to the time left until the next event, to avoid that the warps are too visible externally; for example, you could be sending network packets continously instead of every 100ms. This is what this patch implements. qemu_clock_warp is called: 1) whenever a vm_clock timer is adjusted, to ensure the warp_timer is synchronized; 2) at strategic points in the CPU thread, to make sure the insn counter is synchronized before the CPU starts running. In any case, the warp_timer is disabled while the CPU is running, because the insn counter will then be making progress on its own. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Tested-by: Edgar E. Iglesias <edgar.iglesias@gmail.com> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Diffstat (limited to 'cpus.c')
-rw-r--r--cpus.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/cpus.c b/cpus.c
index cbeac7a..6a50199 100644
--- a/cpus.c
+++ b/cpus.c
@@ -155,7 +155,7 @@ static bool cpu_thread_is_idle(CPUState *env)
return true;
}
-static bool all_cpu_threads_idle(void)
+bool all_cpu_threads_idle(void)
{
CPUState *env;
@@ -739,6 +739,9 @@ static void qemu_tcg_wait_io_event(void)
CPUState *env;
while (all_cpu_threads_idle()) {
+ /* Start accounting real time to the virtual clock if the CPUs
+ are idle. */
+ qemu_clock_warp(vm_clock);
qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
}
@@ -1073,6 +1076,9 @@ bool cpu_exec_all(void)
{
int r;
+ /* Account partial waits to the vm_clock. */
+ qemu_clock_warp(vm_clock);
+
if (next_cpu == NULL) {
next_cpu = first_cpu;
}