sched: clean up new task placement

clean up new task placement.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Mike Galbraith <efault@gmx.de>
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index a60b1da..cc447fb 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -199,6 +199,21 @@
 	return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node);
 }
 
+static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
+{
+	struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
+	struct sched_entity *se = NULL;
+	struct rb_node *parent;
+
+	while (*link) {
+		parent = *link;
+		se = rb_entry(parent, struct sched_entity, run_node);
+		link = &parent->rb_right;
+	}
+
+	return se;
+}
+
 /**************************************************************
  * Scheduling class statistics methods:
  */
@@ -530,6 +545,31 @@
 }
 
 static void
+place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
+{
+	struct sched_entity *last = __pick_last_entity(cfs_rq);
+	u64 min_runtime, latency;
+
+	min_runtime = cfs_rq->min_vruntime;
+	if (last) {
+		min_runtime += last->vruntime;
+		min_runtime >>= 1;
+		if (initial && sched_feat(START_DEBIT))
+			min_runtime += sysctl_sched_latency/2;
+	}
+
+	if (!initial && sched_feat(NEW_FAIR_SLEEPERS)) {
+		latency = sysctl_sched_latency;
+		if (min_runtime > latency)
+			min_runtime -= latency;
+		else
+			min_runtime = 0;
+	}
+
+	se->vruntime = max(se->vruntime, min_runtime);
+}
+
+static void
 enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup)
 {
 	/*
@@ -538,19 +578,7 @@
 	update_curr(cfs_rq);
 
 	if (wakeup) {
-		u64 min_runtime, latency;
-
-		min_runtime = cfs_rq->min_vruntime;
-		min_runtime += sysctl_sched_latency/2;
-
-		if (sched_feat(NEW_FAIR_SLEEPERS)) {
-			latency = calc_weighted(sysctl_sched_latency, se);
-			if (min_runtime > latency)
-				min_runtime -= latency;
-		}
-
-		se->vruntime = max(se->vruntime, min_runtime);
-
+		place_entity(cfs_rq, se, 0);
 		enqueue_sleeper(cfs_rq, se);
 	}
 
@@ -1033,8 +1061,7 @@
 	sched_info_queued(p);
 
 	update_curr(cfs_rq);
-	se->vruntime = cfs_rq->min_vruntime;
-	update_stats_enqueue(cfs_rq, se);
+	place_entity(cfs_rq, se, 1);
 
 	/*
 	 * The first wait is dominated by the child-runs-first logic,