[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Fix Linux so that it does not set a timeout if there are no pending
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |