2.6.18 have watchdog thread woken by timer interrupt, instead of hooking on timer wheel like 2.6.16. In this case, we need change next_timer_interrupt to consider watchdog event in case idle process decides to block a long time. This can effectively fix the softlockup warning seen intermittently. Signed-off-by Kevin Tian diff -r b3cca2636741 -r 99d1480afae8 linux-2.6-xen-sparse/include/linux/sched.h --- a/linux-2.6-xen-sparse/include/linux/sched.h Fri Feb 02 15:32:45 2007 +0800 +++ b/linux-2.6-xen-sparse/include/linux/sched.h Fri Feb 02 21:08:49 2007 +0800 @@ -211,10 +211,15 @@ extern void scheduler_tick(void); extern void scheduler_tick(void); #ifdef CONFIG_DETECT_SOFTLOCKUP +extern unsigned long softlockup_get_next_event(unsigned long expire); extern void softlockup_tick(void); extern void spawn_softlockup_task(void); extern void touch_softlockup_watchdog(void); #else +static inline unsigned long softlockup_get_next_event(unsigned long expire) +{ + return expire; +} static inline void softlockup_tick(void) { } diff -r b3cca2636741 -r 99d1480afae8 linux-2.6-xen-sparse/kernel/softlockup.c --- a/linux-2.6-xen-sparse/kernel/softlockup.c Fri Feb 02 15:32:45 2007 +0800 +++ b/linux-2.6-xen-sparse/kernel/softlockup.c Fri Feb 02 21:08:49 2007 +0800 @@ -40,6 +40,19 @@ void touch_softlockup_watchdog(void) } EXPORT_SYMBOL(touch_softlockup_watchdog); +unsigned long softlockup_get_next_event(unsigned long expire) +{ + if (time_before(expire, jiffies + HZ) || + did_panic || + !per_cpu(watchdog_task, smp_processor_id())) + return expire; + + /* Limit expire duration to maximum 1s, to allow watchdog + * thread waken up appropriately by timer interrupt. + */ + return jiffies + HZ; +} + /* * This callback runs from the timer interrupt, and checks * whether the watchdog thread has hung or not: diff -r b3cca2636741 -r 99d1480afae8 linux-2.6-xen-sparse/kernel/timer.c --- a/linux-2.6-xen-sparse/kernel/timer.c Fri Feb 02 15:32:45 2007 +0800 +++ b/linux-2.6-xen-sparse/kernel/timer.c Fri Feb 02 21:08:49 2007 +0800 @@ -482,8 +482,10 @@ unsigned long next_timer_interrupt(void) struct timespec tsdelta; tsdelta = ktime_to_timespec(hr_delta); hr_expires = timespec_to_jiffies(&tsdelta); - if (hr_expires < 3) - return hr_expires + jiffies; + if (hr_expires < 3) { + expires = hr_expires + jiffies; + goto done; + } } hr_expires += jiffies; @@ -555,9 +557,11 @@ found: return jiffies; if (time_before(hr_expires, expires)) - return hr_expires; - - return expires; + expires = hr_expires; + +done: + /* Assure watchdog thread not blocked by tick-less model */ + return softlockup_get_next_event(expires); } #endif