Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab9e1373 authored by Joonwoo Park's avatar Joonwoo Park Committed by Matt Wagantall
Browse files

sched: warn/panic upon excessive scheduling latency



Add new tunables /proc/sys/kernel/sched_latency_warn_threshold_us and
/proc/sys/kernel/sched_latency_panic_threshold_us to warn or panic for the
cases that tasks are runnable but not scheduled more than configured time.

This helps to find out unacceptably high scheduling latency more easily.

Change-Id: If077aba6211062cf26ee289970c5abcd1c218c82
Signed-off-by: default avatarJoonwoo Park <joonwoop@codeaurora.org>
parent 1fdacc2a
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -147,6 +147,15 @@ this file correlating for that process to:
     2) time spent waiting on a runqueue
     3) # of timeslices run on this cpu

/proc/sys/kernel/{sched_latency_warn_threshold_us,sched_latency_panic_threshold_us}
----------------
schedstats provides procfs nodes /proc/sys/kernel/sched_latency_warn_threshold_us
and /proc/sys/kernel/sched_latency_panic_threshold_us.  These can be configured
to detect unreasonably high scheduling latency.
Set sched_latency_warn_threshold_us or sched_latency_panic_threshold_us with
non-zero threshold to warn or panic system when scheduling latency higher than
configured threshold is detected.  Default is 0 (disabled) for both.

A program could be easily written to make use of these extra fields to
report on how well a particular process or set of processes is faring
under the scheduler's policies.  A simple version of such a program is
+5 −0
Original line number Diff line number Diff line
@@ -142,6 +142,11 @@ extern unsigned int sysctl_sched_cfs_bandwidth_slice;
extern unsigned int sysctl_sched_autogroup_enabled;
#endif

#ifdef CONFIG_SCHEDSTATS
extern unsigned int sysctl_sched_latency_panic_threshold;
extern unsigned int sysctl_sched_latency_warn_threshold;
#endif

extern int sched_rr_timeslice;

extern int sched_rr_handler(struct ctl_table *table, int write,
+38 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <linux/mempolicy.h>
#include <linux/migrate.h>
#include <linux/task_work.h>
#include <linux/ratelimit.h>

#include <trace/events/sched.h>

@@ -122,6 +123,11 @@ unsigned int __read_mostly sysctl_sched_shares_window = 10000000UL;
unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL;
#endif

#ifdef CONFIG_SCHEDSTATS
unsigned int sysctl_sched_latency_panic_threshold;
unsigned int sysctl_sched_latency_warn_threshold;
#endif /* CONFIG_SCHEDSTATS */

static inline void update_load_add(struct load_weight *lw, unsigned long inc)
{
	lw->weight += inc;
@@ -767,6 +773,31 @@ static void update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se,
		update_stats_wait_start(cfs_rq, se, migrating);
}

#ifdef CONFIG_SCHEDSTATS
static inline void check_for_high_latency(struct task_struct *p, u64 latency_us)
{
	int do_warn, do_panic;
	const char *fmt = "excessive latency comm=%s pid=%d latency=%llu(us)\n";
	static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
				      DEFAULT_RATELIMIT_BURST);

	do_warn = (sysctl_sched_latency_warn_threshold &&
		   latency_us > sysctl_sched_latency_warn_threshold);
	do_panic = (sysctl_sched_latency_panic_threshold &&
		    latency_us > sysctl_sched_latency_panic_threshold);
	if (unlikely(do_panic || (do_warn && __ratelimit(&rs)))) {
		if (do_panic)
			panic(fmt, p->comm, p->pid, latency_us);
		else
			printk_deferred(fmt, p->comm, p->pid, latency_us);
	}
}
#else
static inline void check_for_high_latency(struct task_struct *p, u64 latency)
{
}
#endif

static void
update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se,
		      bool migrating)
@@ -785,8 +816,13 @@ update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se,
			rq_clock(rq_of(cfs_rq)) - se->statistics.wait_start);
#ifdef CONFIG_SCHEDSTATS
	if (entity_is_task(se)) {
		trace_sched_stat_wait(task_of(se),
			rq_clock(rq_of(cfs_rq)) - se->statistics.wait_start);
		u64 delta;

		delta = rq_clock(rq_of(cfs_rq)) - se->statistics.wait_start;
		trace_sched_stat_wait(task_of(se), delta);

		delta = delta >> 10;
		check_for_high_latency(task_of(se), delta);
	}
#endif
	schedstat_set(se->statistics.wait_start, 0);
+16 −0
Original line number Diff line number Diff line
@@ -603,6 +603,22 @@ static struct ctl_table kern_table[] = {
		.extra1		= &one,
	},
#endif
#ifdef CONFIG_SCHEDSTATS
	{
		.procname	= "sched_latency_panic_threshold_us",
		.data		= &sysctl_sched_latency_panic_threshold,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
	},
	{
		.procname	= "sched_latency_warn_threshold_us",
		.data		= &sysctl_sched_latency_warn_threshold,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
	},
#endif
#ifdef CONFIG_PROVE_LOCKING
	{
		.procname	= "prove_locking",