[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC] [PATCHv9 19/31] aio / timers: Use all timerlists in i
From: |
Alex Bligh |
Subject: |
[Qemu-devel] [RFC] [PATCHv9 19/31] aio / timers: Use all timerlists in icount warp calculations |
Date: |
Sat, 10 Aug 2013 11:06:23 +0100 |
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 <address@hidden>
---
cpus.c | 46 +++++++++++++++++++++++++++++++++++++---------
include/qemu/timer.h | 13 +++++++++++++
qemu-timer.c | 16 ++++++++++++++++
qtest.c | 2 +-
4 files changed, 67 insertions(+), 10 deletions(-)
diff --git a/cpus.c b/cpus.c
index 0f65e76..673d506 100644
--- a/cpus.c
+++ b/cpus.c
@@ -262,7 +262,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;
@@ -273,13 +273,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)
@@ -314,7 +314,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
@@ -333,8 +344,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;
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 3662cf2..c1fbfb9 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -98,6 +98,7 @@ int64_t qemu_clock_deadline(QEMUClock *clock);
* @clock: the clock to operate on
*
* Calculate the timeout of the earliest expiring timer
+ * on the default timer list associated with the clock
* in nanoseconds, or -1 if no timer is set to expire.
*
* Returns: time until expiry in nanoseconds or -1
@@ -121,6 +122,18 @@ int64_t qemu_clock_deadline_ns(QEMUClock *clock);
bool qemu_clock_use_for_deadline(QEMUClock *clock);
/**
+ * qemu_clock_use_for_deadline:
+ * @clock: the clock to operate on
+ *
+ * Calculate the deadline across all timer lists associated
+ * with a clock (as opposed to just the default one)
+ * in nanoseconds, or -1 if no timer is set to expire.
+ *
+ * Returns: time until expiry in nanoseconds or -1
+ */
+int64_t qemu_clock_deadline_ns_all(QEMUClock *clock);
+
+/**
* qemu_clock_get_main_loop_timerlist:
* @clock: the clock to operate on
*
diff --git a/qemu-timer.c b/qemu-timer.c
index ceaee64..c27218e 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -392,6 +392,22 @@ int64_t qemu_clock_deadline_ns(QEMUClock *clock)
return timerlist_deadline_ns(clock->main_loop_timerlist);
}
+/* Calculate the soonest deadline across all timerlists attached
+ * to the clock. This is used for the icount timeout so we
+ * ignore whether or not the clock should be used in deadline
+ * calculations.
+ */
+int64_t qemu_clock_deadline_ns_all(QEMUClock *clock)
+{
+ int64_t deadline = -1;
+ QEMUTimerList *timer_list;
+ QLIST_FOREACH(timer_list, &clock->timerlists, list) {
+ deadline = qemu_soonest_timeout(deadline,
+ timerlist_deadline_ns(timer_list));
+ }
+ return deadline;
+}
+
QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list)
{
return timer_list->clock;
diff --git a/qtest.c b/qtest.c
index 74f1842..c038e24 100644
--- a/qtest.c
+++ b/qtest.c
@@ -412,7 +412,7 @@ static void qtest_process_command(CharDriverState *chr,
gchar **words)
if (words[1]) {
ns = strtoll(words[1], NULL, 0);
} else {
- ns = qemu_clock_deadline(vm_clock);
+ ns = qemu_clock_deadline_ns_all(vm_clock);
}
qtest_clock_warp(qemu_get_clock_ns(vm_clock) + ns);
qtest_send_prefix(chr);
--
1.7.9.5
- [Qemu-devel] [RFC] [PATCHv9 11/31] aio / timers: Add QEMUTimerListGroup to AioContext, (continued)
- [Qemu-devel] [RFC] [PATCHv9 11/31] aio / timers: Add QEMUTimerListGroup to AioContext, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 10/31] aio / timers: Add QEMUTimerListGroup and helper functions, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 14/31] aio / timers: Add aio_timer_init & aio_timer_new wrappers, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 12/31] aio / timers: Add a notify callback to QEMUTimerList, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 15/31] aio / timers: Convert aio_poll to use AioContext timers' deadline, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 16/31] aio / timers: Convert mainloop to use timeout, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 17/31] aio / timers: On timer modification, qemu_notify or aio_notify, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 09/31] aio / timers: Untangle include files, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 18/31] aio / timers: Introduce new API timer_new and friends, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 22/31] aio / timers: Remove legacy qemu_clock_deadline & qemu_timerlist_deadline, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 19/31] aio / timers: Use all timerlists in icount warp calculations,
Alex Bligh <=
- [Qemu-devel] [RFC] [PATCHv9 20/31] aio / timers: Add documentation and new format calls, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 23/31] aio / timers: Add qemu_clock_get_ms and qemu_clock_get_ms, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 08/31] aio / timers: Split QEMUClock into QEMUClock and QEMUTimerList, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 25/31] aio / timers: Remove main_loop_timerlist, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 27/31] aio / timers: convert block_job_sleep_ns and co_sleep_ns to new API, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 21/31] aio / timers: Remove alarm timers, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 29/31] aio / timers: Add scripts/switch-timer-api, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 28/31] aio / timers: Add test harness for AioContext timers, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 31/31] aio / timers: Remove legacy interface, Alex Bligh, 2013/08/10
- [Qemu-devel] [RFC] [PATCHv9 26/31] aio / timers: Convert rtc_clock to be a QEMUClockType, Alex Bligh, 2013/08/10