From: Alexander Atanasov and John Stultz Spin lock debugging got this on UP+preempt: arch/i386/kernel/i8259.c:176:spin_lock(arch/i386/kernel/i8259.c:c03d4838) already locked by include/asm-i386/mach-default/do_timer.h/50 include/asm-i386/mach-default/do_timer.h:56: spin_unlock(arch/i386/kernel/i8259.c:c03d4838) not locked arch/i386/kernel/i8259.c:176:spin_lock(arch/i386/kernel/i8259.c:c03d4838) already locked by include/asm-i386/mach-default/do_timer.h/50 include/asm-i386/mach-default/do_timer.h:56: spin_unlock(arch/i386/kernel/i8259.c:c03d4838) not locked This is due to do_timer_overflow expecting to be called with IRQs disabled, the whole path used to do that until converted to xtime_lock, but do_timer_overflow seems to be missed. Patch changes get_offset_pit to hold i8253_lock while calling do_timer_overflow. John made some changes and then stress-tested it on 8-way. arch/i386/kernel/timers/timer_pit.c | 25 +++++++++++++------------ 1 files changed, 13 insertions(+), 12 deletions(-) diff -puN arch/i386/kernel/timers/timer_pit.c~do_timer_overflow-locking-fix arch/i386/kernel/timers/timer_pit.c --- 25/arch/i386/kernel/timers/timer_pit.c~do_timer_overflow-locking-fix 2003-04-17 19:31:48.000000000 -0700 +++ 25-akpm/arch/i386/kernel/timers/timer_pit.c 2003-04-17 19:33:20.000000000 -0700 @@ -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; @@ -110,15 +110,15 @@ static unsigned long get_offset_pit(void jiffies_t = jiffies; count |= inb_p(PIT_CH0) << 8; - - /* VIA686a test code... reset the latch if count > max + 1 */ - if (count > LATCH) { - outb_p(0x34, PIT_MODE); - outb_p(LATCH & 0xff, PIT_CH0); - outb(LATCH >> 8, PIT_CH0); - count = LATCH - 1; - } - + + /* VIA686a test code... reset the latch if count > max + 1 */ + if (count > LATCH) { + outb_p(0x34, PIT_MODE); + outb_p(LATCH & 0xff, PIT_CH0); + outb(LATCH >> 8, PIT_CH0); + count = LATCH - 1; + } + spin_unlock_irqrestore(&i8253_lock, flags); /* @@ -130,7 +130,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 */ @@ -139,6 +138,8 @@ static unsigned long get_offset_pit(void } else jiffies_p = jiffies_t; + spin_unlock_irqrestore(&i8253_lock, flags); + count_p = count; count = ((LATCH-1) - count) * TICK_SIZE; _