# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 79f4c91c562864d27a31515d0f7a79d77b2b12a5
# Parent b066b46122860c927d319d53df7e68d6432c2711
Fix Linux so that it does not set a timeout if there are no pending
timers. Fix Xen so that it does not immediately fire a timer event if
it sees a very long timeout -- sometimes this means that there are
no pending timers.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 21 ++++++++++++++-------
xen/common/schedule.c | 7 +++++--
2 files changed, 19 insertions(+), 9 deletions(-)
diff -r b066b4612286 -r 79f4c91c5628
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Tue Jul 25 16:11:12
2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Tue Jul 25 17:01:49
2006 +0100
@@ -958,11 +958,17 @@ u64 jiffies_to_st(unsigned long j)
do {
seq = read_seqbegin(&xtime_lock);
delta = j - jiffies;
- /* NB. The next check can trigger in some wrap-around cases,
- * but that's ok: we'll just end up with a shorter timeout. */
- if (delta < 1)
- delta = 1;
- st = processed_system_time + (delta * (u64)NS_PER_TICK);
+ if (delta < 1) {
+ /* Triggers in some wrap-around cases, but that's okay:
+ * we just end up with a shorter timeout. */
+ st = processed_system_time + NS_PER_TICK;
+ } else if (((unsigned long)delta >> (BITS_PER_LONG-3)) != 0) {
+ /* Very long timeout means there is no pending timer.
+ * We indicate this to Xen by passing zero timeout. */
+ st = 0;
+ } else {
+ st = processed_system_time + delta * (u64)NS_PER_TICK;
+ }
} while (read_seqretry(&xtime_lock, seq));
return st;
@@ -989,14 +995,15 @@ static void stop_hz_timer(void)
smp_mb();
- /* Leave ourselves in 'tick mode' if rcu or softirq or timer pending. */
+ /* Leave ourselves in tick mode if rcu or softirq or timer pending. */
if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
(j = next_timer_interrupt(), time_before_eq(j, jiffies))) {
cpu_clear(cpu, nohz_cpu_mask);
j = jiffies + 1;
}
- BUG_ON(HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0);
+ if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0)
+ BUG();
}
static void start_hz_timer(void)
diff -r b066b4612286 -r 79f4c91c5628 xen/common/schedule.c
--- a/xen/common/schedule.c Tue Jul 25 16:11:12 2006 +0100
+++ b/xen/common/schedule.c Tue Jul 25 17:01:49 2006 +0100
@@ -404,12 +404,15 @@ long do_set_timer_op(s_time_t timeout)
* for timeouts wrapped negative, and for positive timeouts more than
* about 13 days in the future (2^50ns). The correct fix is to trigger
* an interrupt immediately (since Linux in fact has pending work to
- * do in this situation).
+ * do in this situation). However, older guests also set a long timeout
+ * when they have *no* pending timers at all: setting an immediate
+ * timeout in this case can burn a lot of CPU. We therefore go for a
+ * reasonable middleground of triggering a timer event in 100ms.
*/
DPRINTK("Warning: huge timeout set by domain %d (vcpu %d):"
" %"PRIx64"\n",
v->domain->domain_id, v->vcpu_id, (uint64_t)timeout);
- send_timer_event(v);
+ set_timer(&v->timer, NOW() + MILLISECS(100));
}
else
{
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|