Blame view

kernel/softlockup.c 3.95 KB
8446f1d39   Ingo Molnar   [PATCH] detect so...
1
2
3
  /*
   * Detect Soft Lockups
   *
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
4
   * started by Ingo Molnar, Copyright (C) 2005, 2006 Red Hat, Inc.
8446f1d39   Ingo Molnar   [PATCH] detect so...
5
6
7
8
   *
   * this code detects soft lockups: incidents in where on a CPU
   * the kernel does not reschedule for 10 seconds or more.
   */
8446f1d39   Ingo Molnar   [PATCH] detect so...
9
10
11
12
13
14
15
16
17
  #include <linux/mm.h>
  #include <linux/cpu.h>
  #include <linux/init.h>
  #include <linux/delay.h>
  #include <linux/kthread.h>
  #include <linux/notifier.h>
  #include <linux/module.h>
  
  static DEFINE_SPINLOCK(print_lock);
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
18
19
  static DEFINE_PER_CPU(unsigned long, touch_timestamp);
  static DEFINE_PER_CPU(unsigned long, print_timestamp);
8446f1d39   Ingo Molnar   [PATCH] detect so...
20
21
22
  static DEFINE_PER_CPU(struct task_struct *, watchdog_task);
  
  static int did_panic = 0;
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
23
24
25
  
  static int
  softlock_panic(struct notifier_block *this, unsigned long event, void *ptr)
