diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-08-14 06:19:59 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-08-14 06:19:59 -0400 |
| commit | 8d7ccaa545490cdffdfaff0842436a8dd85cf47b (patch) | |
| tree | 8129b5907161bc6ae26deb3645ce1e280c5e1f51 /kernel/softlockup.c | |
| parent | b2139aa0eec330c711c5a279db361e5ef1178e78 (diff) | |
| parent | 30a2f3c60a84092c8084dfe788b710f8d0768cd4 (diff) | |
Merge commit 'v2.6.27-rc3' into x86/prototypes
Conflicts:
include/asm-x86/dma-mapping.h
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/softlockup.c')
| -rw-r--r-- | kernel/softlockup.c | 70 |
1 files changed, 60 insertions, 10 deletions
diff --git a/kernel/softlockup.c b/kernel/softlockup.c index a272d78185eb..b75b492fbfcf 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| 14 | #include <linux/freezer.h> | 14 | #include <linux/freezer.h> |
| 15 | #include <linux/kthread.h> | 15 | #include <linux/kthread.h> |
| 16 | #include <linux/lockdep.h> | ||
| 16 | #include <linux/notifier.h> | 17 | #include <linux/notifier.h> |
| 17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 18 | 19 | ||
| @@ -25,7 +26,22 @@ static DEFINE_PER_CPU(unsigned long, print_timestamp); | |||
| 25 | static DEFINE_PER_CPU(struct task_struct *, watchdog_task); | 26 | static DEFINE_PER_CPU(struct task_struct *, watchdog_task); |
| 26 | 27 | ||
| 27 | static int __read_mostly did_panic; | 28 | static int __read_mostly did_panic; |
| 28 | unsigned long __read_mostly softlockup_thresh = 60; | 29 | int __read_mostly softlockup_thresh = 60; |
| 30 | |||
| 31 | /* | ||
| 32 | * Should we panic (and reboot, if panic_timeout= is set) when a | ||
| 33 | * soft-lockup occurs: | ||
| 34 | */ | ||
| 35 | unsigned int __read_mostly softlockup_panic = | ||
| 36 | CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE; | ||
| 37 | |||
| 38 | static int __init softlockup_panic_setup(char *str) | ||
| 39 | { | ||
| 40 | softlockup_panic = simple_strtoul(str, NULL, 0); | ||
| 41 | |||
| 42 | return 1; | ||
| 43 | } | ||
| 44 | __setup("softlockup_panic=", softlockup_panic_setup); | ||
| 29 | 45 | ||
| 30 | static int | 46 | static int |
| 31 | softlock_panic(struct notifier_block *this, unsigned long event, void *ptr) | 47 | softlock_panic(struct notifier_block *this, unsigned long event, void *ptr) |
| @@ -84,6 +100,14 @@ void softlockup_tick(void) | |||
| 84 | struct pt_regs *regs = get_irq_regs(); | 100 | struct pt_regs *regs = get_irq_regs(); |
| 85 | unsigned long now; | 101 | unsigned long now; |
| 86 | 102 | ||
| 103 | /* Is detection switched off? */ | ||
| 104 | if (!per_cpu(watchdog_task, this_cpu) || softlockup_thresh <= 0) { | ||
| 105 | /* Be sure we don't false trigger if switched back on */ | ||
| 106 | if (touch_timestamp) | ||
| 107 | per_cpu(touch_timestamp, this_cpu) = 0; | ||
| 108 | return; | ||
| 109 | } | ||
| 110 | |||
| 87 | if (touch_timestamp == 0) { | 111 | if (touch_timestamp == 0) { |
| 88 | __touch_softlockup_watchdog(); | 112 | __touch_softlockup_watchdog(); |
| 89 | return; | 113 | return; |
| @@ -92,11 +116,8 @@ void softlockup_tick(void) | |||
| 92 | print_timestamp = per_cpu(print_timestamp, this_cpu); | 116 | print_timestamp = per_cpu(print_timestamp, this_cpu); |
| 93 | 117 | ||
| 94 | /* report at most once a second */ | 118 | /* report at most once a second */ |
| 95 | if ((print_timestamp >= touch_timestamp && | 119 | if (print_timestamp == touch_timestamp || did_panic) |
| 96 | print_timestamp < (touch_timestamp + 1)) || | ||
| 97 | did_panic || !per_cpu(watchdog_task, this_cpu)) { | ||
| 98 | return; | 120 | return; |
| 99 | } | ||
| 100 | 121 | ||
| 101 | /* do not print during early bootup: */ | 122 | /* do not print during early bootup: */ |
| 102 | if (unlikely(system_state != SYSTEM_RUNNING)) { | 123 | if (unlikely(system_state != SYSTEM_RUNNING)) { |
| @@ -106,8 +127,11 @@ void softlockup_tick(void) | |||
| 106 | 127 | ||
| 107 | now = get_timestamp(this_cpu); | 128 | now = get_timestamp(this_cpu); |
| 108 | 129 | ||
| 109 | /* Wake up the high-prio watchdog task every second: */ | 130 | /* |
| 110 | if (now > (touch_timestamp + 1)) | 131 | * Wake up the high-prio watchdog task twice per |
| 132 | * threshold timespan. | ||
| 133 | */ | ||
| 134 | if (now > touch_timestamp + softlockup_thresh/2) | ||
| 111 | wake_up_process(per_cpu(watchdog_task, this_cpu)); | 135 | wake_up_process(per_cpu(watchdog_task, this_cpu)); |
| 112 | 136 | ||
| 113 | /* Warn about unreasonable delays: */ | 137 | /* Warn about unreasonable delays: */ |
| @@ -121,11 +145,15 @@ void softlockup_tick(void) | |||
| 121 | this_cpu, now - touch_timestamp, | 145 | this_cpu, now - touch_timestamp, |
| 122 | current->comm, task_pid_nr(current)); | 146 | current->comm, task_pid_nr(current)); |
| 123 | print_modules(); | 147 | print_modules(); |
| 148 | print_irqtrace_events(current); | ||
| 124 | if (regs) | 149 | if (regs) |
| 125 | show_regs(regs); | 150 | show_regs(regs); |
| 126 | else | 151 | else |
| 127 | dump_stack(); | 152 | dump_stack(); |
| 128 | spin_unlock(&print_lock); | 153 | spin_unlock(&print_lock); |
| 154 | |||
| 155 | if (softlockup_panic) | ||
| 156 | panic("softlockup: hung tasks"); | ||
| 129 | } | 157 | } |
| 130 | 158 | ||
| 131 | /* | 159 | /* |
| @@ -178,6 +206,9 @@ static void check_hung_task(struct task_struct *t, unsigned long now) | |||
| 178 | 206 | ||
| 179 | t->last_switch_timestamp = now; | 207 | t->last_switch_timestamp = now; |
| 180 | touch_nmi_watchdog(); | 208 | touch_nmi_watchdog(); |
| 209 | |||
| 210 | if (softlockup_panic) | ||
| 211 | panic("softlockup: blocked tasks"); | ||
| 181 | } | 212 | } |
| 182 | 213 | ||
| 183 | /* | 214 | /* |
| @@ -307,14 +338,33 @@ static struct notifier_block __cpuinitdata cpu_nfb = { | |||
| 307 | .notifier_call = cpu_callback | 338 | .notifier_call = cpu_callback |
| 308 | }; | 339 | }; |
| 309 | 340 | ||
| 310 | __init void spawn_softlockup_task(void) | 341 | static int __initdata nosoftlockup; |
| 342 | |||
| 343 | static int __init nosoftlockup_setup(char *str) | ||
| 344 | { | ||
| 345 | nosoftlockup = 1; | ||
| 346 | return 1; | ||
| 347 | } | ||
| 348 | __setup("nosoftlockup", nosoftlockup_setup); | ||
| 349 | |||
| 350 | static int __init spawn_softlockup_task(void) | ||
| 311 | { | 351 | { |
| 312 | void *cpu = (void *)(long)smp_processor_id(); | 352 | void *cpu = (void *)(long)smp_processor_id(); |
| 313 | int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); | 353 | int err; |
| 354 | |||
| 355 | if (nosoftlockup) | ||
| 356 | return 0; | ||
| 314 | 357 | ||
| 315 | BUG_ON(err == NOTIFY_BAD); | 358 | err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); |
| 359 | if (err == NOTIFY_BAD) { | ||
| 360 | BUG(); | ||
| 361 | return 1; | ||
| 362 | } | ||
| 316 | cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); | 363 | cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); |
| 317 | register_cpu_notifier(&cpu_nfb); | 364 | register_cpu_notifier(&cpu_nfb); |
| 318 | 365 | ||
| 319 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); | 366 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); |
| 367 | |||
| 368 | return 0; | ||
| 320 | } | 369 | } |
| 370 | early_initcall(spawn_softlockup_task); | ||
