sched: add scheduling latency tracking procfs node

Add a new procfs node /proc/sys/kernel/sched_max_latency_us to track the
worst scheduling latency.  It provides easier way to identify maximum
scheduling latency seen across the CPUs.

Change-Id: I6e435bbf825c0a4dff2eded4a1256fb93f108d0e
Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
This commit is contained in:
Joonwoo Park 2015-03-02 11:25:17 -08:00
parent 4653e0549d
commit 32851d8550
4 changed files with 80 additions and 0 deletions

View File

@ -156,6 +156,13 @@ 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.
/proc/sys/kernel/sched_max_latency_us
----------------
/proc/sys/kernel/sched_max_latency_us shows the maximum scheduling latency seen
accross the CPUs. The file shows the maximum latency seen in microseconds along
with the cpu number or cpu id and the task that incurred maximum latency on that
cpu. The maximum latency can be reset by writing any value to the file.
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

View File

@ -143,6 +143,10 @@ extern unsigned int sysctl_sched_autogroup_enabled;
#ifdef CONFIG_SCHEDSTATS
extern unsigned int sysctl_sched_latency_panic_threshold;
extern unsigned int sysctl_sched_latency_warn_threshold;
extern int sched_max_latency_sysctl(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp,
loff_t *ppos);
#endif
extern int sched_rr_timeslice;

View File

@ -125,6 +125,14 @@ unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL;
#ifdef CONFIG_SCHEDSTATS
unsigned int sysctl_sched_latency_panic_threshold;
unsigned int sysctl_sched_latency_warn_threshold;
struct sched_max_latency {
unsigned int latency_us;
char comm[TASK_COMM_LEN];
pid_t pid;
};
static DEFINE_PER_CPU(struct sched_max_latency, sched_max_latency);
#endif /* CONFIG_SCHEDSTATS */
/*
@ -758,6 +766,54 @@ static void update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se,
}
#ifdef CONFIG_SCHEDSTATS
int sched_max_latency_sysctl(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int ret = 0;
int i, cpu = nr_cpu_ids;
char msg[256];
unsigned long flags;
struct rq *rq;
struct sched_max_latency max, *lat;
if (!write) {
max.latency_us = 0;
for_each_possible_cpu(i) {
rq = cpu_rq(i);
raw_spin_lock_irqsave(&rq->lock, flags);
lat = &per_cpu(sched_max_latency, i);
if (max.latency_us < lat->latency_us) {
max = *lat;
cpu = i;
}
raw_spin_unlock_irqrestore(&rq->lock, flags);
}
if (cpu != nr_cpu_ids) {
table->maxlen =
snprintf(msg, sizeof(msg),
"cpu%d comm=%s pid=%u latency=%u(us)",
cpu, max.comm, max.pid, max.latency_us);
table->data = msg;
ret = proc_dostring(table, write, buffer, lenp, ppos);
}
} else {
for_each_possible_cpu(i) {
rq = cpu_rq(i);
raw_spin_lock_irqsave(&rq->lock, flags);
memset(&per_cpu(sched_max_latency, i), 0,
sizeof(struct sched_max_latency));
raw_spin_unlock_irqrestore(&rq->lock, flags);
}
}
return ret;
}
static inline void check_for_high_latency(struct task_struct *p, u64 latency_us)
{
int do_warn, do_panic;
@ -800,11 +856,19 @@ update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se,
#ifdef CONFIG_SCHEDSTATS
if (entity_is_task(se)) {
u64 delta;
struct sched_max_latency *max;
delta = rq_of(cfs_rq)->clock - se->statistics.wait_start;
trace_sched_stat_wait(task_of(se), delta);
delta = delta >> 10;
max = this_cpu_ptr(&sched_max_latency);
if (max->latency_us < delta) {
max->latency_us = delta;
max->pid = task_of(se)->pid;
memcpy(max->comm, task_of(se)->comm, TASK_COMM_LEN);
}
check_for_high_latency(task_of(se), delta);
}
#endif

View File

@ -618,6 +618,11 @@ static struct ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
},
{
.procname = "sched_max_latency_us",
.mode = 0644,
.proc_handler = sched_max_latency_sysctl,
},
#endif
#ifdef CONFIG_PROVE_LOCKING
{