Subject: Make output of RT throttling more verbose
From: Carsten Emde <C.Emde@osadl.org>
Date: Tue,  9 Aug 2016 11:39:27 +0100

Make output of RT throttling more verbose.

Most of the time when a system is hit by RT throttling
activation it is evident which task is running havoc.
Sometimes, however, the culprit may be more difficult
to detect. Add some more debug output to the RT
throttling activation message for such cases.

Signed-off-by: Carsten Emde <C.Emde@osadl.org>

---
 kernel/sched/rt.c |   41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)

Index: linux-3.12.42-rt58/kernel/sched/rt.c
===================================================================
--- linux-3.12.42-rt58.orig/kernel/sched/rt.c
+++ linux-3.12.42-rt58/kernel/sched/rt.c
@@ -801,6 +801,16 @@ static inline int rt_se_prio(struct sche
 	return rt_task_of(rt_se)->prio;
 }
 
+static struct {
+	char comm[TASK_COMM_LEN];
+	int pid;
+	int cpu;
+	int prio;
+	u64 delta_exec;
+	u64 clock;
+} rt_maxdelta;
+
+
 static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)
 {
 	u64 runtime = sched_rt_runtime(rt_rq);
@@ -830,7 +840,11 @@ static int sched_rt_runtime_exceeded(str
 
 			if (!once) {
 				once = true;
-				printk_deferred("sched: RT throttling activated\n");
+				printk_deferred("sched: RT throttling activated"
+				    " max delta by %s cpu %d prio %d us %llu\n",
+				    rt_maxdelta.comm, rt_maxdelta.cpu,
+				    MAX_RT_PRIO-1 - rt_maxdelta.prio,
+				    rt_maxdelta.delta_exec >> 10);
 			}
 		} else {
 			/*
@@ -858,13 +872,14 @@ static void update_curr_rt(struct rq *rq
 {
 	struct task_struct *curr = rq->curr;
 	struct sched_rt_entity *rt_se = &curr->rt;
-	struct rt_rq *rt_rq = rt_rq_of_se(rt_se);
-	u64 delta_exec;
+	struct rt_rq *rt_rq;
+	u64 delta_exec, rq_clock;
 
 	if (curr->sched_class != &rt_sched_class)
 		return;
 
-	delta_exec = rq_clock_task(rq) - curr->se.exec_start;
+	rq_clock = rq_clock_task(rq);
+	delta_exec = rq_clock - curr->se.exec_start;
 	if (unlikely((s64)delta_exec <= 0))
 		return;
 
@@ -874,7 +889,7 @@ static void update_curr_rt(struct rq *rq
 	curr->se.sum_exec_runtime += delta_exec;
 	account_group_exec_runtime(curr, delta_exec);
 
-	curr->se.exec_start = rq_clock_task(rq);
+	curr->se.exec_start = rq_clock;
 	cpuacct_charge(curr, delta_exec);
 
 	sched_rt_avg_update(rq, delta_exec);
@@ -882,12 +897,28 @@ static void update_curr_rt(struct rq *rq
 	if (!rt_bandwidth_enabled())
 		return;
 
+	if (rq_clock > rt_maxdelta.clock + sched_rt_period(rt_rq))
+		rt_maxdelta.delta_exec = 0;
+
 	for_each_sched_rt_entity(rt_se) {
 		rt_rq = rt_rq_of_se(rt_se);
 
 		if (sched_rt_runtime(rt_rq) != RUNTIME_INF) {
 			raw_spin_lock(&rt_rq->rt_runtime_lock);
 			rt_rq->rt_time += delta_exec;
+			if (rt_maxdelta.delta_exec > 0 &&
+			    task_pid_nr(curr) == rt_maxdelta.pid &&
+			    !strcmp(rt_maxdelta.comm, curr->comm))
+				rt_maxdelta.delta_exec += delta_exec;
+			else if (delta_exec > rt_maxdelta.delta_exec) {
+				rt_maxdelta.delta_exec = delta_exec;
+				rt_maxdelta.cpu = task_cpu(curr);
+				rt_maxdelta.pid = task_pid_nr(curr);
+				rt_maxdelta.prio = curr->prio;
+				strncpy(rt_maxdelta.comm, curr->comm,
+				    sizeof(rt_maxdelta.comm));
+				rt_maxdelta.clock = rq_clock;
+			}
 			if (sched_rt_runtime_exceeded(rt_rq))
 				resched_task(curr);
 			raw_spin_unlock(&rt_rq->rt_runtime_lock);