summaryrefslogtreecommitdiffstats
path: root/kernel/sched/fair.c
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2014-01-23 20:32:21 +0100
committerIngo Molnar <mingo@kernel.org>2014-02-11 09:58:10 +0100
commit38033c37faab850ed5d33bb675c4de6c66be84d8 (patch)
tree7a00530a9a1346f29f8899ff949bf07a9e7db7ee /kernel/sched/fair.c
parent6c3b4d44ba2838f00614a5a2d777d4401e0bfd71 (diff)
downloadop-kernel-dev-38033c37faab850ed5d33bb675c4de6c66be84d8.zip
op-kernel-dev-38033c37faab850ed5d33bb675c4de6c66be84d8.tar.gz
sched: Push down pre_schedule() and idle_balance()
This patch both merged idle_balance() and pre_schedule() and pushes both of them into pick_next_task(). Conceptually pre_schedule() and idle_balance() are rather similar, both are used to pull more work onto the current CPU. We cannot however first move idle_balance() into pre_schedule_fair() since there is no guarantee the last runnable task is a fair task, and thus we would miss newidle balances. Similarly, the dl and rt pre_schedule calls must be ran before idle_balance() since their respective tasks have higher priority and it would not do to delay their execution searching for less important tasks first. However, by noticing that pick_next_tasks() already traverses the sched_class hierarchy in the right order, we can get the right behaviour and do away with both calls. We must however change the special case optimization to also require that prev is of sched_class_fair, otherwise we can miss doing a dl or rt pull where we needed one. Signed-off-by: Peter Zijlstra <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/n/tip-a8k6vvaebtn64nie345kx1je@git.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched/fair.c')
-rw-r--r--kernel/sched/fair.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index a81b241..43b49fe 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2577,7 +2577,8 @@ void idle_exit_fair(struct rq *this_rq)
update_rq_runnable_avg(this_rq, 0);
}
-#else
+#else /* CONFIG_SMP */
+
static inline void update_entity_load_avg(struct sched_entity *se,
int update_cfs_rq) {}
static inline void update_rq_runnable_avg(struct rq *rq, int runnable) {}
@@ -2589,7 +2590,7 @@ static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq,
int sleep) {}
static inline void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq,
int force_update) {}
-#endif
+#endif /* CONFIG_SMP */
static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
@@ -4682,9 +4683,10 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev)
struct sched_entity *se;
struct task_struct *p;
+again: __maybe_unused
#ifdef CONFIG_FAIR_GROUP_SCHED
if (!cfs_rq->nr_running)
- return NULL;
+ goto idle;
if (!prev || prev->sched_class != &fair_sched_class)
goto simple;
@@ -4760,7 +4762,7 @@ simple:
#endif
if (!cfs_rq->nr_running)
- return NULL;
+ goto idle;
if (prev)
prev->sched_class->put_prev_task(rq, prev);
@@ -4777,6 +4779,22 @@ simple:
hrtick_start_fair(rq, p);
return p;
+
+idle:
+#ifdef CONFIG_SMP
+ idle_enter_fair(rq);
+ /*
+ * We must set idle_stamp _before_ calling idle_balance(), such that we
+ * measure the duration of idle_balance() as idle time.
+ */
+ rq->idle_stamp = rq_clock(rq);
+ if (idle_balance(rq)) { /* drops rq->lock */
+ rq->idle_stamp = 0;
+ goto again;
+ }
+#endif
+
+ return NULL;
}
/*
OpenPOWER on IntegriCloud