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:
*/
#endif
}
+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)
{
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);
}
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,