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)