diff options
Diffstat (limited to 'kernel/sched_fair.c')
-rw-r--r-- | kernel/sched_fair.c | 59 |
1 files changed, 31 insertions, 28 deletions
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index ce39282d9c0d..892616bf2c77 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -194,6 +194,8 @@ __enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
194 | update_load_add(&cfs_rq->load, se->load.weight); | 194 | update_load_add(&cfs_rq->load, se->load.weight); |
195 | cfs_rq->nr_running++; | 195 | cfs_rq->nr_running++; |
196 | se->on_rq = 1; | 196 | se->on_rq = 1; |
197 | |||
198 | schedstat_add(cfs_rq, wait_runtime, se->wait_runtime); | ||
197 | } | 199 | } |
198 | 200 | ||
199 | static inline void | 201 | static inline void |
@@ -205,6 +207,8 @@ __dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
205 | update_load_sub(&cfs_rq->load, se->load.weight); | 207 | update_load_sub(&cfs_rq->load, se->load.weight); |
206 | cfs_rq->nr_running--; | 208 | cfs_rq->nr_running--; |
207 | se->on_rq = 0; | 209 | se->on_rq = 0; |
210 | |||
211 | schedstat_add(cfs_rq, wait_runtime, -se->wait_runtime); | ||
208 | } | 212 | } |
209 | 213 | ||
210 | static inline struct rb_node *first_fair(struct cfs_rq *cfs_rq) | 214 | static inline struct rb_node *first_fair(struct cfs_rq *cfs_rq) |
@@ -291,7 +295,7 @@ niced_granularity(struct sched_entity *curr, unsigned long granularity) | |||
291 | /* | 295 | /* |
292 | * It will always fit into 'long': | 296 | * It will always fit into 'long': |
293 | */ | 297 | */ |
294 | return (long) (tmp >> WMULT_SHIFT); | 298 | return (long) (tmp >> (WMULT_SHIFT-NICE_0_SHIFT)); |
295 | } | 299 | } |
296 | 300 | ||
297 | static inline void | 301 | static inline void |
@@ -574,7 +578,6 @@ static void __enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
574 | 578 | ||
575 | prev_runtime = se->wait_runtime; | 579 | prev_runtime = se->wait_runtime; |
576 | __add_wait_runtime(cfs_rq, se, delta_fair); | 580 | __add_wait_runtime(cfs_rq, se, delta_fair); |
577 | schedstat_add(cfs_rq, wait_runtime, se->wait_runtime); | ||
578 | delta_fair = se->wait_runtime - prev_runtime; | 581 | delta_fair = se->wait_runtime - prev_runtime; |
579 | 582 | ||
580 | /* | 583 | /* |
@@ -662,7 +665,6 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) | |||
662 | if (tsk->state & TASK_UNINTERRUPTIBLE) | 665 | if (tsk->state & TASK_UNINTERRUPTIBLE) |
663 | se->block_start = rq_of(cfs_rq)->clock; | 666 | se->block_start = rq_of(cfs_rq)->clock; |
664 | } | 667 | } |
665 | cfs_rq->wait_runtime -= se->wait_runtime; | ||
666 | #endif | 668 | #endif |
667 | } | 669 | } |
668 | __dequeue_entity(cfs_rq, se); | 670 | __dequeue_entity(cfs_rq, se); |
@@ -671,22 +673,39 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) | |||
671 | /* | 673 | /* |
672 | * Preempt the current task with a newly woken task if needed: | 674 | * Preempt the current task with a newly woken task if needed: |
673 | */ | 675 | */ |
674 | static int | 676 | static void |
675 | __check_preempt_curr_fair(struct cfs_rq *cfs_rq, struct sched_entity *se, | 677 | __check_preempt_curr_fair(struct cfs_rq *cfs_rq, struct sched_entity *se, |
676 | struct sched_entity *curr, unsigned long granularity) | 678 | struct sched_entity *curr, unsigned long granularity) |
677 | { | 679 | { |
678 | s64 __delta = curr->fair_key - se->fair_key; | 680 | s64 __delta = curr->fair_key - se->fair_key; |
681 | unsigned long ideal_runtime, delta_exec; | ||
682 | |||
683 | /* | ||
684 | * ideal_runtime is compared against sum_exec_runtime, which is | ||
685 | * walltime, hence do not scale. | ||
686 | */ | ||
687 | ideal_runtime = max(sysctl_sched_latency / cfs_rq->nr_running, | ||
688 | (unsigned long)sysctl_sched_min_granularity); | ||
689 | |||
690 | /* | ||
691 | * If we executed more than what the latency constraint suggests, | ||
692 | * reduce the rescheduling granularity. This way the total latency | ||
693 | * of how much a task is not scheduled converges to | ||
694 | * sysctl_sched_latency: | ||
695 | */ | ||
696 | delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; | ||
697 | if (delta_exec > ideal_runtime) | ||
698 | granularity = 0; | ||
679 | 699 | ||
680 | /* | 700 | /* |
681 | * Take scheduling granularity into account - do not | 701 | * Take scheduling granularity into account - do not |
682 | * preempt the current task unless the best task has | 702 | * preempt the current task unless the best task has |
683 | * a larger than sched_granularity fairness advantage: | 703 | * a larger than sched_granularity fairness advantage: |
704 | * | ||
705 | * scale granularity as key space is in fair_clock. | ||
684 | */ | 706 | */ |
685 | if (__delta > niced_granularity(curr, granularity)) { | 707 | if (__delta > niced_granularity(curr, granularity)) |
686 | resched_task(rq_of(cfs_rq)->curr); | 708 | resched_task(rq_of(cfs_rq)->curr); |
687 | return 1; | ||
688 | } | ||
689 | return 0; | ||
690 | } | 709 | } |
691 | 710 | ||
692 | static inline void | 711 | static inline void |
@@ -702,6 +721,7 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
702 | update_stats_wait_end(cfs_rq, se); | 721 | update_stats_wait_end(cfs_rq, se); |
703 | update_stats_curr_start(cfs_rq, se); | 722 | update_stats_curr_start(cfs_rq, se); |
704 | set_cfs_rq_curr(cfs_rq, se); | 723 | set_cfs_rq_curr(cfs_rq, se); |
724 | se->prev_sum_exec_runtime = se->sum_exec_runtime; | ||
705 | } | 725 | } |
706 | 726 | ||
707 | static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq) | 727 | static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq) |
@@ -731,7 +751,6 @@ static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev) | |||
731 | 751 | ||
732 | static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) | 752 | static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) |
733 | { | 753 | { |
734 | unsigned long gran, ideal_runtime, delta_exec; | ||
735 | struct sched_entity *next; | 754 | struct sched_entity *next; |
736 | 755 | ||
737 | /* | 756 | /* |
@@ -748,22 +767,8 @@ static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) | |||
748 | if (next == curr) | 767 | if (next == curr) |
749 | return; | 768 | return; |
750 | 769 | ||
751 | gran = sched_granularity(cfs_rq); | 770 | __check_preempt_curr_fair(cfs_rq, next, curr, |
752 | ideal_runtime = niced_granularity(curr, | 771 | sched_granularity(cfs_rq)); |
753 | max(sysctl_sched_latency / cfs_rq->nr_running, | ||
754 | (unsigned long)sysctl_sched_min_granularity)); | ||
755 | /* | ||
756 | * If we executed more than what the latency constraint suggests, | ||
757 | * reduce the rescheduling granularity. This way the total latency | ||
758 | * of how much a task is not scheduled converges to | ||
759 | * sysctl_sched_latency: | ||
760 | */ | ||
761 | delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; | ||
762 | if (delta_exec > ideal_runtime) | ||
763 | gran = 0; | ||
764 | |||
765 | if (__check_preempt_curr_fair(cfs_rq, next, curr, gran)) | ||
766 | curr->prev_sum_exec_runtime = curr->sum_exec_runtime; | ||
767 | } | 772 | } |
768 | 773 | ||
769 | /************************************************** | 774 | /************************************************** |
@@ -1121,10 +1126,8 @@ static void task_new_fair(struct rq *rq, struct task_struct *p) | |||
1121 | * The statistical average of wait_runtime is about | 1126 | * The statistical average of wait_runtime is about |
1122 | * -granularity/2, so initialize the task with that: | 1127 | * -granularity/2, so initialize the task with that: |
1123 | */ | 1128 | */ |
1124 | if (sysctl_sched_features & SCHED_FEAT_START_DEBIT) { | 1129 | if (sysctl_sched_features & SCHED_FEAT_START_DEBIT) |
1125 | se->wait_runtime = -(sched_granularity(cfs_rq) / 2); | 1130 | se->wait_runtime = -(sched_granularity(cfs_rq) / 2); |
1126 | schedstat_add(cfs_rq, wait_runtime, se->wait_runtime); | ||
1127 | } | ||
1128 | 1131 | ||
1129 | __enqueue_entity(cfs_rq, se); | 1132 | __enqueue_entity(cfs_rq, se); |
1130 | } | 1133 | } |