linux/kernel/hung_task.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Detect Hung Task
 *
 * kernel/hung_task.c - kernel thread for detecting tasks stuck in D state
 *
 */

#include <linux/mm.h>
#include <linux/cpu.h>
#include <linux/nmi.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/lockdep.h>
#include <linux/export.h>
#include <linux/panic_notifier.h>
#include <linux/sysctl.h>
#include <linux/suspend.h>
#include <linux/utsname.h>
#include <linux/sched/signal.h>
#include <linux/sched/debug.h>
#include <linux/sched/sysctl.h>

#include <trace/events/sched.h>

/*
 * The number of tasks checked:
 */
static int __read_mostly sysctl_hung_task_check_count =;

/*
 * Limit number of tasks checked in a batch.
 *
 * This value controls the preemptibility of khungtaskd since preemption
 * is disabled during the critical section. It also controls the size of
 * the RCU grace period. So it needs to be upper-bound.
 */
#define HUNG_TASK_LOCK_BREAK

/*
 * Zero means infinite timeout - no checking done:
 */
unsigned long __read_mostly sysctl_hung_task_timeout_secs =;
EXPORT_SYMBOL_GPL();

/*
 * Zero (default value) means use sysctl_hung_task_timeout_secs:
 */
static unsigned long __read_mostly sysctl_hung_task_check_interval_secs;

static int __read_mostly sysctl_hung_task_warnings =;

static int __read_mostly did_panic;
static bool hung_task_show_lock;
static bool hung_task_call_panic;
static bool hung_task_show_all_bt;

static struct task_struct *watchdog_task;

#ifdef CONFIG_SMP
/*
 * Should we dump all CPUs backtraces in a hung task event?
 * Defaults to 0, can be changed via sysctl.
 */
static unsigned int __read_mostly sysctl_hung_task_all_cpu_backtrace;
#else
#define sysctl_hung_task_all_cpu_backtrace
#endif /* CONFIG_SMP */

/*
 * Should we panic (and reboot, if panic_timeout= is set) when a
 * hung task is detected:
 */
static unsigned int __read_mostly sysctl_hung_task_panic =
	IS_ENABLED();

static int
hung_task_panic(struct notifier_block *this, unsigned long event, void *ptr)
{}

static struct notifier_block panic_block =;

static void check_hung_task(struct task_struct *t, unsigned long timeout)
{}

/*
 * To avoid extending the RCU grace period for an unbounded amount of time,
 * periodically exit the critical section and enter a new one.
 *
 * For preemptible RCU it is sufficient to call rcu_read_unlock in order
 * to exit the grace period. For classic RCU, a reschedule is required.
 */
static bool rcu_lock_break(struct task_struct *g, struct task_struct *t)
{}

/*
 * 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(unsigned long timeout)
{}

static long hung_timeout_jiffies(unsigned long last_checked,
				 unsigned long timeout)
{}

#ifdef CONFIG_SYSCTL
/*
 * Process updating of timeout sysctl
 */
static int proc_dohung_task_timeout_secs(const struct ctl_table *table, int write,
				  void *buffer,
				  size_t *lenp, loff_t *ppos)
{}

/*
 * This is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs
 * and hung_task_check_interval_secs
 */
static const unsigned long hung_task_timeout_max =;
static struct ctl_table hung_task_sysctls[] =;

static void __init hung_task_sysctl_init(void)
{}
#else
#define hung_task_sysctl_init
#endif /* CONFIG_SYSCTL */


static atomic_t reset_hung_task =;

void reset_hung_task_detector(void)
{}
EXPORT_SYMBOL_GPL();

static bool hung_detector_suspended;

static int hungtask_pm_notify(struct notifier_block *self,
			      unsigned long action, void *hcpu)
{}

/*
 * kthread which checks for tasks stuck in D state
 */
static int watchdog(void *dummy)
{}

static int __init hung_task_init(void)
{}
subsys_initcall(hung_task_init);