1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e162b39aSMandeep Singh Baines /*
3e162b39aSMandeep Singh Baines * Detect Hung Task
4e162b39aSMandeep Singh Baines *
5e162b39aSMandeep Singh Baines * kernel/hung_task.c - kernel thread for detecting tasks stuck in D state
6e162b39aSMandeep Singh Baines *
7e162b39aSMandeep Singh Baines */
8e162b39aSMandeep Singh Baines
9e162b39aSMandeep Singh Baines #include <linux/mm.h>
10e162b39aSMandeep Singh Baines #include <linux/cpu.h>
11e162b39aSMandeep Singh Baines #include <linux/nmi.h>
12e162b39aSMandeep Singh Baines #include <linux/init.h>
13e162b39aSMandeep Singh Baines #include <linux/delay.h>
14e162b39aSMandeep Singh Baines #include <linux/freezer.h>
15e162b39aSMandeep Singh Baines #include <linux/kthread.h>
16e162b39aSMandeep Singh Baines #include <linux/lockdep.h>
179984de1aSPaul Gortmaker #include <linux/export.h>
18f39650deSAndy Shevchenko #include <linux/panic_notifier.h>
19e162b39aSMandeep Singh Baines #include <linux/sysctl.h>
20a1c6ca3cSVitaly Kuznetsov #include <linux/suspend.h>
2141e85ce8SOleg Nesterov #include <linux/utsname.h>
223f07c014SIngo Molnar #include <linux/sched/signal.h>
23b17b0153SIngo Molnar #include <linux/sched/debug.h>
24a98eb6f1SValdis Kletnieks #include <linux/sched/sysctl.h>
253f07c014SIngo Molnar
266a716c90SOleg Nesterov #include <trace/events/sched.h>
27e162b39aSMandeep Singh Baines
28e162b39aSMandeep Singh Baines /*
29ce9dbe24SMandeep Singh Baines * The number of tasks checked:
30e162b39aSMandeep Singh Baines */
31882c5b26STom Rix static int __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT;
32ce9dbe24SMandeep Singh Baines
33ce9dbe24SMandeep Singh Baines /*
3403ecb24dSLance Yang * Total number of tasks detected as hung since boot:
3503ecb24dSLance Yang */
3603ecb24dSLance Yang static unsigned long __read_mostly sysctl_hung_task_detect_count;
3703ecb24dSLance Yang
3803ecb24dSLance Yang /*
39ce9dbe24SMandeep Singh Baines * Limit number of tasks checked in a batch.
40ce9dbe24SMandeep Singh Baines *
41ce9dbe24SMandeep Singh Baines * This value controls the preemptibility of khungtaskd since preemption
42ce9dbe24SMandeep Singh Baines * is disabled during the critical section. It also controls the size of
43ce9dbe24SMandeep Singh Baines * the RCU grace period. So it needs to be upper-bound.
44ce9dbe24SMandeep Singh Baines */
45304ae427STetsuo Handa #define HUNG_TASK_LOCK_BREAK (HZ / 10)
46e162b39aSMandeep Singh Baines
47e162b39aSMandeep Singh Baines /*
48e162b39aSMandeep Singh Baines * Zero means infinite timeout - no checking done:
49e162b39aSMandeep Singh Baines */
50e11feaa1SJeff Mahoney unsigned long __read_mostly sysctl_hung_task_timeout_secs = CONFIG_DEFAULT_HUNG_TASK_TIMEOUT;
515c3273ecSKent Overstreet EXPORT_SYMBOL_GPL(sysctl_hung_task_timeout_secs);
52e162b39aSMandeep Singh Baines
53a2e51445SDmitry Vyukov /*
54a2e51445SDmitry Vyukov * Zero (default value) means use sysctl_hung_task_timeout_secs:
55a2e51445SDmitry Vyukov */
56882c5b26STom Rix static unsigned long __read_mostly sysctl_hung_task_check_interval_secs;
57a2e51445SDmitry Vyukov
58882c5b26STom Rix static int __read_mostly sysctl_hung_task_warnings = 10;
59e162b39aSMandeep Singh Baines
60e162b39aSMandeep Singh Baines static int __read_mostly did_panic;
61780cbcf2STetsuo Handa static bool hung_task_show_lock;
62401c636aSTetsuo Handa static bool hung_task_call_panic;
630ec9dc9bSGuilherme G. Piccoli static bool hung_task_show_all_bt;
64e162b39aSMandeep Singh Baines
65e162b39aSMandeep Singh Baines static struct task_struct *watchdog_task;
66e162b39aSMandeep Singh Baines
670ec9dc9bSGuilherme G. Piccoli #ifdef CONFIG_SMP
680ec9dc9bSGuilherme G. Piccoli /*
690ec9dc9bSGuilherme G. Piccoli * Should we dump all CPUs backtraces in a hung task event?
700ec9dc9bSGuilherme G. Piccoli * Defaults to 0, can be changed via sysctl.
710ec9dc9bSGuilherme G. Piccoli */
72bbe7a10eSXiaoming Ni static unsigned int __read_mostly sysctl_hung_task_all_cpu_backtrace;
73bbe7a10eSXiaoming Ni #else
74bbe7a10eSXiaoming Ni #define sysctl_hung_task_all_cpu_backtrace 0
750ec9dc9bSGuilherme G. Piccoli #endif /* CONFIG_SMP */
760ec9dc9bSGuilherme G. Piccoli
77e162b39aSMandeep Singh Baines /*
78e162b39aSMandeep Singh Baines * Should we panic (and reboot, if panic_timeout= is set) when a
79e162b39aSMandeep Singh Baines * hung task is detected:
80e162b39aSMandeep Singh Baines */
81882c5b26STom Rix static unsigned int __read_mostly sysctl_hung_task_panic =
8267fca000SRasmus Villemoes IS_ENABLED(CONFIG_BOOTPARAM_HUNG_TASK_PANIC);
83e162b39aSMandeep Singh Baines
84e162b39aSMandeep Singh Baines static int
hung_task_panic(struct notifier_block * this,unsigned long event,void * ptr)85e162b39aSMandeep Singh Baines hung_task_panic(struct notifier_block *this, unsigned long event, void *ptr)
86e162b39aSMandeep Singh Baines {
87e162b39aSMandeep Singh Baines did_panic = 1;
88e162b39aSMandeep Singh Baines
89e162b39aSMandeep Singh Baines return NOTIFY_DONE;
90e162b39aSMandeep Singh Baines }
91e162b39aSMandeep Singh Baines
92e162b39aSMandeep Singh Baines static struct notifier_block panic_block = {
93e162b39aSMandeep Singh Baines .notifier_call = hung_task_panic,
94e162b39aSMandeep Singh Baines };
95e162b39aSMandeep Singh Baines
96*3cf67d61SMasami Hiramatsu (Google)
97*3cf67d61SMasami Hiramatsu (Google) #ifdef CONFIG_DETECT_HUNG_TASK_BLOCKER
debug_show_blocker(struct task_struct * task)98*3cf67d61SMasami Hiramatsu (Google) static void debug_show_blocker(struct task_struct *task)
99*3cf67d61SMasami Hiramatsu (Google) {
100*3cf67d61SMasami Hiramatsu (Google) struct task_struct *g, *t;
101*3cf67d61SMasami Hiramatsu (Google) unsigned long owner;
102*3cf67d61SMasami Hiramatsu (Google) struct mutex *lock;
103*3cf67d61SMasami Hiramatsu (Google)
104*3cf67d61SMasami Hiramatsu (Google) RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "No rcu lock held");
105*3cf67d61SMasami Hiramatsu (Google)
106*3cf67d61SMasami Hiramatsu (Google) lock = READ_ONCE(task->blocker_mutex);
107*3cf67d61SMasami Hiramatsu (Google) if (!lock)
108*3cf67d61SMasami Hiramatsu (Google) return;
109*3cf67d61SMasami Hiramatsu (Google)
110*3cf67d61SMasami Hiramatsu (Google) owner = mutex_get_owner(lock);
111*3cf67d61SMasami Hiramatsu (Google) if (unlikely(!owner)) {
112*3cf67d61SMasami Hiramatsu (Google) pr_err("INFO: task %s:%d is blocked on a mutex, but the owner is not found.\n",
113*3cf67d61SMasami Hiramatsu (Google) task->comm, task->pid);
114*3cf67d61SMasami Hiramatsu (Google) return;
115*3cf67d61SMasami Hiramatsu (Google) }
116*3cf67d61SMasami Hiramatsu (Google)
117*3cf67d61SMasami Hiramatsu (Google) /* Ensure the owner information is correct. */
118*3cf67d61SMasami Hiramatsu (Google) for_each_process_thread(g, t) {
119*3cf67d61SMasami Hiramatsu (Google) if ((unsigned long)t == owner) {
120*3cf67d61SMasami Hiramatsu (Google) pr_err("INFO: task %s:%d is blocked on a mutex likely owned by task %s:%d.\n",
121*3cf67d61SMasami Hiramatsu (Google) task->comm, task->pid, t->comm, t->pid);
122*3cf67d61SMasami Hiramatsu (Google) sched_show_task(t);
123*3cf67d61SMasami Hiramatsu (Google) return;
124*3cf67d61SMasami Hiramatsu (Google) }
125*3cf67d61SMasami Hiramatsu (Google) }
126*3cf67d61SMasami Hiramatsu (Google) }
127*3cf67d61SMasami Hiramatsu (Google) #else
debug_show_blocker(struct task_struct * task)128*3cf67d61SMasami Hiramatsu (Google) static inline void debug_show_blocker(struct task_struct *task)
129*3cf67d61SMasami Hiramatsu (Google) {
130*3cf67d61SMasami Hiramatsu (Google) }
131*3cf67d61SMasami Hiramatsu (Google) #endif
132*3cf67d61SMasami Hiramatsu (Google)
check_hung_task(struct task_struct * t,unsigned long timeout)13317406b82SMandeep Singh Baines static void check_hung_task(struct task_struct *t, unsigned long timeout)
134e162b39aSMandeep Singh Baines {
135e162b39aSMandeep Singh Baines unsigned long switch_count = t->nvcsw + t->nivcsw;
136e162b39aSMandeep Singh Baines
137cf2592f5SFrederic Weisbecker /*
138cf2592f5SFrederic Weisbecker * Ensure the task is not frozen.
139f9fab10bSMandeep Singh Baines * Also, skip vfork and any other user process that freezer should skip.
140cf2592f5SFrederic Weisbecker */
141fdf756f7SPeter Zijlstra if (unlikely(READ_ONCE(t->__state) & TASK_FROZEN))
142f9fab10bSMandeep Singh Baines return;
143f9fab10bSMandeep Singh Baines
144f9fab10bSMandeep Singh Baines /*
145f9fab10bSMandeep Singh Baines * When a freshly created task is scheduled once, changes its state to
146f9fab10bSMandeep Singh Baines * TASK_UNINTERRUPTIBLE without having ever been switched out once, it
147f9fab10bSMandeep Singh Baines * musn't be checked.
148f9fab10bSMandeep Singh Baines */
149f9fab10bSMandeep Singh Baines if (unlikely(!switch_count))
150e162b39aSMandeep Singh Baines return;
151e162b39aSMandeep Singh Baines
15217406b82SMandeep Singh Baines if (switch_count != t->last_switch_count) {
153e162b39aSMandeep Singh Baines t->last_switch_count = switch_count;
154a2e51445SDmitry Vyukov t->last_switch_time = jiffies;
155e162b39aSMandeep Singh Baines return;
156e162b39aSMandeep Singh Baines }
157a2e51445SDmitry Vyukov if (time_is_after_jiffies(t->last_switch_time + timeout * HZ))
158a2e51445SDmitry Vyukov return;
1596a716c90SOleg Nesterov
16003ecb24dSLance Yang /*
16103ecb24dSLance Yang * This counter tracks the total number of tasks detected as hung
16203ecb24dSLance Yang * since boot.
16303ecb24dSLance Yang */
16403ecb24dSLance Yang sysctl_hung_task_detect_count++;
16503ecb24dSLance Yang
1666a716c90SOleg Nesterov trace_sched_process_hang(t);
1676a716c90SOleg Nesterov
168168e06f7SLiu, Chuansheng if (sysctl_hung_task_panic) {
169168e06f7SLiu, Chuansheng console_verbose();
170168e06f7SLiu, Chuansheng hung_task_show_lock = true;
171168e06f7SLiu, Chuansheng hung_task_call_panic = true;
172168e06f7SLiu, Chuansheng }
173270750dbSAaron Tomlin
174e162b39aSMandeep Singh Baines /*
175e162b39aSMandeep Singh Baines * Ok, the task did not get scheduled for more than 2 minutes,
176e162b39aSMandeep Singh Baines * complain:
177e162b39aSMandeep Singh Baines */
178abd8ac05SYongliang Gao if (sysctl_hung_task_warnings || hung_task_call_panic) {
1794ca5ede0STetsuo Handa if (sysctl_hung_task_warnings > 0)
18048a6d64eSJohn Siddle sysctl_hung_task_warnings--;
18141e85ce8SOleg Nesterov pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n",
182b014bebaSTetsuo Handa t->comm, t->pid, (jiffies - t->last_switch_time) / HZ);
18341e85ce8SOleg Nesterov pr_err(" %s %s %.*s\n",
18441e85ce8SOleg Nesterov print_tainted(), init_utsname()->release,
18541e85ce8SOleg Nesterov (int)strcspn(init_utsname()->version, " "),
18641e85ce8SOleg Nesterov init_utsname()->version);
18765ef17aaSOxana Kharitonova if (t->flags & PF_POSTCOREDUMP)
18865ef17aaSOxana Kharitonova pr_err(" Blocked by coredump.\n");
18941e85ce8SOleg Nesterov pr_err("\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
190e162b39aSMandeep Singh Baines " disables this message.\n");
191e162b39aSMandeep Singh Baines sched_show_task(t);
192*3cf67d61SMasami Hiramatsu (Google) debug_show_blocker(t);
193780cbcf2STetsuo Handa hung_task_show_lock = true;
1940ec9dc9bSGuilherme G. Piccoli
1950ec9dc9bSGuilherme G. Piccoli if (sysctl_hung_task_all_cpu_backtrace)
1960ec9dc9bSGuilherme G. Piccoli hung_task_show_all_bt = true;
197b1f712b3Sfuyuanli if (!sysctl_hung_task_warnings)
198b1f712b3Sfuyuanli pr_info("Future hung task reports are suppressed, see sysctl kernel.hung_task_warnings\n");
19948a6d64eSJohn Siddle }
200e162b39aSMandeep Singh Baines
201e162b39aSMandeep Singh Baines touch_nmi_watchdog();
202625056b6SSasha Levin }
203e162b39aSMandeep Singh Baines
204e162b39aSMandeep Singh Baines /*
205ce9dbe24SMandeep Singh Baines * To avoid extending the RCU grace period for an unbounded amount of time,
206ce9dbe24SMandeep Singh Baines * periodically exit the critical section and enter a new one.
207ce9dbe24SMandeep Singh Baines *
208ce9dbe24SMandeep Singh Baines * For preemptible RCU it is sufficient to call rcu_read_unlock in order
2096a103b0dSJohn Kacur * to exit the grace period. For classic RCU, a reschedule is required.
210ce9dbe24SMandeep Singh Baines */
rcu_lock_break(struct task_struct * g,struct task_struct * t)2116027ce49SOleg Nesterov static bool rcu_lock_break(struct task_struct *g, struct task_struct *t)
212ce9dbe24SMandeep Singh Baines {
2136027ce49SOleg Nesterov bool can_cont;
2146027ce49SOleg Nesterov
215ce9dbe24SMandeep Singh Baines get_task_struct(g);
216ce9dbe24SMandeep Singh Baines get_task_struct(t);
217ce9dbe24SMandeep Singh Baines rcu_read_unlock();
218ce9dbe24SMandeep Singh Baines cond_resched();
219ce9dbe24SMandeep Singh Baines rcu_read_lock();
2206027ce49SOleg Nesterov can_cont = pid_alive(g) && pid_alive(t);
221ce9dbe24SMandeep Singh Baines put_task_struct(t);
222ce9dbe24SMandeep Singh Baines put_task_struct(g);
2236027ce49SOleg Nesterov
2246027ce49SOleg Nesterov return can_cont;
225ce9dbe24SMandeep Singh Baines }
226ce9dbe24SMandeep Singh Baines
227ce9dbe24SMandeep Singh Baines /*
228e162b39aSMandeep Singh Baines * Check whether a TASK_UNINTERRUPTIBLE does not get woken up for
229e162b39aSMandeep Singh Baines * a really long time (120 seconds). If that happens, print out
230e162b39aSMandeep Singh Baines * a warning.
231e162b39aSMandeep Singh Baines */
check_hung_uninterruptible_tasks(unsigned long timeout)232603a148fSMandeep Singh Baines static void check_hung_uninterruptible_tasks(unsigned long timeout)
233e162b39aSMandeep Singh Baines {
234e162b39aSMandeep Singh Baines int max_count = sysctl_hung_task_check_count;
235304ae427STetsuo Handa unsigned long last_break = jiffies;
236e162b39aSMandeep Singh Baines struct task_struct *g, *t;
237e162b39aSMandeep Singh Baines
238e162b39aSMandeep Singh Baines /*
239e162b39aSMandeep Singh Baines * If the system crashed already then all bets are off,
240e162b39aSMandeep Singh Baines * do not report extra hung tasks:
241e162b39aSMandeep Singh Baines */
242e162b39aSMandeep Singh Baines if (test_taint(TAINT_DIE) || did_panic)
243e162b39aSMandeep Singh Baines return;
244e162b39aSMandeep Singh Baines
245780cbcf2STetsuo Handa hung_task_show_lock = false;
24694be52dcSMandeep Singh Baines rcu_read_lock();
247972fae69SAaron Tomlin for_each_process_thread(g, t) {
2485aec788aSPeter Zijlstra unsigned int state;
2495aec788aSPeter Zijlstra
250e5af0226SAnton Blanchard if (!max_count--)
251e162b39aSMandeep Singh Baines goto unlock;
252304ae427STetsuo Handa if (time_after(jiffies, last_break + HUNG_TASK_LOCK_BREAK)) {
2536027ce49SOleg Nesterov if (!rcu_lock_break(g, t))
254ce9dbe24SMandeep Singh Baines goto unlock;
255304ae427STetsuo Handa last_break = jiffies;
256ce9dbe24SMandeep Singh Baines }
257fdf756f7SPeter Zijlstra /*
258fdf756f7SPeter Zijlstra * skip the TASK_KILLABLE tasks -- these can be killed
259fdf756f7SPeter Zijlstra * skip the TASK_IDLE tasks -- those are genuinely idle
260fdf756f7SPeter Zijlstra */
2615aec788aSPeter Zijlstra state = READ_ONCE(t->__state);
2625aec788aSPeter Zijlstra if ((state & TASK_UNINTERRUPTIBLE) &&
263fdf756f7SPeter Zijlstra !(state & TASK_WAKEKILL) &&
264fdf756f7SPeter Zijlstra !(state & TASK_NOLOAD))
26517406b82SMandeep Singh Baines check_hung_task(t, timeout);
266972fae69SAaron Tomlin }
267e162b39aSMandeep Singh Baines unlock:
26894be52dcSMandeep Singh Baines rcu_read_unlock();
26907a22b61SPetr Mladek if (hung_task_show_lock)
270780cbcf2STetsuo Handa debug_show_all_locks();
2710ec9dc9bSGuilherme G. Piccoli
2720ec9dc9bSGuilherme G. Piccoli if (hung_task_show_all_bt) {
2730ec9dc9bSGuilherme G. Piccoli hung_task_show_all_bt = false;
274401c636aSTetsuo Handa trigger_all_cpu_backtrace();
275401c636aSTetsuo Handa }
2760ec9dc9bSGuilherme G. Piccoli
2770ec9dc9bSGuilherme G. Piccoli if (hung_task_call_panic)
2780ec9dc9bSGuilherme G. Piccoli panic("hung_task: blocked tasks");
279e162b39aSMandeep Singh Baines }
280e162b39aSMandeep Singh Baines
hung_timeout_jiffies(unsigned long last_checked,unsigned long timeout)281b4aa14a6STetsuo Handa static long hung_timeout_jiffies(unsigned long last_checked,
282b4aa14a6STetsuo Handa unsigned long timeout)
283e162b39aSMandeep Singh Baines {
284e162b39aSMandeep Singh Baines /* timeout of 0 will disable the watchdog */
285b4aa14a6STetsuo Handa return timeout ? last_checked - jiffies + timeout * HZ :
286b4aa14a6STetsuo Handa MAX_SCHEDULE_TIMEOUT;
287e162b39aSMandeep Singh Baines }
288e162b39aSMandeep Singh Baines
289bbe7a10eSXiaoming Ni #ifdef CONFIG_SYSCTL
290e162b39aSMandeep Singh Baines /*
291e162b39aSMandeep Singh Baines * Process updating of timeout sysctl
292e162b39aSMandeep Singh Baines */
proc_dohung_task_timeout_secs(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)29378eb4ea2SJoel Granados static int proc_dohung_task_timeout_secs(const struct ctl_table *table, int write,
294591c32bdSBen Dooks void *buffer,
295bbe7a10eSXiaoming Ni size_t *lenp, loff_t *ppos)
296e162b39aSMandeep Singh Baines {
297e162b39aSMandeep Singh Baines int ret;
298e162b39aSMandeep Singh Baines
2998d65af78SAlexey Dobriyan ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
300e162b39aSMandeep Singh Baines
301e162b39aSMandeep Singh Baines if (ret || !write)
302e162b39aSMandeep Singh Baines goto out;
303e162b39aSMandeep Singh Baines
304e162b39aSMandeep Singh Baines wake_up_process(watchdog_task);
305e162b39aSMandeep Singh Baines
306e162b39aSMandeep Singh Baines out:
307e162b39aSMandeep Singh Baines return ret;
308e162b39aSMandeep Singh Baines }
309e162b39aSMandeep Singh Baines
310bbe7a10eSXiaoming Ni /*
311bbe7a10eSXiaoming Ni * This is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs
312bbe7a10eSXiaoming Ni * and hung_task_check_interval_secs
313bbe7a10eSXiaoming Ni */
314bbe7a10eSXiaoming Ni static const unsigned long hung_task_timeout_max = (LONG_MAX / HZ);
3151751f872SJoel Granados static const struct ctl_table hung_task_sysctls[] = {
316bbe7a10eSXiaoming Ni #ifdef CONFIG_SMP
317bbe7a10eSXiaoming Ni {
318bbe7a10eSXiaoming Ni .procname = "hung_task_all_cpu_backtrace",
319bbe7a10eSXiaoming Ni .data = &sysctl_hung_task_all_cpu_backtrace,
320bbe7a10eSXiaoming Ni .maxlen = sizeof(int),
321bbe7a10eSXiaoming Ni .mode = 0644,
322bbe7a10eSXiaoming Ni .proc_handler = proc_dointvec_minmax,
323bbe7a10eSXiaoming Ni .extra1 = SYSCTL_ZERO,
324bbe7a10eSXiaoming Ni .extra2 = SYSCTL_ONE,
325bbe7a10eSXiaoming Ni },
326bbe7a10eSXiaoming Ni #endif /* CONFIG_SMP */
327bbe7a10eSXiaoming Ni {
328bbe7a10eSXiaoming Ni .procname = "hung_task_panic",
329bbe7a10eSXiaoming Ni .data = &sysctl_hung_task_panic,
330bbe7a10eSXiaoming Ni .maxlen = sizeof(int),
331bbe7a10eSXiaoming Ni .mode = 0644,
332bbe7a10eSXiaoming Ni .proc_handler = proc_dointvec_minmax,
333bbe7a10eSXiaoming Ni .extra1 = SYSCTL_ZERO,
334bbe7a10eSXiaoming Ni .extra2 = SYSCTL_ONE,
335bbe7a10eSXiaoming Ni },
336bbe7a10eSXiaoming Ni {
337bbe7a10eSXiaoming Ni .procname = "hung_task_check_count",
338bbe7a10eSXiaoming Ni .data = &sysctl_hung_task_check_count,
339bbe7a10eSXiaoming Ni .maxlen = sizeof(int),
340bbe7a10eSXiaoming Ni .mode = 0644,
341bbe7a10eSXiaoming Ni .proc_handler = proc_dointvec_minmax,
342bbe7a10eSXiaoming Ni .extra1 = SYSCTL_ZERO,
343bbe7a10eSXiaoming Ni },
344bbe7a10eSXiaoming Ni {
345bbe7a10eSXiaoming Ni .procname = "hung_task_timeout_secs",
346bbe7a10eSXiaoming Ni .data = &sysctl_hung_task_timeout_secs,
347bbe7a10eSXiaoming Ni .maxlen = sizeof(unsigned long),
348bbe7a10eSXiaoming Ni .mode = 0644,
349bbe7a10eSXiaoming Ni .proc_handler = proc_dohung_task_timeout_secs,
350bbe7a10eSXiaoming Ni .extra2 = (void *)&hung_task_timeout_max,
351bbe7a10eSXiaoming Ni },
352bbe7a10eSXiaoming Ni {
353bbe7a10eSXiaoming Ni .procname = "hung_task_check_interval_secs",
354bbe7a10eSXiaoming Ni .data = &sysctl_hung_task_check_interval_secs,
355bbe7a10eSXiaoming Ni .maxlen = sizeof(unsigned long),
356bbe7a10eSXiaoming Ni .mode = 0644,
357bbe7a10eSXiaoming Ni .proc_handler = proc_dohung_task_timeout_secs,
358bbe7a10eSXiaoming Ni .extra2 = (void *)&hung_task_timeout_max,
359bbe7a10eSXiaoming Ni },
360bbe7a10eSXiaoming Ni {
361bbe7a10eSXiaoming Ni .procname = "hung_task_warnings",
362bbe7a10eSXiaoming Ni .data = &sysctl_hung_task_warnings,
363bbe7a10eSXiaoming Ni .maxlen = sizeof(int),
364bbe7a10eSXiaoming Ni .mode = 0644,
365bbe7a10eSXiaoming Ni .proc_handler = proc_dointvec_minmax,
366bbe7a10eSXiaoming Ni .extra1 = SYSCTL_NEG_ONE,
367bbe7a10eSXiaoming Ni },
36803ecb24dSLance Yang {
36903ecb24dSLance Yang .procname = "hung_task_detect_count",
37003ecb24dSLance Yang .data = &sysctl_hung_task_detect_count,
37103ecb24dSLance Yang .maxlen = sizeof(unsigned long),
37203ecb24dSLance Yang .mode = 0444,
37303ecb24dSLance Yang .proc_handler = proc_doulongvec_minmax,
37403ecb24dSLance Yang },
375bbe7a10eSXiaoming Ni };
376bbe7a10eSXiaoming Ni
hung_task_sysctl_init(void)377bbe7a10eSXiaoming Ni static void __init hung_task_sysctl_init(void)
378bbe7a10eSXiaoming Ni {
379bbe7a10eSXiaoming Ni register_sysctl_init("kernel", hung_task_sysctls);
380bbe7a10eSXiaoming Ni }
381bbe7a10eSXiaoming Ni #else
382bbe7a10eSXiaoming Ni #define hung_task_sysctl_init() do { } while (0)
383bbe7a10eSXiaoming Ni #endif /* CONFIG_SYSCTL */
384bbe7a10eSXiaoming Ni
385bbe7a10eSXiaoming Ni
3868b414521SMarcelo Tosatti static atomic_t reset_hung_task = ATOMIC_INIT(0);
3878b414521SMarcelo Tosatti
reset_hung_task_detector(void)3888b414521SMarcelo Tosatti void reset_hung_task_detector(void)
3898b414521SMarcelo Tosatti {
3908b414521SMarcelo Tosatti atomic_set(&reset_hung_task, 1);
3918b414521SMarcelo Tosatti }
3928b414521SMarcelo Tosatti EXPORT_SYMBOL_GPL(reset_hung_task_detector);
3938b414521SMarcelo Tosatti
394a1c6ca3cSVitaly Kuznetsov static bool hung_detector_suspended;
395a1c6ca3cSVitaly Kuznetsov
hungtask_pm_notify(struct notifier_block * self,unsigned long action,void * hcpu)396a1c6ca3cSVitaly Kuznetsov static int hungtask_pm_notify(struct notifier_block *self,
397a1c6ca3cSVitaly Kuznetsov unsigned long action, void *hcpu)
398a1c6ca3cSVitaly Kuznetsov {
399a1c6ca3cSVitaly Kuznetsov switch (action) {
400a1c6ca3cSVitaly Kuznetsov case PM_SUSPEND_PREPARE:
401a1c6ca3cSVitaly Kuznetsov case PM_HIBERNATION_PREPARE:
402a1c6ca3cSVitaly Kuznetsov case PM_RESTORE_PREPARE:
403a1c6ca3cSVitaly Kuznetsov hung_detector_suspended = true;
404a1c6ca3cSVitaly Kuznetsov break;
405a1c6ca3cSVitaly Kuznetsov case PM_POST_SUSPEND:
406a1c6ca3cSVitaly Kuznetsov case PM_POST_HIBERNATION:
407a1c6ca3cSVitaly Kuznetsov case PM_POST_RESTORE:
408a1c6ca3cSVitaly Kuznetsov hung_detector_suspended = false;
409a1c6ca3cSVitaly Kuznetsov break;
410a1c6ca3cSVitaly Kuznetsov default:
411a1c6ca3cSVitaly Kuznetsov break;
412a1c6ca3cSVitaly Kuznetsov }
413a1c6ca3cSVitaly Kuznetsov return NOTIFY_OK;
414a1c6ca3cSVitaly Kuznetsov }
415a1c6ca3cSVitaly Kuznetsov
416e162b39aSMandeep Singh Baines /*
417e162b39aSMandeep Singh Baines * kthread which checks for tasks stuck in D state
418e162b39aSMandeep Singh Baines */
watchdog(void * dummy)419e162b39aSMandeep Singh Baines static int watchdog(void *dummy)
420e162b39aSMandeep Singh Baines {
421b4aa14a6STetsuo Handa unsigned long hung_last_checked = jiffies;
422b4aa14a6STetsuo Handa
423e162b39aSMandeep Singh Baines set_user_nice(current, 0);
424e162b39aSMandeep Singh Baines
425e162b39aSMandeep Singh Baines for ( ; ; ) {
42617406b82SMandeep Singh Baines unsigned long timeout = sysctl_hung_task_timeout_secs;
427a2e51445SDmitry Vyukov unsigned long interval = sysctl_hung_task_check_interval_secs;
428a2e51445SDmitry Vyukov long t;
429603a148fSMandeep Singh Baines
430a2e51445SDmitry Vyukov if (interval == 0)
431a2e51445SDmitry Vyukov interval = timeout;
432a2e51445SDmitry Vyukov interval = min_t(unsigned long, interval, timeout);
433a2e51445SDmitry Vyukov t = hung_timeout_jiffies(hung_last_checked, interval);
434b4aa14a6STetsuo Handa if (t <= 0) {
435a1c6ca3cSVitaly Kuznetsov if (!atomic_xchg(&reset_hung_task, 0) &&
436a1c6ca3cSVitaly Kuznetsov !hung_detector_suspended)
437603a148fSMandeep Singh Baines check_hung_uninterruptible_tasks(timeout);
438b4aa14a6STetsuo Handa hung_last_checked = jiffies;
439b4aa14a6STetsuo Handa continue;
440b4aa14a6STetsuo Handa }
441b4aa14a6STetsuo Handa schedule_timeout_interruptible(t);
442e162b39aSMandeep Singh Baines }
443e162b39aSMandeep Singh Baines
444e162b39aSMandeep Singh Baines return 0;
445e162b39aSMandeep Singh Baines }
446e162b39aSMandeep Singh Baines
hung_task_init(void)447e162b39aSMandeep Singh Baines static int __init hung_task_init(void)
448e162b39aSMandeep Singh Baines {
449e162b39aSMandeep Singh Baines atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
450a1c6ca3cSVitaly Kuznetsov
451a1c6ca3cSVitaly Kuznetsov /* Disable hung task detector on suspend */
452a1c6ca3cSVitaly Kuznetsov pm_notifier(hungtask_pm_notify, 0);
453a1c6ca3cSVitaly Kuznetsov
454e162b39aSMandeep Singh Baines watchdog_task = kthread_run(watchdog, NULL, "khungtaskd");
455bbe7a10eSXiaoming Ni hung_task_sysctl_init();
456e162b39aSMandeep Singh Baines
457e162b39aSMandeep Singh Baines return 0;
458e162b39aSMandeep Singh Baines }
459c96d6660SPaul Gortmaker subsys_initcall(hung_task_init);
460