ia64/xen-unstable

changeset 10794:79f4c91c5628

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@xensource.com>
author kfraser@localhost.localdomain
date Tue Jul 25 17:01:49 2006 +0100 (2006-07-25)
parents b066b4612286
children 37f206c7405a
files linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c xen/common/schedule.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Tue Jul 25 16:11:12 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Tue Jul 25 17:01:49 2006 +0100
     1.3 @@ -958,11 +958,17 @@ u64 jiffies_to_st(unsigned long j)
     1.4  	do {
     1.5  		seq = read_seqbegin(&xtime_lock);
     1.6  		delta = j - jiffies;
     1.7 -		/* NB. The next check can trigger in some wrap-around cases,
     1.8 -		 * but that's ok: we'll just end up with a shorter timeout. */
     1.9 -		if (delta < 1)
    1.10 -			delta = 1;
    1.11 -		st = processed_system_time + (delta * (u64)NS_PER_TICK);
    1.12 +		if (delta < 1) {
    1.13 +			/* Triggers in some wrap-around cases, but that's okay:
    1.14 +			 * we just end up with a shorter timeout. */
    1.15 +			st = processed_system_time + NS_PER_TICK;
    1.16 +		} else if (((unsigned long)delta >> (BITS_PER_LONG-3)) != 0) {
    1.17 +			/* Very long timeout means there is no pending timer.
    1.18 +			 * We indicate this to Xen by passing zero timeout. */
    1.19 +			st = 0;
    1.20 +		} else {
    1.21 +			st = processed_system_time + delta * (u64)NS_PER_TICK;
    1.22 +		}
    1.23  	} while (read_seqretry(&xtime_lock, seq));
    1.24  
    1.25  	return st;
    1.26 @@ -989,14 +995,15 @@ static void stop_hz_timer(void)
    1.27  
    1.28  	smp_mb();
    1.29  
    1.30 -	/* Leave ourselves in 'tick mode' if rcu or softirq or timer pending. */
    1.31 +	/* Leave ourselves in tick mode if rcu or softirq or timer pending. */
    1.32  	if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
    1.33  	    (j = next_timer_interrupt(), time_before_eq(j, jiffies))) {
    1.34  		cpu_clear(cpu, nohz_cpu_mask);
    1.35  		j = jiffies + 1;
    1.36  	}
    1.37  
    1.38 -	BUG_ON(HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0);
    1.39 +	if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0)
    1.40 +		BUG();
    1.41  }
    1.42  
    1.43  static void start_hz_timer(void)
     2.1 --- a/xen/common/schedule.c	Tue Jul 25 16:11:12 2006 +0100
     2.2 +++ b/xen/common/schedule.c	Tue Jul 25 17:01:49 2006 +0100
     2.3 @@ -404,12 +404,15 @@ long do_set_timer_op(s_time_t timeout)
     2.4           * for timeouts wrapped negative, and for positive timeouts more than 
     2.5           * about 13 days in the future (2^50ns). The correct fix is to trigger 
     2.6           * an interrupt immediately (since Linux in fact has pending work to 
     2.7 -         * do in this situation).
     2.8 +         * do in this situation). However, older guests also set a long timeout
     2.9 +         * when they have *no* pending timers at all: setting an immediate
    2.10 +         * timeout in this case can burn a lot of CPU. We therefore go for a
    2.11 +         * reasonable middleground of triggering a timer event in 100ms.
    2.12           */
    2.13          DPRINTK("Warning: huge timeout set by domain %d (vcpu %d):"
    2.14                  " %"PRIx64"\n",
    2.15                  v->domain->domain_id, v->vcpu_id, (uint64_t)timeout);
    2.16 -        send_timer_event(v);
    2.17 +        set_timer(&v->timer, NOW() + MILLISECS(100));
    2.18      }
    2.19      else
    2.20      {