@@ -1366,33 +1366,66 @@ out:
return cpu;
}
-static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
+static struct task_struct *peek_next_task_rt(struct rq *rq);
+
+static void check_preempt_equal_prio_common(struct rq *rq)
{
+ struct task_struct *curr = rq->curr;
+ struct task_struct *next;
+
+ /* Current can't be migrated, useless to reschedule */
+ if (curr->nr_cpus_allowed == 1 ||
+ !cpupri_find(&rq->rd->cpupri, curr, NULL))
+ return;
+
/*
- * Current can't be migrated, useless to reschedule,
- * let's hope p can move out.
+ * Can we find any task with the same priority as
+ * curr? To accomplish this, firstly requeue curr
+ * to the tail, then peek next, finally put curr
+ * back to the head if a different task was peeked.
*/
- if (rq->curr->nr_cpus_allowed == 1 ||
- !cpupri_find(&rq->rd->cpupri, rq->curr, NULL))
+ requeue_task_rt(rq, curr, 0);
+ next = peek_next_task_rt(rq);
+ if (next == curr)
+ return;
+
+ requeue_task_rt(rq, curr, 1);
+
+ if (next->prio != curr->prio)
return;
/*
- * p is migratable, so let's not schedule it and
- * see if it is pushed or pulled somewhere else.
+ * Got the right "next" queued with the same priority
+ * as current. If next is migratable, don't schedule
+ * it as it will be pushed or pulled somewhere else.
*/
- if (p->nr_cpus_allowed != 1
- && cpupri_find(&rq->rd->cpupri, p, NULL))
+ if (next->nr_cpus_allowed != 1 &&
+ cpupri_find(&rq->rd->cpupri, next, NULL))
return;
/*
* There appears to be other cpus that can accept
- * current and none to run 'p', so lets reschedule
- * to try and push current away:
+ * current and none to run next, so lets reschedule
+ * to try and push current away.
*/
- requeue_task_rt(rq, p, 1);
+ requeue_task_rt(rq, next, 1);
resched_curr(rq);
}
+static inline
+void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
+{
+ /*
+ * p is migratable, so let's not schedule it and
+ * see if it is pushed or pulled somewhere else.
+ */
+ if (p->nr_cpus_allowed != 1 &&
+ cpupri_find(&rq->rd->cpupri, p, NULL))
+ return;
+
+ check_preempt_equal_prio_common(rq);
+}
+
#endif /* CONFIG_SMP */
/*
@@ -1440,10 +1473,9 @@ static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq,
return next;
}
-static struct task_struct *_pick_next_task_rt(struct rq *rq)
+static struct task_struct *peek_next_task_rt(struct rq *rq)
{
struct sched_rt_entity *rt_se;
- struct task_struct *p;
struct rt_rq *rt_rq = &rq->rt;
do {
@@ -1452,9 +1484,15 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
rt_rq = group_rt_rq(rt_se);
} while (rt_rq);
- p = rt_task_of(rt_se);
- p->se.exec_start = rq_clock_task(rq);
+ return rt_task_of(rt_se);
+}
+static inline struct task_struct *_pick_next_task_rt(struct rq *rq)
+{
+ struct task_struct *p;
+
+ p = peek_next_task_rt(rq);
+ p->se.exec_start = rq_clock_task(rq);
return p;
}