diff options
-rw-r--r-- | include/linux/sched.h | 21 | ||||
-rw-r--r-- | kernel/sched/debug.c | 10 | ||||
-rw-r--r-- | kernel/sched/fair.c | 74 | ||||
-rw-r--r-- | kernel/sched/sched.h | 8 |
4 files changed, 89 insertions, 24 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 6d77432e14ff..fdca05c5f812 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1115,15 +1115,28 @@ struct load_weight { | |||
1115 | }; | 1115 | }; |
1116 | 1116 | ||
1117 | struct sched_avg { | 1117 | struct sched_avg { |
1118 | u64 last_runnable_update; | ||
1119 | s64 decay_count; | ||
1120 | /* | ||
1121 | * utilization_avg_contrib describes the amount of time that a | ||
1122 | * sched_entity is running on a CPU. It is based on running_avg_sum | ||
1123 | * and is scaled in the range [0..SCHED_LOAD_SCALE]. | ||
1124 | * load_avg_contrib described the amount of time that a sched_entity | ||
1125 | * is runnable on a rq. It is based on both runnable_avg_sum and the | ||
1126 | * weight of the task. | ||
1127 | */ | ||
1128 | unsigned long load_avg_contrib, utilization_avg_contrib; | ||
1118 | /* | 1129 | /* |
1119 | * These sums represent an infinite geometric series and so are bound | 1130 | * These sums represent an infinite geometric series and so are bound |
1120 | * above by 1024/(1-y). Thus we only need a u32 to store them for all | 1131 | * above by 1024/(1-y). Thus we only need a u32 to store them for all |
1121 | * choices of y < 1-2^(-32)*1024. | 1132 | * choices of y < 1-2^(-32)*1024. |
1133 | * running_avg_sum reflects the time that the sched_entity is | ||
1134 | * effectively running on the CPU. | ||
1135 | * runnable_avg_sum represents the amount of time a sched_entity is on | ||
1136 | * a runqueue which includes the running time that is monitored by | ||
1137 | * running_avg_sum. | ||
1122 | */ | 1138 | */ |
1123 | u32 runnable_avg_sum, runnable_avg_period; | 1139 | u32 runnable_avg_sum, avg_period, running_avg_sum; |
1124 | u64 last_runnable_update; | ||
1125 | s64 decay_count; | ||
1126 | unsigned long load_avg_contrib; | ||
1127 | }; | 1140 | }; |
1128 | 1141 | ||
1129 | #ifdef CONFIG_SCHEDSTATS | 1142 | #ifdef CONFIG_SCHEDSTATS |
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 8baaf858d25c..578ff83d1d1a 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c | |||
@@ -71,7 +71,7 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group | |||
71 | if (!se) { | 71 | if (!se) { |
72 | struct sched_avg *avg = &cpu_rq(cpu)->avg; | 72 | struct sched_avg *avg = &cpu_rq(cpu)->avg; |
73 | P(avg->runnable_avg_sum); | 73 | P(avg->runnable_avg_sum); |
74 | P(avg->runnable_avg_period); | 74 | P(avg->avg_period); |
75 | return; | 75 | return; |
76 | } | 76 | } |
77 | 77 | ||
@@ -94,7 +94,7 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group | |||
94 | P(se->load.weight); | 94 | P(se->load.weight); |
95 | #ifdef CONFIG_SMP | 95 | #ifdef CONFIG_SMP |
96 | P(se->avg.runnable_avg_sum); | 96 | P(se->avg.runnable_avg_sum); |
97 | P(se->avg.runnable_avg_period); | 97 | P(se->avg.avg_period); |
98 | P(se->avg.load_avg_contrib); | 98 | P(se->avg.load_avg_contrib); |
99 | P(se->avg.decay_count); | 99 | P(se->avg.decay_count); |
100 | #endif | 100 | #endif |
@@ -214,6 +214,8 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) | |||
214 | cfs_rq->runnable_load_avg); | 214 | cfs_rq->runnable_load_avg); |
215 | SEQ_printf(m, " .%-30s: %ld\n", "blocked_load_avg", | 215 | SEQ_printf(m, " .%-30s: %ld\n", "blocked_load_avg", |
216 | cfs_rq->blocked_load_avg); | 216 | cfs_rq->blocked_load_avg); |
217 | SEQ_printf(m, " .%-30s: %ld\n", "utilization_load_avg", | ||
218 | cfs_rq->utilization_load_avg); | ||
217 | #ifdef CONFIG_FAIR_GROUP_SCHED | 219 | #ifdef CONFIG_FAIR_GROUP_SCHED |
218 | SEQ_printf(m, " .%-30s: %ld\n", "tg_load_contrib", | 220 | SEQ_printf(m, " .%-30s: %ld\n", "tg_load_contrib", |
219 | cfs_rq->tg_load_contrib); | 221 | cfs_rq->tg_load_contrib); |
@@ -636,8 +638,10 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) | |||
636 | P(se.load.weight); | 638 | P(se.load.weight); |
637 | #ifdef CONFIG_SMP | 639 | #ifdef CONFIG_SMP |
638 | P(se.avg.runnable_avg_sum); | 640 | P(se.avg.runnable_avg_sum); |
639 | P(se.avg.runnable_avg_period); | 641 | P(se.avg.running_avg_sum); |
642 | P(se.avg.avg_period); | ||
640 | P(se.avg.load_avg_contrib); | 643 | P(se.avg.load_avg_contrib); |
644 | P(se.avg.utilization_avg_contrib); | ||
641 | P(se.avg.decay_count); | 645 | P(se.avg.decay_count); |
642 | #endif | 646 | #endif |
643 | P(policy); | 647 | P(policy); |
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ee595ef30470..414408dd6e0c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c | |||
@@ -670,6 +670,7 @@ static int select_idle_sibling(struct task_struct *p, int cpu); | |||
670 | static unsigned long task_h_load(struct task_struct *p); | 670 | static unsigned long task_h_load(struct task_struct *p); |
671 | 671 | ||
672 | static inline void __update_task_entity_contrib(struct sched_entity *se); | 672 | static inline void __update_task_entity_contrib(struct sched_entity *se); |
673 | static inline void __update_task_entity_utilization(struct sched_entity *se); | ||
673 | 674 | ||
674 | /* Give new task start runnable values to heavy its load in infant time */ | 675 | /* Give new task start runnable values to heavy its load in infant time */ |
675 | void init_task_runnable_average(struct task_struct *p) | 676 | void init_task_runnable_average(struct task_struct *p) |
@@ -677,9 +678,10 @@ void init_task_runnable_average(struct task_struct *p) | |||
677 | u32 slice; | 678 | u32 slice; |
678 | 679 | ||
679 | slice = sched_slice(task_cfs_rq(p), &p->se) >> 10; | 680 | slice = sched_slice(task_cfs_rq(p), &p->se) >> 10; |
680 | p->se.avg.runnable_avg_sum = slice; | 681 | p->se.avg.runnable_avg_sum = p->se.avg.running_avg_sum = slice; |
681 | p->se.avg.runnable_avg_period = slice; | 682 | p->se.avg.avg_period = slice; |
682 | __update_task_entity_contrib(&p->se); | 683 | __update_task_entity_contrib(&p->se); |
684 | __update_task_entity_utilization(&p->se); | ||
683 | } | 685 | } |
684 | #else | 686 | #else |
685 | void init_task_runnable_average(struct task_struct *p) | 687 | void init_task_runnable_average(struct task_struct *p) |
@@ -1684,7 +1686,7 @@ static u64 numa_get_avg_runtime(struct task_struct *p, u64 *period) | |||
1684 | *period = now - p->last_task_numa_placement; | 1686 | *period = now - p->last_task_numa_placement; |
1685 | } else { | 1687 | } else { |
1686 | delta = p->se.avg.runnable_avg_sum; | 1688 | delta = p->se.avg.runnable_avg_sum; |
1687 | *period = p->se.avg.runnable_avg_period; | 1689 | *period = p->se.avg.avg_period; |
1688 | } | 1690 | } |
1689 | 1691 | ||
1690 | p->last_sum_exec_runtime = runtime; | 1692 | p->last_sum_exec_runtime = runtime; |
@@ -2512,7 +2514,8 @@ static u32 __compute_runnable_contrib(u64 n) | |||
2512 | */ | 2514 | */ |
2513 | static __always_inline int __update_entity_runnable_avg(u64 now, | 2515 | static __always_inline int __update_entity_runnable_avg(u64 now, |
2514 | struct sched_avg *sa, | 2516 | struct sched_avg *sa, |
2515 | int runnable) | 2517 | int runnable, |
2518 | int running) | ||
2516 | { | 2519 | { |
2517 | u64 delta, periods; | 2520 | u64 delta, periods; |
2518 | u32 runnable_contrib; | 2521 | u32 runnable_contrib; |
@@ -2538,7 +2541,7 @@ static __always_inline int __update_entity_runnable_avg(u64 now, | |||
2538 | sa->last_runnable_update = now; | 2541 | sa->last_runnable_update = now; |
2539 | 2542 | ||
2540 | /* delta_w is the amount already accumulated against our next period */ | 2543 | /* delta_w is the amount already accumulated against our next period */ |
2541 | delta_w = sa->runnable_avg_period % 1024; | 2544 | delta_w = sa->avg_period % 1024; |
2542 | if (delta + delta_w >= 1024) { | 2545 | if (delta + delta_w >= 1024) { |
2543 | /* period roll-over */ | 2546 | /* period roll-over */ |
2544 | decayed = 1; | 2547 | decayed = 1; |
@@ -2551,7 +2554,9 @@ static __always_inline int __update_entity_runnable_avg(u64 now, | |||
2551 | delta_w = 1024 - delta_w; | 2554 | delta_w = 1024 - delta_w; |
2552 | if (runnable) | 2555 | if (runnable) |
2553 | sa->runnable_avg_sum += delta_w; | 2556 | sa->runnable_avg_sum += delta_w; |
2554 | sa->runnable_avg_period += delta_w; | 2557 | if (running) |
2558 | sa->running_avg_sum += delta_w; | ||
2559 | sa->avg_period += delta_w; | ||
2555 | 2560 | ||
2556 | delta -= delta_w; | 2561 | delta -= delta_w; |
2557 | 2562 | ||
@@ -2561,20 +2566,26 @@ static __always_inline int __update_entity_runnable_avg(u64 now, | |||
2561 | 2566 | ||
2562 | sa->runnable_avg_sum = decay_load(sa->runnable_avg_sum, | 2567 | sa->runnable_avg_sum = decay_load(sa->runnable_avg_sum, |
2563 | periods + 1); | 2568 | periods + 1); |
2564 | sa->runnable_avg_period = decay_load(sa->runnable_avg_period, | 2569 | sa->running_avg_sum = decay_load(sa->running_avg_sum, |
2570 | periods + 1); | ||
2571 | sa->avg_period = decay_load(sa->avg_period, | ||
2565 | periods + 1); | 2572 | periods + 1); |
2566 | 2573 | ||
2567 | /* Efficiently calculate \sum (1..n_period) 1024*y^i */ | 2574 | /* Efficiently calculate \sum (1..n_period) 1024*y^i */ |
2568 | runnable_contrib = __compute_runnable_contrib(periods); | 2575 | runnable_contrib = __compute_runnable_contrib(periods); |
2569 | if (runnable) | 2576 | if (runnable) |
2570 | sa->runnable_avg_sum += runnable_contrib; | 2577 | sa->runnable_avg_sum += runnable_contrib; |
2571 | sa->runnable_avg_period += runnable_contrib; | 2578 | if (running) |
2579 | sa->running_avg_sum += runnable_contrib; | ||
2580 | sa->avg_period += runnable_contrib; | ||
2572 | } | 2581 | } |
2573 | 2582 | ||
2574 | /* Remainder of delta accrued against u_0` */ | 2583 | /* Remainder of delta accrued against u_0` */ |
2575 | if (runnable) | 2584 | if (runnable) |
2576 | sa->runnable_avg_sum += delta; | 2585 | sa->runnable_avg_sum += delta; |
2577 | sa->runnable_avg_period += delta; | 2586 | if (running) |
2587 | sa->running_avg_sum += delta; | ||
2588 | sa->avg_period += delta; | ||
2578 | 2589 | ||
2579 | return decayed; | 2590 | return decayed; |
2580 | } | 2591 | } |
@@ -2591,6 +2602,8 @@ static inline u64 __synchronize_entity_decay(struct sched_entity *se) | |||
2591 | return 0; | 2602 | return 0; |
2592 | 2603 | ||
2593 | se->avg.load_avg_contrib = decay_load(se->avg.load_avg_contrib, decays); | 2604 | se->avg.load_avg_contrib = decay_load(se->avg.load_avg_contrib, decays); |
2605 | se->avg.utilization_avg_contrib = | ||
2606 | decay_load(se->avg.utilization_avg_contrib, decays); | ||
2594 | 2607 | ||
2595 | return decays; | 2608 | return decays; |
2596 | } | 2609 | } |
@@ -2626,7 +2639,7 @@ static inline void __update_tg_runnable_avg(struct sched_avg *sa, | |||
2626 | 2639 | ||
2627 | /* The fraction of a cpu used by this cfs_rq */ | 2640 | /* The fraction of a cpu used by this cfs_rq */ |
2628 | contrib = div_u64((u64)sa->runnable_avg_sum << NICE_0_SHIFT, | 2641 | contrib = div_u64((u64)sa->runnable_avg_sum << NICE_0_SHIFT, |
2629 | sa->runnable_avg_period + 1); | 2642 | sa->avg_period + 1); |
2630 | contrib -= cfs_rq->tg_runnable_contrib; | 2643 | contrib -= cfs_rq->tg_runnable_contrib; |
2631 | 2644 | ||
2632 | if (abs(contrib) > cfs_rq->tg_runnable_contrib / 64) { | 2645 | if (abs(contrib) > cfs_rq->tg_runnable_contrib / 64) { |
@@ -2679,7 +2692,8 @@ static inline void __update_group_entity_contrib(struct sched_entity *se) | |||
2679 | 2692 | ||
2680 | static inline void update_rq_runnable_avg(struct rq *rq, int runnable) | 2693 | static inline void update_rq_runnable_avg(struct rq *rq, int runnable) |
2681 | { | 2694 | { |
2682 | __update_entity_runnable_avg(rq_clock_task(rq), &rq->avg, runnable); | 2695 | __update_entity_runnable_avg(rq_clock_task(rq), &rq->avg, runnable, |
2696 | runnable); | ||
2683 | __update_tg_runnable_avg(&rq->avg, &rq->cfs); | 2697 | __update_tg_runnable_avg(&rq->avg, &rq->cfs); |
2684 | } | 2698 | } |
2685 | #else /* CONFIG_FAIR_GROUP_SCHED */ | 2699 | #else /* CONFIG_FAIR_GROUP_SCHED */ |
@@ -2697,7 +2711,7 @@ static inline void __update_task_entity_contrib(struct sched_entity *se) | |||
2697 | 2711 | ||
2698 | /* avoid overflowing a 32-bit type w/ SCHED_LOAD_SCALE */ | 2712 | /* avoid overflowing a 32-bit type w/ SCHED_LOAD_SCALE */ |
2699 | contrib = se->avg.runnable_avg_sum * scale_load_down(se->load.weight); | 2713 | contrib = se->avg.runnable_avg_sum * scale_load_down(se->load.weight); |
2700 | contrib /= (se->avg.runnable_avg_period + 1); | 2714 | contrib /= (se->avg.avg_period + 1); |
2701 | se->avg.load_avg_contrib = scale_load(contrib); | 2715 | se->avg.load_avg_contrib = scale_load(contrib); |
2702 | } | 2716 | } |
2703 | 2717 | ||
@@ -2716,6 +2730,27 @@ static long __update_entity_load_avg_contrib(struct sched_entity *se) | |||
2716 | return se->avg.load_avg_contrib - old_contrib; | 2730 | return se->avg.load_avg_contrib - old_contrib; |
2717 | } | 2731 | } |
2718 | 2732 | ||
2733 | |||
2734 | static inline void __update_task_entity_utilization(struct sched_entity *se) | ||
2735 | { | ||
2736 | u32 contrib; | ||
2737 | |||
2738 | /* avoid overflowing a 32-bit type w/ SCHED_LOAD_SCALE */ | ||
2739 | contrib = se->avg.running_avg_sum * scale_load_down(SCHED_LOAD_SCALE); | ||
2740 | contrib /= (se->avg.avg_period + 1); | ||
2741 | se->avg.utilization_avg_contrib = scale_load(contrib); | ||
2742 | } | ||
2743 | |||
2744 | static long __update_entity_utilization_avg_contrib(struct sched_entity *se) | ||
2745 | { | ||
2746 | long old_contrib = se->avg.utilization_avg_contrib; | ||
2747 | |||
2748 | if (entity_is_task(se)) | ||
2749 | __update_task_entity_utilization(se); | ||
2750 | |||
2751 | return se->avg.utilization_avg_contrib - old_contrib; | ||
2752 | } | ||
2753 | |||
2719 | static inline void subtract_blocked_load_contrib(struct cfs_rq *cfs_rq, | 2754 | static inline void subtract_blocked_load_contrib(struct cfs_rq *cfs_rq, |
2720 | long load_contrib) | 2755 | long load_contrib) |
2721 | { | 2756 | { |
@@ -2732,7 +2767,7 @@ static inline void update_entity_load_avg(struct sched_entity *se, | |||
2732 | int update_cfs_rq) | 2767 | int update_cfs_rq) |
2733 | { | 2768 | { |
2734 | struct cfs_rq *cfs_rq = cfs_rq_of(se); | 2769 | struct cfs_rq *cfs_rq = cfs_rq_of(se); |
2735 | long contrib_delta; | 2770 | long contrib_delta, utilization_delta; |
2736 | u64 now; | 2771 | u64 now; |
2737 | 2772 | ||
2738 | /* | 2773 | /* |
@@ -2744,18 +2779,22 @@ static inline void update_entity_load_avg(struct sched_entity *se, | |||
2744 | else | 2779 | else |
2745 | now = cfs_rq_clock_task(group_cfs_rq(se)); | 2780 | now = cfs_rq_clock_task(group_cfs_rq(se)); |
2746 | 2781 | ||
2747 | if (!__update_entity_runnable_avg(now, &se->avg, se->on_rq)) | 2782 | if (!__update_entity_runnable_avg(now, &se->avg, se->on_rq, |
2783 | cfs_rq->curr == se)) | ||
2748 | return; | 2784 | return; |
2749 | 2785 | ||
2750 | contrib_delta = __update_entity_load_avg_contrib(se); | 2786 | contrib_delta = __update_entity_load_avg_contrib(se); |
2787 | utilization_delta = __update_entity_utilization_avg_contrib(se); | ||
2751 | 2788 | ||
2752 | if (!update_cfs_rq) | 2789 | if (!update_cfs_rq) |
2753 | return; | 2790 | return; |
2754 | 2791 | ||
2755 | if (se->on_rq) | 2792 | if (se->on_rq) { |
2756 | cfs_rq->runnable_load_avg += contrib_delta; | 2793 | cfs_rq->runnable_load_avg += contrib_delta; |
2757 | else | 2794 | cfs_rq->utilization_load_avg += utilization_delta; |
2795 | } else { | ||
2758 | subtract_blocked_load_contrib(cfs_rq, -contrib_delta); | 2796 | subtract_blocked_load_contrib(cfs_rq, -contrib_delta); |
2797 | } | ||
2759 | } | 2798 | } |
2760 | 2799 | ||
2761 | /* | 2800 | /* |
@@ -2830,6 +2869,7 @@ static inline void enqueue_entity_load_avg(struct cfs_rq *cfs_rq, | |||
2830 | } | 2869 | } |
2831 | 2870 | ||
2832 | cfs_rq->runnable_load_avg += se->avg.load_avg_contrib; | 2871 | cfs_rq->runnable_load_avg += se->avg.load_avg_contrib; |
2872 | cfs_rq->utilization_load_avg += se->avg.utilization_avg_contrib; | ||
2833 | /* we force update consideration on load-balancer moves */ | 2873 | /* we force update consideration on load-balancer moves */ |
2834 | update_cfs_rq_blocked_load(cfs_rq, !wakeup); | 2874 | update_cfs_rq_blocked_load(cfs_rq, !wakeup); |
2835 | } | 2875 | } |
@@ -2848,6 +2888,7 @@ static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq, | |||
2848 | update_cfs_rq_blocked_load(cfs_rq, !sleep); | 2888 | update_cfs_rq_blocked_load(cfs_rq, !sleep); |
2849 | 2889 | ||
2850 | cfs_rq->runnable_load_avg -= se->avg.load_avg_contrib; | 2890 | cfs_rq->runnable_load_avg -= se->avg.load_avg_contrib; |
2891 | cfs_rq->utilization_load_avg -= se->avg.utilization_avg_contrib; | ||
2851 | if (sleep) { | 2892 | if (sleep) { |
2852 | cfs_rq->blocked_load_avg += se->avg.load_avg_contrib; | 2893 | cfs_rq->blocked_load_avg += se->avg.load_avg_contrib; |
2853 | se->avg.decay_count = atomic64_read(&cfs_rq->decay_counter); | 2894 | se->avg.decay_count = atomic64_read(&cfs_rq->decay_counter); |
@@ -3185,6 +3226,7 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
3185 | */ | 3226 | */ |
3186 | update_stats_wait_end(cfs_rq, se); | 3227 | update_stats_wait_end(cfs_rq, se); |
3187 | __dequeue_entity(cfs_rq, se); | 3228 | __dequeue_entity(cfs_rq, se); |
3229 | update_entity_load_avg(se, 1); | ||
3188 | } | 3230 | } |
3189 | 3231 | ||
3190 | update_stats_curr_start(cfs_rq, se); | 3232 | update_stats_curr_start(cfs_rq, se); |
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index c2c0d7bd5027..4c95cc2e0be2 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h | |||
@@ -363,8 +363,14 @@ struct cfs_rq { | |||
363 | * Under CFS, load is tracked on a per-entity basis and aggregated up. | 363 | * Under CFS, load is tracked on a per-entity basis and aggregated up. |
364 | * This allows for the description of both thread and group usage (in | 364 | * This allows for the description of both thread and group usage (in |
365 | * the FAIR_GROUP_SCHED case). | 365 | * the FAIR_GROUP_SCHED case). |
366 | * runnable_load_avg is the sum of the load_avg_contrib of the | ||
367 | * sched_entities on the rq. | ||
368 | * blocked_load_avg is similar to runnable_load_avg except that its | ||
369 | * the blocked sched_entities on the rq. | ||
370 | * utilization_load_avg is the sum of the average running time of the | ||
371 | * sched_entities on the rq. | ||
366 | */ | 372 | */ |
367 | unsigned long runnable_load_avg, blocked_load_avg; | 373 | unsigned long runnable_load_avg, blocked_load_avg, utilization_load_avg; |
368 | atomic64_t decay_counter; | 374 | atomic64_t decay_counter; |
369 | u64 last_decay; | 375 | u64 last_decay; |
370 | atomic_long_t removed_load; | 376 | atomic_long_t removed_load; |