On Thu, Feb 23, 2017 at 06:45:05PM +0100, Peter Zijlstra wrote:
> Hurm.. maybe we should do what Steve initially suggested. The
> alternative is link order trickery, and I'm not sure we want to do that.

That is, given:

kernel/sched/Makefile: obj-y += idle_task.o fair.o rt.o deadline.o stop_task.o

results in:

readelf -s defconfig-build/vmlinux | awk '/sched_class/ {print $2 " " $8}' | 
sort -n
00000000602c93c0 idle_sched_class
00000000602c9480 fair_sched_class
00000000602c9580 rt_sched_class
00000000602c96c0 dl_sched_class
00000000602c97c0 stop_sched_class

we can do this, but yuck!

---
 kernel/sched/core.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 8f972df76eb2..eebe6729ceb7 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3285,10 +3285,16 @@ pick_next_task(struct rq *rq, struct task_struct *prev, 
struct rq_flags *rf)
        struct task_struct *p;
 
        /*
-        * Optimization: we know that if all tasks are in
-        * the fair class we can call that function directly:
+        * Optimization: we know that if all tasks are in the fair class we can
+        * call that function directly, but only if the @prev task wasn't of a
+        * higher scheduling class, because otherwise those loose the
+        * opportinity to pull in more work from other CPUs.
+        *
+        * Depends on link order in kernel/sched/Makefile.
         */
-       if (likely(rq->nr_running == rq->cfs.h_nr_running)) {
+       if (likely(rq->nr_running == rq->cfs.h_nr_running &&
+                  prev->sched_class <= &fair_sched_class)) {
+
                p = fair_sched_class.pick_next_task(rq, prev, rf);
                if (unlikely(p == RETRY_TASK))
                        goto again;

Reply via email to