aboutsummaryrefslogtreecommitdiff
path: root/cpus.c
diff options
context:
space:
mode:
authorAlex Bligh <alex@alex.org.uk>2013-08-21 16:02:57 +0100
committerStefan Hajnoczi <stefanha@redhat.com>2013-08-22 19:10:28 +0200
commitac70aafc28bec4d1014082f0c6659a368c5a95bd (patch)
tree44fe4dafc708c49787dd77901601fb006c720b31 /cpus.c
parenta3a726ae09cdf6d277ac88cd725cf50d5849db2c (diff)
aio / timers: Use all timerlists in icount warp calculations
Notify all timerlists derived from vm_clock in icount warp calculations. When calculating timer delay based on vm_clock deadline, use all timerlists. For compatibility, maintain an apparent bug where when using icount, if no vm_clock timer was set, qemu_clock_deadline would return INT32_MAX and always set an icount clock expiry about 2 seconds ahead. NB: thread safety - when different timerlists sit on different threads, this will need some locking. Signed-off-by: Alex Bligh <alex@alex.org.uk> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'cpus.c')
-rw-r--r--cpus.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/cpus.c b/cpus.c
index 70cc6171e2..254eb4c3e8 100644
--- a/cpus.c
+++ b/cpus.c
@@ -267,7 +267,7 @@ static void icount_warp_rt(void *opaque)
qemu_icount_bias += MIN(warp_delta, delta);
}
if (qemu_clock_expired(vm_clock)) {
- qemu_notify_event();
+ qemu_clock_notify(vm_clock);
}
}
vm_clock_warp_start = -1;
@@ -278,13 +278,13 @@ void qtest_clock_warp(int64_t dest)
int64_t clock = qemu_get_clock_ns(vm_clock);
assert(qtest_enabled());
while (clock < dest) {
- int64_t deadline = qemu_clock_deadline(vm_clock);
+ int64_t deadline = qemu_clock_deadline_ns_all(vm_clock);
int64_t warp = MIN(dest - clock, deadline);
qemu_icount_bias += warp;
qemu_run_timers(vm_clock);
clock = qemu_get_clock_ns(vm_clock);
}
- qemu_notify_event();
+ qemu_clock_notify(vm_clock);
}
void qemu_clock_warp(QEMUClock *clock)
@@ -319,7 +319,18 @@ void qemu_clock_warp(QEMUClock *clock)
}
vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
- deadline = qemu_clock_deadline(vm_clock);
+ /* We want to use the earliest deadline from ALL vm_clocks */
+ deadline = qemu_clock_deadline_ns_all(vm_clock);
+
+ /* Maintain prior (possibly buggy) behaviour where if no deadline
+ * was set (as there is no vm_clock timer) or it is more than
+ * INT32_MAX nanoseconds ahead, we still use INT32_MAX
+ * nanoseconds.
+ */
+ if ((deadline < 0) || (deadline > INT32_MAX)) {
+ deadline = INT32_MAX;
+ }
+
if (deadline > 0) {
/*
* Ensure the vm_clock proceeds even when the virtual CPU goes to
@@ -338,8 +349,8 @@ void qemu_clock_warp(QEMUClock *clock)
* packets continuously instead of every 100ms.
*/
qemu_mod_timer(icount_warp_timer, vm_clock_warp_start + deadline);
- } else {
- qemu_notify_event();
+ } else if (deadline == 0) {
+ qemu_clock_notify(vm_clock);
}
}
@@ -866,8 +877,13 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
while (1) {
tcg_exec_all();
- if (use_icount && qemu_clock_deadline(vm_clock) <= 0) {
- qemu_notify_event();
+
+ if (use_icount) {
+ int64_t deadline = qemu_clock_deadline_ns_all(vm_clock);
+
+ if (deadline == 0) {
+ qemu_clock_notify(vm_clock);
+ }
}
qemu_tcg_wait_io_event();
}
@@ -1145,11 +1161,23 @@ static int tcg_cpu_exec(CPUArchState *env)
#endif
if (use_icount) {
int64_t count;
+ int64_t deadline;
int decr;
qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
env->icount_decr.u16.low = 0;
env->icount_extra = 0;
- count = qemu_icount_round(qemu_clock_deadline(vm_clock));
+ deadline = qemu_clock_deadline_ns_all(vm_clock);
+
+ /* Maintain prior (possibly buggy) behaviour where if no deadline
+ * was set (as there is no vm_clock timer) or it is more than
+ * INT32_MAX nanoseconds ahead, we still use INT32_MAX
+ * nanoseconds.
+ */
+ if ((deadline < 0) || (deadline > INT32_MAX)) {
+ deadline = INT32_MAX;
+ }
+
+ count = qemu_icount_round(deadline);
qemu_icount += count;
decr = (count > 0xffff) ? 0xffff : count;
count -= decr;