From: john stultz , Alexander Atanasov We want to make sure we update jiffies_p and count_p atomically. So I'm inserting the spin_unlock_irqrestore() after we update count_p, rather then just before. 25-akpm/arch/i386/kernel/timers/timer_pit.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diff -puN arch/i386/kernel/timers/timer_pit.c~timer-pit-race-fix arch/i386/kernel/timers/timer_pit.c --- 25/arch/i386/kernel/timers/timer_pit.c~timer-pit-race-fix Fri Apr 18 16:31:07 2003 +++ 25-akpm/arch/i386/kernel/timers/timer_pit.c Fri Apr 18 16:31:07 2003 @@ -54,7 +54,7 @@ static void delay_pit(unsigned long loop } -/* This function must be called with interrupts disabled +/* This function must be called with xtime_lock held. * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs * * However, the pc-audio speaker driver changes the divisor so that @@ -93,7 +93,7 @@ static unsigned long get_offset_pit(void static unsigned long jiffies_p = 0; /* - * cache volatile jiffies temporarily; we have IRQs turned off. + * cache volatile jiffies temporarily; we have xtime_lock. */ unsigned long jiffies_t; @@ -119,8 +119,6 @@ static unsigned long get_offset_pit(void count = LATCH - 1; } - spin_unlock_irqrestore(&i8253_lock, flags); - /* * avoiding timer inconsistencies (they are rare, but they happen)... * there are two kinds of problems that must be avoided here: @@ -130,7 +128,6 @@ static unsigned long get_offset_pit(void * (see c't 95/10 page 335 for Neptun bug.) */ - if( jiffies_t == jiffies_p ) { if( count > count_p ) { /* the nutcase */ @@ -141,6 +138,8 @@ static unsigned long get_offset_pit(void count_p = count; + spin_unlock_irqrestore(&i8253_lock, flags); + count = ((LATCH-1) - count) * TICK_SIZE; count = (count + LATCH/2) / LATCH; _