softlockup.c 7.7 KB
Newer Older
I
Ingo Molnar 已提交
1 2 3
/*
 * Detect Soft Lockups
 *
4
 * started by Ingo Molnar, Copyright (C) 2005, 2006 Red Hat, Inc.
I
Ingo Molnar 已提交
5 6 7 8 9 10
 *
 * this code detects soft lockups: incidents in where on a CPU
 * the kernel does not reschedule for 10 seconds or more.
 */
#include <linux/mm.h>
#include <linux/cpu.h>
11
#include <linux/nmi.h>
I
Ingo Molnar 已提交
12 13
#include <linux/init.h>
#include <linux/delay.h>
14
#include <linux/freezer.h>
I
Ingo Molnar 已提交
15 16 17 18
#include <linux/kthread.h>
#include <linux/notifier.h>
#include <linux/module.h>

I
Ingo Molnar 已提交
19 20
#include <asm/irq_regs.h>

I
Ingo Molnar 已提交
21 22
static DEFINE_SPINLOCK(print_lock);

23 24
static DEFINE_PER_CPU(unsigned long, touch_timestamp);
static DEFINE_PER_CPU(unsigned long, print_timestamp);
I
Ingo Molnar 已提交
25 26
static DEFINE_PER_CPU(struct task_struct *, watchdog_task);

I
Ingo Molnar 已提交
27 28
static int __read_mostly did_panic;
unsigned long __read_mostly softlockup_thresh = 60;
29 30 31

static int
softlock_panic(struct notifier_block *this, unsigned long event, void *ptr)
I
Ingo Molnar 已提交
32 33 34 35 36 37 38 39 40 41
{
	did_panic = 1;

	return NOTIFY_DONE;
}

static struct notifier_block panic_block = {
	.notifier_call = softlock_panic,
};

42 43 44 45 46
/*
 * Returns seconds, approximately.  We don't need nanosecond
 * resolution, and we don't need to waste time with a big divide when
 * 2^30ns == 1.074s.
 */
47
static unsigned long get_timestamp(int this_cpu)
48
{
49
	return cpu_clock(this_cpu) >> 30LL;  /* 2^30 ~= 10^9 */
50 51
}

I
Ingo Molnar 已提交
52 53
void touch_softlockup_watchdog(void)
{
54 55 56
	int this_cpu = raw_smp_processor_id();

	__raw_get_cpu_var(touch_timestamp) = get_timestamp(this_cpu);
I
Ingo Molnar 已提交
57 58 59
}
EXPORT_SYMBOL(touch_softlockup_watchdog);

60 61 62 63 64 65 66 67 68 69
void touch_all_softlockup_watchdogs(void)
{
	int cpu;

	/* Cause each CPU to re-update its timestamp rather than complain */
	for_each_online_cpu(cpu)
		per_cpu(touch_timestamp, cpu) = 0;
}
EXPORT_SYMBOL(touch_all_softlockup_watchdogs);

I
Ingo Molnar 已提交
70 71 72 73
/*
 * This callback runs from the timer interrupt, and checks
 * whether the watchdog thread has hung or not:
 */
74
void softlockup_tick(void)
I
Ingo Molnar 已提交
75 76
{
	int this_cpu = smp_processor_id();
77
	unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu);
78
	unsigned long print_timestamp;
I
Ingo Molnar 已提交
79
	struct pt_regs *regs = get_irq_regs();
80
	unsigned long now;
I
Ingo Molnar 已提交
81

82 83
	if (touch_timestamp == 0) {
		touch_softlockup_watchdog();
84
		return;
85
	}
86 87 88 89

	print_timestamp = per_cpu(print_timestamp, this_cpu);

	/* report at most once a second */
90 91 92
	if ((print_timestamp >= touch_timestamp &&
			print_timestamp < (touch_timestamp + 1)) ||
			did_panic || !per_cpu(watchdog_task, this_cpu)) {
I
Ingo Molnar 已提交
93
		return;
94
	}
I
Ingo Molnar 已提交
95

96 97 98
	/* do not print during early bootup: */
	if (unlikely(system_state != SYSTEM_RUNNING)) {
		touch_softlockup_watchdog();
I
Ingo Molnar 已提交
99
		return;
100
	}
I
Ingo Molnar 已提交
101

102
	now = get_timestamp(this_cpu);
103

