Skip to content

Commit 371bf42

Browse files
vingu-linaroIngo Molnar
authored andcommitted
sched/rt: Add rt_rq utilization tracking
schedutil governor relies on cfs_rq's util_avg to choose the OPP when CFS tasks are running. When the CPU is overloaded by CFS and RT tasks, CFS tasks are preempted by RT tasks and in this case util_avg reflects the remaining capacity but not what CFS want to use. In such case, schedutil can select a lower OPP whereas the CPU is overloaded. In order to have a more accurate view of the utilization of the CPU, we track the utilization of RT tasks. Only util_avg is correctly tracked but not load_avg and runnable_load_avg which are useless for rt_rq. rt_rq uses rq_clock_task and cfs_rq uses cfs_rq_clock_task but they are the same at the root group level, so the PELT windows of the util_sum are aligned. Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Morten.Rasmussen@arm.com Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: claudio@evidence.eu.com Cc: daniel.lezcano@linaro.org Cc: dietmar.eggemann@arm.com Cc: joel@joelfernandes.org Cc: juri.lelli@redhat.com Cc: luca.abeni@santannapisa.it Cc: patrick.bellasi@arm.com Cc: quentin.perret@arm.com Cc: rjw@rjwysocki.net Cc: valentin.schneider@arm.com Cc: viresh.kumar@linaro.org Link: http://lkml.kernel.org/r/1530200714-4504-3-git-send-email-vincent.guittot@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent c079629 commit 371bf42

File tree

5 files changed

+66
-1
lines changed

5 files changed

+66
-1
lines changed

kernel/sched/fair.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7290,6 +7290,14 @@ static inline bool cfs_rq_has_blocked(struct cfs_rq *cfs_rq)
72907290
return false;
72917291
}
72927292

7293+
static inline bool rt_rq_has_blocked(struct rq *rq)
7294+
{
7295+
if (READ_ONCE(rq->avg_rt.util_avg))
7296+
return true;
7297+
7298+
return false;
7299+
}
7300+
72937301
#ifdef CONFIG_FAIR_GROUP_SCHED
72947302

72957303
static inline bool cfs_rq_is_decayed(struct cfs_rq *cfs_rq)
@@ -7349,6 +7357,10 @@ static void update_blocked_averages(int cpu)
73497357
if (cfs_rq_has_blocked(cfs_rq))
73507358
done = false;
73517359
}
7360+
update_rt_rq_load_avg(rq_clock_task(rq), rq, 0);
7361+
/* Don't need periodic decay once load/util_avg are null */
7362+
if (rt_rq_has_blocked(rq))
7363+
done = false;
73527364

73537365
#ifdef CONFIG_NO_HZ_COMMON
73547366
rq->last_blocked_load_update_tick = jiffies;
@@ -7414,9 +7426,10 @@ static inline void update_blocked_averages(int cpu)
74147426
rq_lock_irqsave(rq, &rf);
74157427
update_rq_clock(rq);
74167428
update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq);
7429+
update_rt_rq_load_avg(rq_clock_task(rq), rq, 0);
74177430
#ifdef CONFIG_NO_HZ_COMMON
74187431
rq->last_blocked_load_update_tick = jiffies;
7419-
if (!cfs_rq_has_blocked(cfs_rq))
7432+
if (!cfs_rq_has_blocked(cfs_rq) && !rt_rq_has_blocked(rq))
74207433
rq->has_blocked_load = 0;
74217434
#endif
74227435
rq_unlock_irqrestore(rq, &rf);

kernel/sched/pelt.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,28 @@ int __update_load_avg_cfs_rq(u64 now, int cpu, struct cfs_rq *cfs_rq)
309309

310310
return 0;
311311
}
312+
313+
/*
314+
* rt_rq:
315+
*
316+
* util_sum = \Sum se->avg.util_sum but se->avg.util_sum is not tracked
317+
* util_sum = cpu_scale * load_sum
318+
* runnable_load_sum = load_sum
319+
*
320+
* load_avg and runnable_load_avg are not supported and meaningless.
321+
*
322+
*/
323+
324+
int update_rt_rq_load_avg(u64 now, struct rq *rq, int running)
325+
{
326+
if (___update_load_sum(now, rq->cpu, &rq->avg_rt,
327+
running,
328+
running,
329+
running)) {
330+
331+
___update_load_avg(&rq->avg_rt, 1, 1);
332+
return 1;
333+
}
334+
335+
return 0;
336+
}

kernel/sched/pelt.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
int __update_load_avg_blocked_se(u64 now, int cpu, struct sched_entity *se);
44
int __update_load_avg_se(u64 now, int cpu, struct cfs_rq *cfs_rq, struct sched_entity *se);
55
int __update_load_avg_cfs_rq(u64 now, int cpu, struct cfs_rq *cfs_rq);
6+
int update_rt_rq_load_avg(u64 now, struct rq *rq, int running);
67

78
/*
89
* When a task is dequeued, its estimated utilization should not be update if
@@ -38,6 +39,12 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
3839
return 0;
3940
}
4041

42+
static inline int
43+
update_rt_rq_load_avg(u64 now, struct rq *rq, int running)
44+
{
45+
return 0;
46+
}
47+
4148
#endif
4249

4350

kernel/sched/rt.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66
#include "sched.h"
77

8+
#include "pelt.h"
9+
810
int sched_rr_timeslice = RR_TIMESLICE;
911
int sysctl_sched_rr_timeslice = (MSEC_PER_SEC / HZ) * RR_TIMESLICE;
1012

@@ -1576,13 +1578,23 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
15761578

15771579
rt_queue_push_tasks(rq);
15781580

1581+
/*
1582+
* If prev task was rt, put_prev_task() has already updated the
1583+
* utilization. We only care of the case where we start to schedule a
1584+
* rt task
1585+
*/
1586+
if (rq->curr->sched_class != &rt_sched_class)
1587+
update_rt_rq_load_avg(rq_clock_task(rq), rq, 0);
1588+
15791589
return p;
15801590
}
15811591

15821592
static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
15831593
{
15841594
update_curr_rt(rq);
15851595

1596+
update_rt_rq_load_avg(rq_clock_task(rq), rq, 1);
1597+
15861598
/*
15871599
* The previous task needs to be made eligible for pushing
15881600
* if it is still active
@@ -2312,6 +2324,7 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued)
23122324
struct sched_rt_entity *rt_se = &p->rt;
23132325

23142326
update_curr_rt(rq);
2327+
update_rt_rq_load_avg(rq_clock_task(rq), rq, 1);
23152328

23162329
watchdog(rq, p);
23172330

kernel/sched/sched.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ struct rt_rq {
594594
unsigned long rt_nr_total;
595595
int overloaded;
596596
struct plist_head pushable_tasks;
597+
597598
#endif /* CONFIG_SMP */
598599
int rt_queued;
599600

@@ -854,6 +855,7 @@ struct rq {
854855

855856
u64 rt_avg;
856857
u64 age_stamp;
858+
struct sched_avg avg_rt;
857859
u64 idle_stamp;
858860
u64 avg_idle;
859861

@@ -2212,4 +2214,9 @@ static inline unsigned long cpu_util_cfs(struct rq *rq)
22122214

22132215
return util;
22142216
}
2217+
2218+
static inline unsigned long cpu_util_rt(struct rq *rq)
2219+
{
2220+
return rq->avg_rt.util_avg;
2221+
}
22152222
#endif

0 commit comments

Comments
 (0)