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 <quic_snimmala@quicinc.com>
This commit is contained in:
Sai Harshini Nimmala 2022-01-24 20:04:49 -08:00 committed by Rishabh Bhatnagar
parent a63fa747f0
commit e27237ebec
3 changed files with 84 additions and 0 deletions

View File

@ -4,6 +4,7 @@
*/
#include "walt.h"
#include <trace/hooks/sched.h>
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,
},
{ }
};

View File

@ -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)

View File

@ -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)