Skip to contentSkip to conversation

Ignore RT throttling if rq->rt tasks are the only running tasks in the rq

PATCH New Kirill Tkhai 1 participant 1 message Nov 17, 2012 Scheduler

lore
Share & tools
lore
#0 lore raw

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.

CC Steven Rostedt <[email protected]>
CC Ingo Molnar <[email protected]>
CC Peter Zijlstra <[email protected]>
---
 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
index c33495b..a79600b 100644
@@ -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
index bb9475c..73b86c0 100644
@@ -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