P
Peter Zijlstra 已提交
104 105 106 107
	/* Wake up the high-prio watchdog task every second: */
	if (now > (touch_timestamp + 1))
		wake_up_process(per_cpu(watchdog_task, this_cpu));

108
	/* Warn about unreasonable delays: */
109
	if (now <= (touch_timestamp + softlockup_thresh))
I
Ingo Molnar 已提交
110
		return;
I
Ingo Molnar 已提交
111

I
Ingo Molnar 已提交
112 113 114
	per_cpu(print_timestamp, this_cpu) = touch_timestamp;

	spin_lock(&print_lock);
115 116
	printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %lus! [%s:%d]\n",
			this_cpu, now - touch_timestamp,
117
			current->comm, task_pid_nr(current));
I
Ingo Molnar 已提交
118 119 120
	if (regs)
		show_regs(regs);
	else
121
		dump_stack();
I
Ingo Molnar 已提交
122
	spin_unlock(&print_lock);
I
Ingo Molnar 已提交
123 124
}

125 126 127
/*
 * Have a reasonable limit on the number of tasks checked:
 */
I
Ingo Molnar 已提交
128
unsigned long __read_mostly sysctl_hung_task_check_count = 1024;
129 130 131 132

/*
 * Zero means infinite timeout - no checking done:
 */
I
Ingo Molnar 已提交
133
unsigned long __read_mostly sysctl_hung_task_timeout_secs = 120;
134

I
Ingo Molnar 已提交
135
unsigned long __read_mostly sysctl_hung_task_warnings = 10;
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

/*
 * Only do the hung-tasks check on one CPU:
 */
static int check_cpu __read_mostly = -1;

static void check_hung_task(struct task_struct *t, unsigned long now)
{
	unsigned long switch_count = t->nvcsw + t->nivcsw;

	if (t->flags & PF_FROZEN)
		return;

	if (switch_count != t->last_switch_count || !t->last_switch_timestamp) {
		t->last_switch_count = switch_count;
		t->last_switch_timestamp = now;
		return;
	}
	if ((long)(now - t->last_switch_timestamp) <
					sysctl_hung_task_timeout_secs)
		return;
	if (sysctl_hung_task_warnings < 0)
		return;
	sysctl_hung_task_warnings--;

	/*
	 * Ok, the task did not get scheduled for more than 2 minutes,
	 * complain:
	 */
	printk(KERN_ERR "INFO: task %s:%d blocked for more than "
			"%ld seconds.\n", t->comm, t->pid,
			sysctl_hung_task_timeout_secs);
	printk(KERN_ERR "\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
			" disables this message.\n");
	sched_show_task(t);
	__debug_show_held_locks(t);

	t->last_switch_timestamp = now;
	touch_nmi_watchdog();
}

/*
 * Check whether a TASK_UNINTERRUPTIBLE does not get woken up for
 * a really long time (120 seconds). If that happens, print out
 * a warning.
 */
static void check_hung_uninterruptible_tasks(int this_cpu)
{
	int max_count = sysctl_hung_task_check_count;
	unsigned long now = get_timestamp(this_cpu);
	struct task_struct *g, *t;

	/*
	 * If the system crashed already then all bets are off,
	 * do not report extra hung tasks:
	 */
	if ((tainted & TAINT_DIE) || did_panic)
		return;

	read_lock(&tasklist_lock);
	do_each_thread(g, t) {
		if (!--max_count)
P
Peter Zijlstra 已提交
198
			goto unlock;
199 200 201
		if (t->state & TASK_UNINTERRUPTIBLE)
			check_hung_task(t, now);
	} while_each_thread(g, t);
P
Peter Zijlstra 已提交
202
 unlock:
203 204 205
	read_unlock(&tasklist_lock);
}

I
Ingo Molnar 已提交
206 207 208
/*
 * The watchdog thread - runs every second and touches the timestamp.
 */
