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:
parent
4653e0549d
commit
32851d8550
|
@ -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
|
non-zero threshold to warn or panic system when scheduling latency higher than
|
||||||
configured threshold is detected. Default is 0 (disabled) for both.
|
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
|
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
|
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
|
under the scheduler's policies. A simple version of such a program is
|
||||||
|
|
|
@ -143,6 +143,10 @@ extern unsigned int sysctl_sched_autogroup_enabled;
|
||||||
#ifdef CONFIG_SCHEDSTATS
|
#ifdef CONFIG_SCHEDSTATS
|
||||||
extern unsigned int sysctl_sched_latency_panic_threshold;
|
extern unsigned int sysctl_sched_latency_panic_threshold;
|
||||||
extern unsigned int sysctl_sched_latency_warn_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
|
#endif
|
||||||
|
|
||||||
extern int sched_rr_timeslice;
|
extern int sched_rr_timeslice;
|
||||||
|
|
|
@ -125,6 +125,14 @@ unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL;
|
||||||
#ifdef CONFIG_SCHEDSTATS
|
#ifdef CONFIG_SCHEDSTATS
|
||||||
unsigned int sysctl_sched_latency_panic_threshold;
|
unsigned int sysctl_sched_latency_panic_threshold;
|
||||||
unsigned int sysctl_sched_latency_warn_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 */
|
#endif /* CONFIG_SCHEDSTATS */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -758,6 +766,54 @@ static void update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SCHEDSTATS
|
#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)
|
static inline void check_for_high_latency(struct task_struct *p, u64 latency_us)
|
||||||
{
|
{
|
||||||
int do_warn, do_panic;
|
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
|
#ifdef CONFIG_SCHEDSTATS
|
||||||
if (entity_is_task(se)) {
|
if (entity_is_task(se)) {
|
||||||
u64 delta;
|
u64 delta;
|
||||||
|
struct sched_max_latency *max;
|
||||||
|
|
||||||
delta = rq_of(cfs_rq)->clock - se->statistics.wait_start;
|
delta = rq_of(cfs_rq)->clock - se->statistics.wait_start;
|
||||||
trace_sched_stat_wait(task_of(se), delta);
|
trace_sched_stat_wait(task_of(se), delta);
|
||||||
|
|
||||||
delta = delta >> 10;
|
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);
|
check_for_high_latency(task_of(se), delta);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -618,6 +618,11 @@ static struct ctl_table kern_table[] = {
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dointvec_minmax,
|
.proc_handler = proc_dointvec_minmax,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.procname = "sched_max_latency_us",
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = sched_max_latency_sysctl,
|
||||||
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PROVE_LOCKING
|
#ifdef CONFIG_PROVE_LOCKING
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue