diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sched_fair.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index a60b1dac598a..cc447fbff51c 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -199,6 +199,21 @@ static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq) | |||
199 | return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node); | 199 | return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node); |
200 | } | 200 | } |
201 | 201 | ||
202 | static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq) | ||
203 | { | ||
204 | struct rb_node **link = &cfs_rq->tasks_timeline.rb_node; | ||
205 | struct sched_entity *se = NULL; | ||
206 | struct rb_node *parent; | ||
207 | |||
208 | while (*link) { | ||
209 | parent = *link; | ||
210 | se = rb_entry(parent, struct sched_entity, run_node); | ||
211 | link = &parent->rb_right; | ||
212 | } | ||
213 | |||
214 | return se; | ||
215 | } | ||
216 | |||
202 | /************************************************************** | 217 | /************************************************************** |
203 | * Scheduling class statistics methods: | 218 | * Scheduling class statistics methods: |
204 | */ | 219 | */ |
@@ -530,6 +545,31 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
530 | } | 545 | } |
531 | 546 | ||
532 | static void | 547 | static void |
548 | place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) | ||
549 | { | ||
550 | struct sched_entity *last = __pick_last_entity(cfs_rq); | ||
551 | u64 min_runtime, latency; | ||
552 | |||
553 | min_runtime = cfs_rq->min_vruntime; | ||
554 | if (last) { | ||
555 | min_runtime += last->vruntime; | ||
556 | min_runtime >>= 1; | ||
557 | if (initial && sched_feat(START_DEBIT)) | ||
558 | min_runtime += sysctl_sched_latency/2; | ||
559 | } | ||
560 | |||
561 | if (!initial && sched_feat(NEW_FAIR_SLEEPERS)) { | ||
562 | latency = sysctl_sched_latency; | ||
563 | if (min_runtime > latency) | ||
564 | min_runtime -= latency; | ||
565 | else | ||
566 | min_runtime = 0; | ||
567 | } | ||
568 | |||
569 | se->vruntime = max(se->vruntime, min_runtime); | ||
570 | } | ||
571 | |||
572 | static void | ||
533 | enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) | 573 | enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) |
534 | { | 574 | { |
535 | /* | 575 | /* |
@@ -538,19 +578,7 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) | |||
538 | update_curr(cfs_rq); | 578 | update_curr(cfs_rq); |
539 | 579 | ||
540 | if (wakeup) { | 580 | if (wakeup) { |
541 | u64 min_runtime, latency; | 581 | place_entity(cfs_rq, se, 0); |
542 | |||
543 | min_runtime = cfs_rq->min_vruntime; | ||
544 | min_runtime += sysctl_sched_latency/2; | ||
545 | |||
546 | if (sched_feat(NEW_FAIR_SLEEPERS)) { | ||
547 | latency = calc_weighted(sysctl_sched_latency, se); | ||
548 | if (min_runtime > latency) | ||
549 | min_runtime -= latency; | ||
550 | } | ||
551 | |||
552 | se->vruntime = max(se->vruntime, min_runtime); | ||
553 | |||
554 | enqueue_sleeper(cfs_rq, se); | 582 | enqueue_sleeper(cfs_rq, se); |
555 | } | 583 | } |
556 | 584 | ||
@@ -1033,8 +1061,7 @@ static void task_new_fair(struct rq *rq, struct task_struct *p) | |||
1033 | sched_info_queued(p); | 1061 | sched_info_queued(p); |
1034 | 1062 | ||
1035 | update_curr(cfs_rq); | 1063 | update_curr(cfs_rq); |
1036 | se->vruntime = cfs_rq->min_vruntime; | 1064 | place_entity(cfs_rq, se, 1); |
1037 | update_stats_enqueue(cfs_rq, se); | ||
1038 | 1065 | ||
1039 | /* | 1066 | /* |
1040 | * The first wait is dominated by the child-runs-first logic, | 1067 | * The first wait is dominated by the child-runs-first logic, |