I
Ingo Molnar 已提交
209
static int watchdog(void *__bind_cpu)
I
Ingo Molnar 已提交
210
{
O
Oleg Nesterov 已提交
211
	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
212
	int this_cpu = (long)__bind_cpu;
I
Ingo Molnar 已提交
213 214 215

	sched_setscheduler(current, SCHED_FIFO, &param);

216 217 218
	/* initialize timestamp */
	touch_softlockup_watchdog();

219
	set_current_state(TASK_INTERRUPTIBLE);
I
Ingo Molnar 已提交
220
	/*
221
	 * Run briefly once per second to reset the softlockup timestamp.
222
	 * If this gets delayed for more than 60 seconds then the
223
	 * debug-printout triggers in softlockup_tick().
I
Ingo Molnar 已提交
224 225 226
	 */
	while (!kthread_should_stop()) {
		touch_softlockup_watchdog();
P
Peter Zijlstra 已提交
227 228 229 230
		schedule();

		if (kthread_should_stop())
			break;
231

232 233 234 235
		if (this_cpu == check_cpu) {
			if (sysctl_hung_task_timeout_secs)
				check_hung_uninterruptible_tasks(this_cpu);
		}
P
Peter Zijlstra 已提交
236

237
		set_current_state(TASK_INTERRUPTIBLE);
I
Ingo Molnar 已提交
238
	}
239
	__set_current_state(TASK_RUNNING);
I
Ingo Molnar 已提交
240 241 242 243 244 245 246

	return 0;
}

/*
 * Create/destroy watchdog threads as CPUs come and go:
 */
247
static int __cpuinit
I
Ingo Molnar 已提交
248 249 250 251 252 253 254
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:
255
	case CPU_UP_PREPARE_FROZEN:
I
Ingo Molnar 已提交
256 257 258
		BUG_ON(per_cpu(watchdog_task, hotcpu));
		p = kthread_create(watchdog, hcpu, "watchdog/%d", hotcpu);
		if (IS_ERR(p)) {
I
Ingo Molnar 已提交
259
			printk(KERN_ERR "watchdog for %i failed\n", hotcpu);
I
Ingo Molnar 已提交
260 261
			return NOTIFY_BAD;
		}
I
Ingo Molnar 已提交
262 263
		per_cpu(touch_timestamp, hotcpu) = 0;
		per_cpu(watchdog_task, hotcpu) = p;
I
Ingo Molnar 已提交
264
		kthread_bind(p, hotcpu);
I
Ingo Molnar 已提交
265
		break;
I
Ingo Molnar 已提交
266
	case CPU_ONLINE:
267
	case CPU_ONLINE_FROZEN:
268
		check_cpu = any_online_cpu(cpu_online_map);
I
Ingo Molnar 已提交
269 270 271
		wake_up_process(per_cpu(watchdog_task, hotcpu));
		break;
#ifdef CONFIG_HOTPLUG_CPU
272 273 274 275 276 277 278 279 280
	case CPU_DOWN_PREPARE:
	case CPU_DOWN_PREPARE_FROZEN:
		if (hotcpu == check_cpu) {
			cpumask_t temp_cpu_online_map = cpu_online_map;

			cpu_clear(hotcpu, temp_cpu_online_map);
			check_cpu = any_online_cpu(temp_cpu_online_map);
		}
		break;
P
Peter Zijlstra 已提交
281 282 283 284 285 286 287 288

	case CPU_UP_CANCELED:
	case CPU_UP_CANCELED_FROZEN:
		if (!per_cpu(watchdog_task, hotcpu))
			break;
		/* Unbind so it can run.  Fall thru. */
		kthread_bind(per_cpu(watchdog_task, hotcpu),
			     any_online_cpu(cpu_online_map));
I
Ingo Molnar 已提交
289
	case CPU_DEAD:
290
	case CPU_DEAD_FROZEN:
I
Ingo Molnar 已提交
291 292 293 294 295
		p = per_cpu(watchdog_task, hotcpu);
		per_cpu(watchdog_task, hotcpu) = NULL;
		kthread_stop(p);
		break;
#endif /* CONFIG_HOTPLUG_CPU */
I
Ingo Molnar 已提交
296
	}
I
Ingo Molnar 已提交
297 298 299
	return NOTIFY_OK;
}

300
static struct notifier_block __cpuinitdata cpu_nfb = {
I
Ingo Molnar 已提交
301 302 303 304 305 306
	.notifier_call = cpu_callback
};

__init void spawn_softlockup_task(void)
{
	void *cpu = (void *)(long)smp_processor_id();
307
	int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
I
Ingo Molnar 已提交
308

309
	BUG_ON(err == NOTIFY_BAD);
I
Ingo Molnar 已提交
310 311 312
	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
	register_cpu_notifier(&cpu_nfb);

313
	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
I
Ingo Molnar 已提交
314
}