diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-02-07 02:16:56 +0000 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-02-07 02:16:56 +0000 |
commit | a38c7c1575e655ccdee168a265058a41ae13b548 (patch) | |
tree | d63845610942d76e677e4d2a6968263dc5e26c9c /patches | |
parent | 326d80a41220644cbaa82b25058437dff32c4e44 (diff) | |
download | xen-a38c7c1575e655ccdee168a265058a41ae13b548.tar.gz xen-a38c7c1575e655ccdee168a265058a41ae13b548.tar.bz2 xen-a38c7c1575e655ccdee168a265058a41ae13b548.zip |
linux: Fix softlockup interaction with noidlehz.
next_timer_interrupt() must check for when timer ISR is due to wake up
the softlockup thread.
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'patches')
-rw-r--r-- | patches/linux-2.6.18/series | 1 | ||||
-rw-r--r-- | patches/linux-2.6.18/softlockup-no-idle-hz.patch | 56 |
2 files changed, 57 insertions, 0 deletions
diff --git a/patches/linux-2.6.18/series b/patches/linux-2.6.18/series index 62b3e0e0d7..85bbae63e4 100644 --- a/patches/linux-2.6.18/series +++ b/patches/linux-2.6.18/series @@ -18,3 +18,4 @@ git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch x86-elfnote-as-preprocessor-macro.patch fixaddr-top.patch git-c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4.patch +softlockup-no-idle-hz.patch diff --git a/patches/linux-2.6.18/softlockup-no-idle-hz.patch b/patches/linux-2.6.18/softlockup-no-idle-hz.patch new file mode 100644 index 0000000000..6799bfc4bf --- /dev/null +++ b/patches/linux-2.6.18/softlockup-no-idle-hz.patch @@ -0,0 +1,56 @@ +diff -pruN ../orig-linux-2.6.18/include/linux/sched.h ./include/linux/sched.h +--- ../orig-linux-2.6.18/include/linux/sched.h 2006-09-20 04:42:06.000000000 +0100 ++++ ./include/linux/sched.h 2007-02-07 01:10:24.000000000 +0000 +@@ -211,10 +211,15 @@ extern void update_process_times(int use + extern void scheduler_tick(void); + + #ifdef CONFIG_DETECT_SOFTLOCKUP ++extern unsigned long softlockup_get_next_event(void); + 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(void) ++{ ++ return MAX_JIFFY_OFFSET; ++} + static inline void softlockup_tick(void) + { + } +diff -pruN ../orig-linux-2.6.18/kernel/softlockup.c ./kernel/softlockup.c +--- ../orig-linux-2.6.18/kernel/softlockup.c 2006-09-20 04:42:06.000000000 +0100 ++++ ./kernel/softlockup.c 2007-02-07 01:53:22.000000000 +0000 +@@ -40,6 +40,19 @@ void touch_softlockup_watchdog(void) + } + EXPORT_SYMBOL(touch_softlockup_watchdog); + ++unsigned long softlockup_get_next_event(void) ++{ ++ int this_cpu = smp_processor_id(); ++ unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu); ++ ++ if (per_cpu(print_timestamp, this_cpu) == touch_timestamp || ++ did_panic || ++ !per_cpu(watchdog_task, this_cpu)) ++ return MAX_JIFFY_OFFSET; ++ ++ return min_t(long, 0, touch_timestamp + HZ - jiffies); ++} ++ + /* + * This callback runs from the timer interrupt, and checks + * whether the watchdog thread has hung or not: +diff -pruN ../orig-linux-2.6.18/kernel/timer.c ./kernel/timer.c +--- ../orig-linux-2.6.18/kernel/timer.c 2006-09-20 04:42:06.000000000 +0100 ++++ ./kernel/timer.c 2007-02-07 01:29:34.000000000 +0000 +@@ -485,7 +485,9 @@ unsigned long next_timer_interrupt(void) + if (hr_expires < 3) + return hr_expires + jiffies; + } +- hr_expires += jiffies; ++ hr_expires = min_t(unsigned long, ++ softlockup_get_next_event(), ++ hr_expires) + jiffies; + + base = __get_cpu_var(tvec_bases); + spin_lock(&base->lock); |