Ignore RT throttling if rq->rt tasks are the only running tasks in the rq
PATCH v2 1/1 Ignore RT throttling if rq->rt tasks are the only running tasks in the rq
The current throttling logic always skips RT class if rq->rt is throttled. It doesn't handle the special case when RT tasks are the only running tasks in the rq. So it's possible CPU picks idle task up when RTs are available.
This patch aims to avoid the above situation. The modified _pick_next_task_rt() looks at the number of total rq->rt tasks(with the sum of all child rt_rq's) and compares it with the number of all running tasks of the rq. If they are equal then scheduler picks the highest rq->rt task (children are considered too).
Later, the first unthrottled rq_rt will replace this task. In this moment the prolongated rt_rq receives rt_time equal to rt_runtime. The case of appearance of fair task is handled in check_preempt_curr() and check_class_changed functions.
The patch changes the logic of pick_rt_task() and pick_next_highest_task_rt(). Now the negative cpu always makes task "picked". But there are no another users of this posibility and nobody is touched by this change.
--- kernel/sched/core.c | 13 ++++- kernel/sched/rt.c | 148 +++++++++++++++++++++++++++++++++++--------------- kernel/sched/sched.h | 3 +- 3 files changed, 118 insertions(+), 46 deletions(-)
kernel/sched/core.c +11 -2
@@ -893,6 +893,8 @@ static inline void check_class_changed(struct rq *rq, struct task_struct *p,if (prev_class->switched_from) prev_class->switched_from (rq, p); p->sched_class->switched_to (rq, p); +if (p->on_rq &&unlikely (rq->extended_class)) +resched_task (rq->curr); }else if (oldprio != p->prio) p->sched_class->prio_changed (rq, p, oldprio); }
@@ -901,7 +903,9 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags) {const struct sched_class *class; -if (p->sched_class == rq->curr->sched_class) { +if (unlikely (rq->extended_class)) { +resched_task (rq->curr); + }else if (p->sched_class == rq->curr->sched_class) { rq->curr->sched_class->check_preempt_curr (rq, p, flags); }else {for_each_class (class) {
@@ -2771,6 +2775,7 @@ static void put_prev_task(struct rq *rq, struct task_struct *prev)if (prev->on_rq || rq->skip_clock_update <0 )update_rq_clock (rq); prev->sched_class->put_prev_task (rq, prev); + rq->extended_class =NULL ; }/*
@@ -6888,6 +6893,7 @@ void __init sched_init(void) rq->calc_load_update = jiffies +LOAD_FREQ ;init_cfs_rq (&rq->cfs);init_rt_rq (&rq->rt, rq); + rq->extended_class =NULL ;#ifdef CONFIG_FAIR_GROUP_SCHED root_task_group.shares =ROOT_TASK_GROUP_LOAD ;INIT_LIST_HEAD (&rq->leaf_cfs_rq_list);
@@ -7250,8 +7256,11 @@ void sched_move_task(struct task_struct *tsk)if (unlikely (running)) tsk->sched_class->set_curr_task (rq); -if (on_rq) +if (on_rq) {enqueue_task (rq, tsk,0 ); +if (unlikely (rq->extended_class)) +resched_task (rq->curr); + }task_rq_unlock (rq, tsk, &flags); }
kernel/sched/rt.c +105 -43
264 lines not on this page · raw message
kernel/sched/sched.h +2 -1
@@ -294,6 +294,7 @@ static inline int rt_bandwidth_enabled(void)struct rt_rq {struct rt_prio_array active;unsigned int rt_nr_running; +unsigned long rt_nr_total; #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED struct { int curr; /* highest queued rt task prio */
@@ -304,7 +305,6 @@ struct rt_rq {#endif #ifdef CONFIG_SMP unsigned long rt_nr_migratory; -unsigned long rt_nr_total;int overloaded;struct plist_head pushable_tasks;#endif
@@ -396,6 +396,7 @@ struct rq {#ifdef CONFIG_RT_GROUP_SCHED struct list_head leaf_rt_rq_list;#endif +const struct sched_class *extended_class;/* * This is part of a global counter where only the total sum