linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: george anzinger <george@mvista.com>
To: john stultz <johnstul@us.ibm.com>
Cc: Andrew Morton <akpm@digeo.com>,
	lkml <linux-kernel@vger.kernel.org>,
	James.Bottomley@SteelEye.com, shemminger@osdl.org, alex@ssi.bg
Subject: Re: [PATCH] linux-2.5.67_lost-tick-fix_A2
Date: Wed, 16 Apr 2003 16:03:02 -0700	[thread overview]
Message-ID: <3E9DE126.7040001@mvista.com> (raw)
In-Reply-To: <1050530545.1077.120.camel@w-jstultz2.beaverton.ibm.com>

john stultz wrote:
> Andrew, All,
> 
> 	This patch fixes a race in the timer_interrupt code caused by
> detect_lost_tick(). Since we're doing lost-tick compensation outside
> timer->mark_offset, time can pass between time-source reads which can
> cause gettimeofday inconsistencies. 
> 
> Additionally detect_lost_tick() was broken for the PIT case, since the
> whole point of detect_lost_tick() is to interpolate between two time
> sources to find inconsistencies. Additionally this could cause
> xtime_lock seq_lock reader starvation which has been causing machine
> hangs for SMP boxes that use the PIT as a time source.
> 
> This patch fixes the described race by removing detect_lost_tick() and
> instead implementing the lost tick detection code inside mark_offset().
> 
> Some of the divs and mods being added here might concern folks, but by
> not calling timer->get_offset() in detect_lost_tick() we eliminate much
> of the same math. I did some simple cycle counting and the new code
> comes out on average equivalent or faster. 

I think that if you look at the generated code you may find that there 
are NO div in the asm code.  The C folks know about scaling to avoid 
div especially when the divisor is a constant :)

