summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/fair.c26
-rw-r--r--kernel/sysctl.c16
2 files changed, 42 insertions, 0 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 98740228ed32..1da6091b54f3 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -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;
@@ -750,6 +756,25 @@ static void update_curr_fair(struct rq *rq)
}
#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);
+ }
+}
+
static inline void
update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
@@ -780,6 +805,7 @@ update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se)
return;
}
trace_sched_stat_wait(p, delta);
+ check_for_high_latency(p, delta >> 10);
}
se->statistics.wait_max = max(se->statistics.wait_max, delta);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 16e465103020..188c7fabeec0 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -593,6 +593,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",