X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fsoftlockup.c;h=c67189a25d52efbd2aa6afdf0655cfe860971189;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=14c7faf02909e8e4879a057406416a43a34b3fdf;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/kernel/softlockup.c b/kernel/softlockup.c index 14c7faf02..c67189a25 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c @@ -1,11 +1,12 @@ /* * Detect Soft Lockups * - * started by Ingo Molnar, Copyright (C) 2005, 2006 Red Hat, Inc. + * started by Ingo Molnar, (C) 2005, Red Hat * * this code detects soft lockups: incidents in where on a CPU * the kernel does not reschedule for 10 seconds or more. */ + #include #include #include @@ -16,14 +17,13 @@ static DEFINE_SPINLOCK(print_lock); -static DEFINE_PER_CPU(unsigned long, touch_timestamp); -static DEFINE_PER_CPU(unsigned long, print_timestamp); +static DEFINE_PER_CPU(unsigned long, timestamp) = 0; +static DEFINE_PER_CPU(unsigned long, print_timestamp) = 0; static DEFINE_PER_CPU(struct task_struct *, watchdog_task); static int did_panic = 0; - -static int -softlock_panic(struct notifier_block *this, unsigned long event, void *ptr) +static int softlock_panic(struct notifier_block *this, unsigned long event, + void *ptr) { did_panic = 1; @@ -36,7 +36,7 @@ static struct notifier_block panic_block = { void touch_softlockup_watchdog(void) { - per_cpu(touch_timestamp, raw_smp_processor_id()) = jiffies; + per_cpu(timestamp, raw_smp_processor_id()) = jiffies; } EXPORT_SYMBOL(touch_softlockup_watchdog); @@ -44,35 +44,25 @@ EXPORT_SYMBOL(touch_softlockup_watchdog); * This callback runs from the timer interrupt, and checks * whether the watchdog thread has hung or not: */ -void softlockup_tick(void) +void softlockup_tick(struct pt_regs *regs) { int this_cpu = smp_processor_id(); - unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu); + unsigned long timestamp = per_cpu(timestamp, this_cpu); - /* prevent double reports: */ - if (per_cpu(print_timestamp, this_cpu) == touch_timestamp || - did_panic || - !per_cpu(watchdog_task, this_cpu)) + if (per_cpu(print_timestamp, this_cpu) == timestamp) return; - /* do not print during early bootup: */ - if (unlikely(system_state != SYSTEM_RUNNING)) { - touch_softlockup_watchdog(); + /* Do not cause a second panic when there already was one */ + if (did_panic) return; - } - /* Wake up the high-prio watchdog task every second: */ - if (time_after(jiffies, touch_timestamp + HZ)) - wake_up_process(per_cpu(watchdog_task, this_cpu)); - - /* Warn about unreasonable 10+ seconds delays: */ - if (time_after(jiffies, touch_timestamp + 10*HZ)) { - per_cpu(print_timestamp, this_cpu) = touch_timestamp; + if (time_after(jiffies, timestamp + 10*HZ)) { + per_cpu(print_timestamp, this_cpu) = timestamp; spin_lock(&print_lock); printk(KERN_ERR "BUG: soft lockup detected on CPU#%d!\n", this_cpu); - dump_stack(); + show_regs(regs); spin_unlock(&print_lock); } } @@ -87,16 +77,18 @@ static int watchdog(void * __bind_cpu) sched_setscheduler(current, SCHED_FIFO, ¶m); current->flags |= PF_NOFREEZE; + set_current_state(TASK_INTERRUPTIBLE); + /* - * Run briefly once per second to reset the softlockup timestamp. - * If this gets delayed for more than 10 seconds then the - * debug-printout triggers in softlockup_tick(). + * Run briefly once per second - if this gets delayed for + * more than 10 seconds then the debug-printout triggers + * in softlockup_tick(): */ while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); + msleep_interruptible(1000); touch_softlockup_watchdog(); - schedule(); } + __set_current_state(TASK_RUNNING); return 0; } @@ -104,7 +96,7 @@ static int watchdog(void * __bind_cpu) /* * Create/destroy watchdog threads as CPUs come and go: */ -static int +static int __devinit cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { int hotcpu = (unsigned long)hcpu; @@ -118,11 +110,11 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) printk("watchdog for %i failed\n", hotcpu); return NOTIFY_BAD; } - per_cpu(touch_timestamp, hotcpu) = jiffies; per_cpu(watchdog_task, hotcpu) = p; kthread_bind(p, hotcpu); break; case CPU_ONLINE: + wake_up_process(per_cpu(watchdog_task, hotcpu)); break; #ifdef CONFIG_HOTPLUG_CPU @@ -140,7 +132,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block cpu_nfb = { +static struct notifier_block __devinitdata cpu_nfb = { .notifier_call = cpu_callback }; @@ -152,5 +144,6 @@ __init void spawn_softlockup_task(void) cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); register_cpu_notifier(&cpu_nfb); - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + notifier_chain_register(&panic_notifier_list, &panic_block); } +