8446f1d39   Ingo Molnar   [PATCH] detect so...
26
27
28
29
30
31
32
33
34
35
36
37
  {
  	did_panic = 1;
  
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block panic_block = {
  	.notifier_call = softlock_panic,
  };
  
  void touch_softlockup_watchdog(void)
  {
bfe5d8341   Paul Mackerras   [PATCH] Define __...
38
  	__raw_get_cpu_var(touch_timestamp) = jiffies;
8446f1d39   Ingo Molnar   [PATCH] detect so...
39
40
41
42
43
44
45
  }
  EXPORT_SYMBOL(touch_softlockup_watchdog);
  
  /*
   * This callback runs from the timer interrupt, and checks
   * whether the watchdog thread has hung or not:
   */
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
46
  void softlockup_tick(void)
8446f1d39   Ingo Molnar   [PATCH] detect so...
47
48
  {
  	int this_cpu = smp_processor_id();
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
49
  	unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu);
8446f1d39   Ingo Molnar   [PATCH] detect so...
50

6687a97d4   Ingo Molnar   [PATCH] timer-irq...
51
52
53
54
  	/* prevent double reports: */
  	if (per_cpu(print_timestamp, this_cpu) == touch_timestamp ||
  		did_panic ||
  			!per_cpu(watchdog_task, this_cpu))
8446f1d39   Ingo Molnar   [PATCH] detect so...
55
  		return;
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
56
57
58
  	/* do not print during early bootup: */
  	if (unlikely(system_state != SYSTEM_RUNNING)) {
  		touch_softlockup_watchdog();
8446f1d39   Ingo Molnar   [PATCH] detect so...
59
  		return;
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
60
  	}
8446f1d39   Ingo Molnar   [PATCH] detect so...
61

6687a97d4   Ingo Molnar   [PATCH] timer-irq...
62
63
64
65
66
67
68
  	/* 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;
8446f1d39   Ingo Molnar   [PATCH] detect so...
69
70
71
72
73
  
  		spin_lock(&print_lock);
  		printk(KERN_ERR "BUG: soft lockup detected on CPU#%d!
  ",
  			this_cpu);
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
74
  		dump_stack();
8446f1d39   Ingo Molnar   [PATCH] detect so...
75
76
77
78
79
80
81
82
83
84
  		spin_unlock(&print_lock);
  	}
  }
  
  /*
   * The watchdog thread - runs every second and touches the timestamp.
   */
  static int watchdog(void * __bind_cpu)
  {
  	struct sched_param param = { .sched_priority = 99 };
8446f1d39   Ingo Molnar   [PATCH] detect so...
85
86
87
  
  	sched_setscheduler(current, SCHED_FIFO, &param);
  	current->flags |= PF_NOFREEZE;
8446f1d39   Ingo Molnar   [PATCH] detect so...
88
  	/*
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
89
90
91
  	 * 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().
8446f1d39   Ingo Molnar   [PATCH] detect so...
92
93
  	 */
  	while (!kthread_should_stop()) {
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
94
  		set_current_state(TASK_INTERRUPTIBLE);
8446f1d39   Ingo Molnar   [PATCH] detect so...
95
  		touch_softlockup_watchdog();
6687a97d4   Ingo Molnar   [PATCH] timer-irq...
96
  		schedule();
8446f1d39   Ingo Molnar   [PATCH] detect so...
97
  	}
8446f1d39   Ingo Molnar   [PATCH] detect so...
98
99
100
101
102
103
104
  
  	return 0;
  }
  
  /*
   * Create/destroy watchdog threads as CPUs come and go:
   */
8c78f3075   Chandra Seetharaman   [PATCH] cpu hotpl...
105
  static int __cpuinit
8446f1d39   Ingo Molnar   [PATCH] detect so...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
  {
  	int hotcpu = (unsigned long)hcpu;
  	struct task_struct *p;
  
  	switch (action) {
  	case CPU_UP_PREPARE:
  		BUG_ON(per_cpu(watchdog_task, hotcpu));
  		p = kthread_create(watchdog, hcpu, "watchdog/%d", hotcpu);
  		if (IS_ERR(p)) {
  			printk("watchdog for %i failed
  ", hotcpu);
  			return NOTIFY_BAD;
  		}
185ae6d7a   Andrew Morton   [PATCH] timer irq...
120
    		per_cpu(touch_timestamp, hotcpu) = jiffies;
8446f1d39   Ingo Molnar   [PATCH] detect so...
121
122
123
124
    		per_cpu(watchdog_task, hotcpu) = p;
  		kthread_bind(p, hotcpu);
   		break;
  	case CPU_ONLINE:
8446f1d39   Ingo Molnar   [PATCH] detect so...
125
126
127
128
  		wake_up_process(per_cpu(watchdog_task, hotcpu));
  		break;
  #ifdef CONFIG_HOTPLUG_CPU
  	case CPU_UP_CANCELED:
fc75cdfa5   Heiko Carstens   [PATCH] cpu hotpl...
129
130
  		if (!per_cpu(watchdog_task, hotcpu))
  			break;
8446f1d39   Ingo Molnar   [PATCH] detect so...
131
  		/* Unbind so it can run.  Fall thru. */
a4c4af7c8   Heiko Carstens   [PATCH] cpu hoptl...
132
133
  		kthread_bind(per_cpu(watchdog_task, hotcpu),
  			     any_online_cpu(cpu_online_map));
8446f1d39   Ingo Molnar   [PATCH] detect so...
134
135
136
137
138
139
140
141
142
  	case CPU_DEAD:
  		p = per_cpu(watchdog_task, hotcpu);
  		per_cpu(watchdog_task, hotcpu) = NULL;
  		kthread_stop(p);
  		break;
  #endif /* CONFIG_HOTPLUG_CPU */
   	}
  	return NOTIFY_OK;
  }
8c78f3075   Chandra Seetharaman   [PATCH] cpu hotpl...
143
  static struct notifier_block __cpuinitdata cpu_nfb = {
8446f1d39   Ingo Molnar   [PATCH] detect so...
144
145
146
147
148
149
  	.notifier_call = cpu_callback
  };
  
  __init void spawn_softlockup_task(void)
  {
  	void *cpu = (void *)(long)smp_processor_id();
07dccf334   Akinobu Mita   [PATCH] check ret...
150
  	int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
8446f1d39   Ingo Molnar   [PATCH] detect so...
151

07dccf334   Akinobu Mita   [PATCH] check ret...
152
  	BUG_ON(err == NOTIFY_BAD);
8446f1d39   Ingo Molnar   [PATCH] detect so...
153
154
  	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
  	register_cpu_notifier(&cpu_nfb);
e041c6834   Alan Stern   [PATCH] Notifier ...
155
  	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
8446f1d39   Ingo Molnar   [PATCH] detect so...
156
  }