-g
> 
> Please consider for inclusion.
> 
> thanks
> -john
> 
> 
> diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
> --- a/arch/i386/kernel/time.c	Wed Apr 16 14:53:59 2003
> +++ b/arch/i386/kernel/time.c	Wed Apr 16 14:53:59 2003
> @@ -279,41 +279,6 @@
>  }
>  
>  /*
> - * Lost tick detection and compensation
> - */
> -static inline void detect_lost_tick(void)
> -{
> -	/* read time since last interrupt */
> -	unsigned long delta = timer->get_offset();
> -	static unsigned long dbg_print;
> -	
> -	/* check if delta is greater then two ticks */
> -	if(delta >= 2*(1000000/HZ)){
> -
> -		/*
> -		 * only print debug info first 5 times
> -		 */
> -		/*
> -		 * AKPM: disable this for now; it's nice, but irritating.
> -		 */
> -		if (0 && dbg_print < 5) {
> -			printk(KERN_WARNING "\nWarning! Detected %lu "
> -				"micro-second gap between interrupts.\n",
> -				delta);
> -			printk(KERN_WARNING "  Compensating for %lu lost "
> -				"ticks.\n",
> -				delta/(1000000/HZ)-1);
> -			dump_stack();
> -			dbg_print++;
> -		}
> -		/* calculate number of missed ticks */
> -		delta = delta/(1000000/HZ)-1;
> -		jiffies += delta;
> -	}
> -		
> -}
> -
> -/*
>   * This is the same as the above, except we _also_ save the current
>   * Time Stamp Counter value at the time of the timer interrupt, so that
>   * we later on can estimate the time of day more exactly.
> @@ -329,7 +294,6 @@
>  	 */
>  	write_seqlock(&xtime_lock);
>  
> -	detect_lost_tick();
>  	timer->mark_offset();
>   
>  	do_timer_interrupt(irq, NULL, regs);
> diff -Nru a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c
> --- a/arch/i386/kernel/timers/timer_cyclone.c	Wed Apr 16 14:53:59 2003
> +++ b/arch/i386/kernel/timers/timer_cyclone.c	Wed Apr 16 14:53:59 2003
> @@ -18,6 +18,7 @@
>  #include <asm/fixmap.h>
>  
>  extern spinlock_t i8253_lock;
> +extern unsigned long jiffies;
>  extern unsigned long calibrate_tsc(void);
>  
>  /* Number of usecs that the last interrupt was delayed */
> @@ -46,6 +47,8 @@
>  
>  static void mark_offset_cyclone(void)
>  {
> +	unsigned long lost, delay;
> +	unsigned long delta = last_cyclone_low;
>  	int count;
>  	unsigned long long this_offset, last_offset;
>  
> @@ -62,6 +65,15 @@
>  	count |= inb(0x40) << 8;
>  	spin_unlock(&i8253_lock);
>  
> +	/* lost tick compensation */
> +	delta = last_cyclone_low - delta;	
> +	delta /=(CYCLONE_TIMER_FREQ/1000000);
> +	delta += delay_at_last_interrupt;
> +	lost = delta/(1000000/HZ);
> +	delay = delta%(1000000/HZ);
> +	if(lost >= 2)
> +		jiffies += lost-1;
> +	
>  	/* update the monotonic base value */
>  	this_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low;
>  	monotonic_base += (this_offset - last_offset) & CYCLONE_TIMER_MASK;
> @@ -70,6 +82,12 @@
>  	/* calculate delay_at_last_interrupt */
>  	count = ((LATCH-1) - count) * TICK_SIZE;
>  	delay_at_last_interrupt = (count + LATCH/2) / LATCH;
> +
> +	/* catch corner case where tick rollover 
> +	 * occured between cyclone and pit reads
> +	 */
> +	if(abs(delay - delay_at_last_interrupt) > 900)
> +		jiffies++;
>  }
>  
>  static unsigned long get_offset_cyclone(void)
> diff -Nru a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
> --- a/arch/i386/kernel/timers/timer_tsc.c	Wed Apr 16 14:53:59 2003
> +++ b/arch/i386/kernel/timers/timer_tsc.c	Wed Apr 16 14:53:59 2003
> @@ -18,6 +18,7 @@
>  int tsc_disable __initdata = 0;
>  
>  extern spinlock_t i8253_lock;
> +extern unsigned long jiffies;
>  
>  static int use_tsc;
>  /* Number of usecs that the last interrupt was delayed */
> @@ -112,6 +113,8 @@
>  
>  static void mark_offset_tsc(void)
>  {
> +	unsigned long lost,delay;
> +	unsigned long delta = last_tsc_low;
>  	int count;
>  	int countmp;
>  	static int count1=0, count2=LATCH;
> @@ -156,6 +159,23 @@
>  		}
>  	}
>  
> +	/* lost tick compensation */
> +	delta = last_tsc_low - delta;
> +	{
> +		register unsigned long eax, edx;
> +		eax = delta;
> +		__asm__("mull %2"
> +		:"=a" (eax), "=d" (edx)
> +		:"rm" (fast_gettimeoffset_quotient),
> +		 "0" (eax));
> +		delta = edx;
> +	}
> +	delta += delay_at_last_interrupt;
> +	lost = delta/(1000000/HZ);
> +	delay = delta%(1000000/HZ);
> +	if(lost >= 2)
> +		jiffies += lost-1;
> +
>  	/* update the monotonic base value */
>  	this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
>  	monotonic_base += cycles_2_ns(this_offset - last_offset);
> @@ -164,6 +184,12 @@
>  	/* calculate delay_at_last_interrupt */
>  	count = ((LATCH-1) - count) * TICK_SIZE;
>  	delay_at_last_interrupt = (count + LATCH/2) / LATCH;
> +
> +	/* catch corner case where tick rollover 
> +	 * occured between tsc and pit reads
> +	 */
> +	if(abs(delay - delay_at_last_interrupt) > 900)
> +		jiffies++;
>  }
>  
>  static void delay_tsc(unsigned long loops)
> 
> 
> 
> 
> 
> 

-- 
George Anzinger   george@mvista.com
High-res-timers:  http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml


  parent reply	other threads:[~2003-04-16 22:52 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-04-16 22:02 [PATCH] linux-2.5.67_lost-tick-fix_A2 john stultz
2003-04-16 22:32 ` Andrew Morton
2003-04-16 22:46   ` john stultz
2003-04-16 23:02     ` Andrew Morton
2003-04-16 23:03 ` george anzinger [this message]
2003-04-16 23:21   ` john stultz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3E9DE126.7040001@mvista.com \
    --to=george@mvista.com \
    --cc=James.Bottomley@SteelEye.com \
    --cc=akpm@digeo.com \
    --cc=alex@ssi.bg \
    --cc=johnstul@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=shemminger@osdl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).