From e27237ebec77f798e08f0facd80fa7ad4fe8047c Mon Sep 17 00:00:00 2001 From: Sai Harshini Nimmala Date: Mon, 24 Jan 2022 20:04:49 -0800 Subject: [PATCH] sched/walt: Handle long running RT tasks Detect long running RT tasks by tapping into the scheduler_tick tracepoint, so that task can be detected while it is actively running on the CPU and cause panic on the same CPU to get relevant stack information for debug purposes. Change-Id: I205a5512ba61e1a92d64659b723e661e11c39dd1 Signed-off-by: Sai Harshini Nimmala --- kernel/sched/walt/sysctl.c | 12 +++++++ kernel/sched/walt/walt.h | 10 ++++++ kernel/sched/walt/walt_rt.c | 62 +++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/kernel/sched/walt/sysctl.c b/kernel/sched/walt/sysctl.c index f52aa1b90f76..1f2ede153895 100644 --- a/kernel/sched/walt/sysctl.c +++ b/kernel/sched/walt/sysctl.c @@ -4,6 +4,7 @@ */ #include "walt.h" +#include static int neg_three = -3; static int three = 3; @@ -15,6 +16,7 @@ static int __maybe_unused two = 2; static int __maybe_unused four = 4; static int one_hundred = 100; static int one_thousand = 1000; +static int two_thousand = 2000; /* * CFS task prio range is [100 ... 139] @@ -67,6 +69,7 @@ unsigned int sysctl_sched_suppress_region2; unsigned int sysctl_sched_skip_sp_newly_idle_lb = 1; unsigned int sysctl_sched_hyst_min_coloc_ns = 80000000; unsigned int sysctl_sched_asymcap_boost; +unsigned int sysctl_sched_long_running_rt_task_ms = 1200; /* range is [1 .. INT_MAX] */ static int sysctl_task_read_pid = 1; @@ -869,6 +872,15 @@ struct ctl_table walt_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, }, + { + .procname = "sched_long_running_rt_task_ms", + .data = &sysctl_sched_long_running_rt_task_ms, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = sched_long_running_rt_task_ms_handler, + .extra1 = SYSCTL_ZERO, + .extra2 = &two_thousand, + }, { } }; diff --git a/kernel/sched/walt/walt.h b/kernel/sched/walt/walt.h index 96ba533bc618..ba34a2eea0d9 100644 --- a/kernel/sched/walt/walt.h +++ b/kernel/sched/walt/walt.h @@ -207,6 +207,7 @@ extern unsigned int sysctl_sched_boost_on_input; extern unsigned int sysctl_sched_user_hint; extern unsigned int sysctl_sched_conservative_pl; extern unsigned int sysctl_sched_hyst_min_coloc_ns; +extern unsigned int sysctl_sched_long_running_rt_task_ms; #define WALT_MANY_WAKEUP_DEFAULT 1000 extern unsigned int sysctl_sched_many_wakeup_threshold; @@ -878,6 +879,15 @@ static inline bool walt_fair_task(struct task_struct *p) return p->prio >= MAX_RT_PRIO && !is_idle_task(p); } +extern void rt_task_arrival_marker(void *unused, bool preempt, + struct task_struct *prev, struct task_struct *next); + +extern void long_running_rt_task_notifier(void *unused, struct rq *rq); + +extern int sched_long_running_rt_task_ms_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos); + #define WALT_MVP_SLICE 3000000U #define WALT_MVP_LIMIT (4 * WALT_MVP_SLICE) diff --git a/kernel/sched/walt/walt_rt.c b/kernel/sched/walt/walt_rt.c index 594990a18291..c8c8a5f690a7 100644 --- a/kernel/sched/walt/walt_rt.c +++ b/kernel/sched/walt/walt_rt.c @@ -8,7 +8,69 @@ #include "walt.h" #include "trace.h" +#define MSEC_TO_NSEC (1000 * 1000) + static DEFINE_PER_CPU(cpumask_var_t, walt_local_cpu_mask); +static DEFINE_PER_CPU(u64, rt_task_arrival_time); +static bool long_running_rt_task_trace_rgstrd; + +void rt_task_arrival_marker(void *unused, bool preempt, + struct task_struct *prev, struct task_struct *next) +{ + unsigned int cpu = raw_smp_processor_id(); + + if (rt_task(next)) + per_cpu(rt_task_arrival_time, cpu) = rq_clock_task(this_rq()); + else + per_cpu(rt_task_arrival_time, cpu) = 0; +} + +void long_running_rt_task_notifier(void *unused, struct rq *rq) +{ + struct task_struct *curr = rq->curr; + unsigned int cpu = raw_smp_processor_id(); + + if (!sysctl_sched_long_running_rt_task_ms) + return; + + if (!per_cpu(rt_task_arrival_time, cpu)) + return; + + if (rq_clock_task(rq) - + per_cpu(rt_task_arrival_time, cpu) + > sysctl_sched_long_running_rt_task_ms * MSEC_TO_NSEC) { + printk_deferred("RT task %s (%d) runtime > %u now=%llu task arrival time=%llu runtime=%llu\n", + curr->comm, curr->pid, + sysctl_sched_long_running_rt_task_ms * MSEC_TO_NSEC, + rq_clock_task(rq), + per_cpu(rt_task_arrival_time, cpu), + rq_clock_task(rq) - + per_cpu(rt_task_arrival_time, cpu)); + BUG(); + } +} + +int sched_long_running_rt_task_ms_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int ret; + static DEFINE_MUTEX(mutex); + + mutex_lock(&mutex); + + ret = proc_douintvec_minmax(table, write, buffer, lenp, ppos); + + if (write && !long_running_rt_task_trace_rgstrd) { + register_trace_sched_switch(rt_task_arrival_marker, NULL); + register_trace_android_vh_scheduler_tick(long_running_rt_task_notifier, NULL); + long_running_rt_task_trace_rgstrd = true; + } + + mutex_unlock(&mutex); + + return ret; +} static void walt_rt_energy_aware_wake_cpu(struct task_struct *task, struct cpumask *lowest_mask, int ret, int *best_cpu)