diff options
| author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2010-11-15 18:47:01 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2010-11-18 07:27:47 -0500 |
| commit | 3d4b47b4b040c9d77dd68104cfc1055d89a55afd (patch) | |
| tree | a4b39b5d7c89a319b81543c1b26778d6220e772b /kernel | |
| parent | 2069dd75c7d0f49355939e5586daf5a9ab216db7 (diff) | |
sched: Implement on-demand (active) cfs_rq list
Make certain load-balance actions scale per number of active cgroups
instead of the number of existing cgroups.
This makes wakeup/sleep paths more expensive, but is a win for systems
where the vast majority of existing cgroups are idle.
Signed-off-by: Paul Turner <pjt@google.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20101115234937.666535048@google.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched.c | 105 | ||||
| -rw-r--r-- | kernel/sched_fair.c | 46 | ||||
| -rw-r--r-- | kernel/sched_rt.c | 24 |
3 files changed, 92 insertions, 83 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index e2f1a3024a99..22436dd2e19f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -274,9 +274,7 @@ struct task_group { | |||
| 274 | 274 | ||
| 275 | #define root_task_group init_task_group | 275 | #define root_task_group init_task_group |
| 276 | 276 | ||
| 277 | /* task_group_lock serializes add/remove of task groups and also changes to | 277 | /* task_group_lock serializes the addition/removal of task groups */ |
| 278 | * a task group's cpu shares. | ||
| 279 | */ | ||
| 280 | static DEFINE_SPINLOCK(task_group_lock); | 278 | static DEFINE_SPINLOCK(task_group_lock); |
| 281 | 279 | ||
| 282 | #ifdef CONFIG_FAIR_GROUP_SCHED | 280 | #ifdef CONFIG_FAIR_GROUP_SCHED |
| @@ -344,6 +342,7 @@ struct cfs_rq { | |||
| 344 | * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This | 342 | * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This |
| 345 | * list is used during load balance. | 343 | * list is used during load balance. |
| 346 | */ | 344 | */ |
| 345 | int on_list; | ||
| 347 | struct list_head leaf_cfs_rq_list; | 346 | struct list_head leaf_cfs_rq_list; |
| 348 | struct task_group *tg; /* group that "owns" this runqueue */ | 347 | struct task_group *tg; /* group that "owns" this runqueue */ |
| 349 | 348 | ||
| @@ -1547,7 +1546,7 @@ static unsigned long cpu_avg_load_per_task(int cpu) | |||
| 1547 | 1546 | ||
| 1548 | #ifdef CONFIG_FAIR_GROUP_SCHED | 1547 | #ifdef CONFIG_FAIR_GROUP_SCHED |
| 1549 | 1548 | ||
| 1550 | static void update_cfs_load(struct cfs_rq *cfs_rq); | 1549 | static void update_cfs_load(struct cfs_rq *cfs_rq, int lb); |
| 1551 | static void update_cfs_shares(struct cfs_rq *cfs_rq); | 1550 | static void update_cfs_shares(struct cfs_rq *cfs_rq); |
| 1552 | 1551 | ||
| 1553 | /* | 1552 | /* |
| @@ -1570,7 +1569,7 @@ static int tg_shares_up(struct task_group *tg, void *data) | |||
| 1570 | raw_spin_lock_irqsave(&rq->lock, flags); | 1569 | raw_spin_lock_irqsave(&rq->lock, flags); |
| 1571 | 1570 | ||
| 1572 | update_rq_clock(rq); | 1571 | update_rq_clock(rq); |
| 1573 | update_cfs_load(cfs_rq); | 1572 | update_cfs_load(cfs_rq, 1); |
| 1574 | 1573 | ||
| 1575 | load_avg = div64_u64(cfs_rq->load_avg, cfs_rq->load_period+1); | 1574 | load_avg = div64_u64(cfs_rq->load_avg, cfs_rq->load_period+1); |
| 1576 | load_avg -= cfs_rq->load_contribution; | 1575 | load_avg -= cfs_rq->load_contribution; |
| @@ -7688,15 +7687,13 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq) | |||
| 7688 | 7687 | ||
| 7689 | #ifdef CONFIG_FAIR_GROUP_SCHED | 7688 | #ifdef CONFIG_FAIR_GROUP_SCHED |
| 7690 | static void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq, | 7689 | static void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq, |
| 7691 | struct sched_entity *se, int cpu, int add, | 7690 | struct sched_entity *se, int cpu, |
| 7692 | struct sched_entity *parent) | 7691 | struct sched_entity *parent) |
| 7693 | { | 7692 | { |
| 7694 | struct rq *rq = cpu_rq(cpu); | 7693 | struct rq *rq = cpu_rq(cpu); |
| 7695 | tg->cfs_rq[cpu] = cfs_rq; | 7694 | tg->cfs_rq[cpu] = cfs_rq; |
| 7696 | init_cfs_rq(cfs_rq, rq); | 7695 | init_cfs_rq(cfs_rq, rq); |
| 7697 | cfs_rq->tg = tg; | 7696 | cfs_rq->tg = tg; |
| 7698 | if (add) | ||
| 7699 | list_add(&cfs_rq->leaf_cfs_rq_list, &rq->leaf_cfs_rq_list); | ||
| 7700 | 7697 | ||
| 7701 | tg->se[cpu] = se; | 7698 | tg->se[cpu] = se; |
| 7702 | /* se could be NULL for init_task_group */ | 7699 | /* se could be NULL for init_task_group */ |
| @@ -7716,7 +7713,7 @@ static void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq, | |||
| 7716 | 7713 | ||
| 7717 | #ifdef CONFIG_RT_GROUP_SCHED | 7714 | #ifdef CONFIG_RT_GROUP_SCHED |
| 7718 | static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq, | 7715 | static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq, |
| 7719 | struct sched_rt_entity *rt_se, int cpu, int add, | 7716 | struct sched_rt_entity *rt_se, int cpu, |
| 7720 | struct sched_rt_entity *parent) | 7717 | struct sched_rt_entity *parent) |
| 7721 | { | 7718 | { |
| 7722 | struct rq *rq = cpu_rq(cpu); | 7719 | struct rq *rq = cpu_rq(cpu); |
| @@ -7725,8 +7722,6 @@ static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq, | |||
| 7725 | init_rt_rq(rt_rq, rq); | 7722 | init_rt_rq(rt_rq, rq); |
| 7726 | rt_rq->tg = tg; | 7723 | rt_rq->tg = tg; |
| 7727 | rt_rq->rt_runtime = tg->rt_bandwidth.rt_runtime; | 7724 | rt_rq->rt_runtime = tg->rt_bandwidth.rt_runtime; |
| 7728 | if (add) | ||
| 7729 | list_add(&rt_rq->leaf_rt_rq_list, &rq->leaf_rt_rq_list); | ||
| 7730 | 7725 | ||
| 7731 | tg->rt_se[cpu] = rt_se; | 7726 | tg->rt_se[cpu] = rt_se; |
| 7732 | if (!rt_se) | 7727 | if (!rt_se) |
| @@ -7835,7 +7830,7 @@ void __init sched_init(void) | |||
| 7835 | * We achieve this by letting init_task_group's tasks sit | 7830 | * We achieve this by letting init_task_group's tasks sit |
| 7836 | * directly in rq->cfs (i.e init_task_group->se[] = NULL). | 7831 | * directly in rq->cfs (i.e init_task_group->se[] = NULL). |
| 7837 | */ | 7832 | */ |
| 7838 | init_tg_cfs_entry(&init_task_group, &rq->cfs, NULL, i, 1, NULL); | 7833 | init_tg_cfs_entry(&init_task_group, &rq->cfs, NULL, i, NULL); |
| 7839 | #endif | 7834 | #endif |
| 7840 | #endif /* CONFIG_FAIR_GROUP_SCHED */ | 7835 | #endif /* CONFIG_FAIR_GROUP_SCHED */ |
| 7841 | 7836 | ||
| @@ -7843,7 +7838,7 @@ void __init sched_init(void) | |||
| 7843 | #ifdef CONFIG_RT_GROUP_SCHED | 7838 | #ifdef CONFIG_RT_GROUP_SCHED |
| 7844 | INIT_LIST_HEAD(&rq->leaf_rt_rq_list); | 7839 | INIT_LIST_HEAD(&rq->leaf_rt_rq_list); |
| 7845 | #ifdef CONFIG_CGROUP_SCHED | 7840 | #ifdef CONFIG_CGROUP_SCHED |
| 7846 | init_tg_rt_entry(&init_task_group, &rq->rt, NULL, i, 1, NULL); | 7841 | init_tg_rt_entry(&init_task_group, &rq->rt, NULL, i, NULL); |
| 7847 | #endif | 7842 | #endif |
| 7848 | #endif | 7843 | #endif |
| 7849 | 7844 | ||
| @@ -8119,7 +8114,7 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) | |||
| 8119 | if (!se) | 8114 | if (!se) |
| 8120 | goto err_free_rq; | 8115 | goto err_free_rq; |
| 8121 | 8116 | ||
| 8122 | init_tg_cfs_entry(tg, cfs_rq, se, i, 0, parent->se[i]); | 8117 | init_tg_cfs_entry(tg, cfs_rq, se, i, parent->se[i]); |
| 8123 | } | 8118 | } |
| 8124 | 8119 | ||
| 8125 | return 1; | 8120 | return 1; |
| @@ -8130,15 +8125,22 @@ err: | |||
| 8130 | return 0; | 8125 | return 0; |
| 8131 | } | 8126 | } |
| 8132 | 8127 | ||
| 8133 | static inline void register_fair_sched_group(struct task_group *tg, int cpu) | ||
| 8134 | { | ||
| 8135 | list_add_rcu(&tg->cfs_rq[cpu]->leaf_cfs_rq_list, | ||
| 8136 | &cpu_rq(cpu)->leaf_cfs_rq_list); | ||
| 8137 | } | ||
| 8138 | |||
| 8139 | static inline void unregister_fair_sched_group(struct task_group *tg, int cpu) | 8128 | static inline void unregister_fair_sched_group(struct task_group *tg, int cpu) |
| 8140 | { | 8129 | { |
| 8141 | list_del_rcu(&tg->cfs_rq[cpu]->leaf_cfs_rq_list); | 8130 | struct rq *rq = cpu_rq(cpu); |
| 8131 | unsigned long flags; | ||
| 8132 | int i; | ||
| 8133 | |||
| 8134 | /* | ||
| 8135 | * Only empty task groups can be destroyed; so we can speculatively | ||
| 8136 | * check on_list without danger of it being re-added. | ||
| 8137 | */ | ||
| 8138 | if (!tg->cfs_rq[cpu]->on_list) | ||
| 8139 | return; | ||
| 8140 | |||
| 8141 | raw_spin_lock_irqsave(&rq->lock, flags); | ||
| 8142 | list_del_leaf_cfs_rq(tg->cfs_rq[i]); | ||
| 8143 | raw_spin_unlock_irqrestore(&rq->lock, flags); | ||
| 8142 | } | 8144 | } |
| 8143 | #else /* !CONFG_FAIR_GROUP_SCHED */ | 8145 | #else /* !CONFG_FAIR_GROUP_SCHED */ |
| 8144 | static inline void free_fair_sched_group(struct task_group *tg) | 8146 | static inline void free_fair_sched_group(struct task_group *tg) |
| @@ -8151,10 +8153,6 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) | |||
| 8151 | return 1; | 8153 | return 1; |
| 8152 | } | 8154 | } |
| 8153 | 8155 | ||
| 8154 | static inline void register_fair_sched_group(struct task_group *tg, int cpu) | ||
| 8155 | { | ||
| 8156 | } | ||
| 8157 | |||
| 8158 | static inline void unregister_fair_sched_group(struct task_group *tg, int cpu) | 8156 | static inline void unregister_fair_sched_group(struct task_group *tg, int cpu) |
| 8159 | { | 8157 | { |
| 8160 | } | 8158 | } |
| @@ -8209,7 +8207,7 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) | |||
| 8209 | if (!rt_se) | 8207 | if (!rt_se) |
| 8210 | goto err_free_rq; | 8208 | goto err_free_rq; |
| 8211 | 8209 | ||
| 8212 | init_tg_rt_entry(tg, rt_rq, rt_se, i, 0, parent->rt_se[i]); | 8210 | init_tg_rt_entry(tg, rt_rq, rt_se, i, parent->rt_se[i]); |
| 8213 | } | 8211 | } |
| 8214 | 8212 | ||
| 8215 | return 1; | 8213 | return 1; |
| @@ -8219,17 +8217,6 @@ err_free_rq: | |||
| 8219 | err: | 8217 | err: |
| 8220 | return 0; | 8218 | return 0; |
| 8221 | } | 8219 | } |
| 8222 | |||
| 8223 | static inline void register_rt_sched_group(struct task_group *tg, int cpu) | ||
| 8224 | { | ||
| 8225 | list_add_rcu(&tg->rt_rq[cpu]->leaf_rt_rq_list, | ||
| 8226 | &cpu_rq(cpu)->leaf_rt_rq_list); | ||
| 8227 | } | ||
| 8228 | |||
| 8229 | static inline void unregister_rt_sched_group(struct task_group *tg, int cpu) | ||
| 8230 | { | ||
| 8231 | list_del_rcu(&tg->rt_rq[cpu]->leaf_rt_rq_list); | ||
| 8232 | } | ||
| 8233 | #else /* !CONFIG_RT_GROUP_SCHED */ | 8220 | #else /* !CONFIG_RT_GROUP_SCHED */ |
| 8234 | static inline void free_rt_sched_group(struct task_group *tg) | 8221 | static inline void free_rt_sched_group(struct task_group *tg) |
| 8235 | { | 8222 | { |
| @@ -8240,14 +8227,6 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) | |||
| 8240 | { | 8227 | { |
| 8241 | return 1; | 8228 | return 1; |
| 8242 | } | 8229 | } |
| 8243 | |||
| 8244 | static inline void register_rt_sched_group(struct task_group *tg, int cpu) | ||
| 8245 | { | ||
| 8246 | } | ||
| 8247 | |||
| 8248 | static inline void unregister_rt_sched_group(struct task_group *tg, int cpu) | ||
| 8249 | { | ||
| 8250 | } | ||
| 8251 | #endif /* CONFIG_RT_GROUP_SCHED */ | 8230 | #endif /* CONFIG_RT_GROUP_SCHED */ |
| 8252 | 8231 | ||
| 8253 | #ifdef CONFIG_CGROUP_SCHED | 8232 | #ifdef CONFIG_CGROUP_SCHED |
| @@ -8263,7 +8242,6 @@ struct task_group *sched_create_group(struct task_group *parent) | |||
| 8263 | { | 8242 | { |
| 8264 | struct task_group *tg; | 8243 | struct task_group *tg; |
| 8265 | unsigned long flags; | 8244 | unsigned long flags; |
| 8266 | int i; | ||
| 8267 | 8245 | ||
| 8268 | tg = kzalloc(sizeof(*tg), GFP_KERNEL); | 8246 | tg = kzalloc(sizeof(*tg), GFP_KERNEL); |
| 8269 | if (!tg) | 8247 | if (!tg) |
| @@ -8276,10 +8254,6 @@ struct task_group *sched_create_group(struct task_group *parent) | |||
| 8276 | goto err; | 8254 | goto err; |
| 8277 | 8255 | ||
| 8278 | spin_lock_irqsave(&task_group_lock, flags); | 8256 | spin_lock_irqsave(&task_group_lock, flags); |
| 8279 | for_each_possible_cpu(i) { | ||
| 8280 | register_fair_sched_group(tg, i); | ||
| 8281 | register_rt_sched_group(tg, i); | ||
| 8282 | } | ||
| 8283 | list_add_rcu(&tg->list, &task_groups); | 8257 | list_add_rcu(&tg->list, &task_groups); |
| 8284 | 8258 | ||
| 8285 | WARN_ON(!parent); /* root should already exist */ | 8259 | WARN_ON(!parent); /* root should already exist */ |
| @@ -8309,11 +8283,11 @@ void sched_destroy_group(struct task_group *tg) | |||
| 8309 | unsigned long flags; | 8283 | unsigned long flags; |
| 8310 | int i; | 8284 | int i; |
| 8311 | 8285 | ||
| 8312 | spin_lock_irqsave(&task_group_lock, flags); | 8286 | /* end participation in shares distribution */ |
| 8313 | for_each_possible_cpu(i) { | 8287 | for_each_possible_cpu(i) |
| 8314 | unregister_fair_sched_group(tg, i); | 8288 | unregister_fair_sched_group(tg, i); |
| 8315 | unregister_rt_sched_group(tg, i); | 8289 | |
| 8316 | } | 8290 | spin_lock_irqsave(&task_group_lock, flags); |
| 8317 | list_del_rcu(&tg->list); | 8291 | list_del_rcu(&tg->list); |
| 8318 | list_del_rcu(&tg->siblings); | 8292 | list_del_rcu(&tg->siblings); |
| 8319 | spin_unlock_irqrestore(&task_group_lock, flags); | 8293 | spin_unlock_irqrestore(&task_group_lock, flags); |
| @@ -8391,7 +8365,6 @@ static DEFINE_MUTEX(shares_mutex); | |||
| 8391 | int sched_group_set_shares(struct task_group *tg, unsigned long shares) | 8365 | int sched_group_set_shares(struct task_group *tg, unsigned long shares) |
| 8392 | { | 8366 | { |
| 8393 | int i; | 8367 | int i; |
| 8394 | unsigned long flags; | ||
| 8395 | 8368 | ||
| 8396 | /* | 8369 | /* |
| 8397 | * We can't change the weight of the root cgroup. | 8370 | * We can't change the weight of the root cgroup. |
| @@ -8408,19 +8381,6 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares) | |||
| 8408 | if (tg->shares == shares) | 8381 | if (tg->shares == shares) |
| 8409 | goto done; | 8382 | goto done; |
| 8410 | 8383 | ||
| 8411 | spin_lock_irqsave(&task_group_lock, flags); | ||
| 8412 | for_each_possible_cpu(i) | ||
| 8413 | unregister_fair_sched_group(tg, i); | ||
| 8414 | list_del_rcu(&tg->siblings); | ||
| 8415 | spin_unlock_irqrestore(&task_group_lock, flags); | ||
| 8416 | |||
| 8417 | /* wait for any ongoing reference to this group to finish */ | ||
| 8418 | synchronize_sched(); | ||
| 8419 | |||
| 8420 | /* | ||
| 8421 | * Now we are free to modify the group's share on each cpu | ||
| 8422 | * w/o tripping rebalance_share or load_balance_fair. | ||
| 8423 | */ | ||
| 8424 | tg->shares = shares; | 8384 | tg->shares = shares; |
| 8425 | for_each_possible_cpu(i) { | 8385 | for_each_possible_cpu(i) { |
| 8426 | /* | 8386 | /* |
| @@ -8429,15 +8389,6 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares) | |||
| 8429 | set_se_shares(tg->se[i], shares); | 8389 | set_se_shares(tg->se[i], shares); |
| 8430 | } | 8390 | } |
| 8431 | 8391 | ||
| 8432 | /* | ||
| 8433 | * Enable load balance activity on this group, by inserting it back on | ||
| 8434 | * each cpu's rq->leaf_cfs_rq_list. | ||
| 8435 | */ | ||
| 8436 | spin_lock_irqsave(&task_group_lock, flags); | ||
| 8437 | for_each_possible_cpu(i) | ||
| 8438 | register_fair_sched_group(tg, i); | ||
| 8439 | list_add_rcu(&tg->siblings, &tg->parent->children); | ||
| 8440 | spin_unlock_irqrestore(&task_group_lock, flags); | ||
| 8441 | done: | 8392 | done: |
| 8442 | mutex_unlock(&shares_mutex); | 8393 | mutex_unlock(&shares_mutex); |
| 8443 | return 0; | 8394 | return 0; |
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index d86544b4151c..0560e72bd732 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
| @@ -143,6 +143,24 @@ static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu) | |||
| 143 | return cfs_rq->tg->cfs_rq[this_cpu]; | 143 | return cfs_rq->tg->cfs_rq[this_cpu]; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq) | ||
| 147 | { | ||
| 148 | if (!cfs_rq->on_list) { | ||
| 149 | list_add_rcu(&cfs_rq->leaf_cfs_rq_list, | ||
| 150 | &rq_of(cfs_rq)->leaf_cfs_rq_list); | ||
| 151 | |||
| 152 | cfs_rq->on_list = 1; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq) | ||
| 157 | { | ||
| 158 | if (cfs_rq->on_list) { | ||
| 159 | list_del_rcu(&cfs_rq->leaf_cfs_rq_list); | ||
| 160 | cfs_rq->on_list = 0; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 146 | /* Iterate thr' all leaf cfs_rq's on a runqueue */ | 164 | /* Iterate thr' all leaf cfs_rq's on a runqueue */ |
| 147 | #define for_each_leaf_cfs_rq(rq, cfs_rq) \ | 165 | #define for_each_leaf_cfs_rq(rq, cfs_rq) \ |
| 148 | list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list) | 166 | list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list) |
| @@ -246,6 +264,14 @@ static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu) | |||
| 246 | return &cpu_rq(this_cpu)->cfs; | 264 | return &cpu_rq(this_cpu)->cfs; |
| 247 | } | 265 | } |
| 248 | 266 | ||
| 267 | static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq) | ||
| 268 | { | ||
| 269 | } | ||
| 270 | |||
| 271 | static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq) | ||
| 272 | { | ||
| 273 | } | ||
| 274 | |||
| 249 | #define for_each_leaf_cfs_rq(rq, cfs_rq) \ | 275 | #define for_each_leaf_cfs_rq(rq, cfs_rq) \ |
| 250 | for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL) | 276 | for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL) |
| 251 | 277 | ||
| @@ -648,7 +674,7 @@ account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
| 648 | } | 674 | } |
| 649 | 675 | ||
| 650 | #if defined CONFIG_SMP && defined CONFIG_FAIR_GROUP_SCHED | 676 | #if defined CONFIG_SMP && defined CONFIG_FAIR_GROUP_SCHED |
| 651 | static void update_cfs_load(struct cfs_rq *cfs_rq) | 677 | static void update_cfs_load(struct cfs_rq *cfs_rq, int lb) |
| 652 | { | 678 | { |
| 653 | u64 period = sched_avg_period(); | 679 | u64 period = sched_avg_period(); |
| 654 | u64 now, delta; | 680 | u64 now, delta; |
| @@ -673,6 +699,11 @@ static void update_cfs_load(struct cfs_rq *cfs_rq) | |||
| 673 | cfs_rq->load_period /= 2; | 699 | cfs_rq->load_period /= 2; |
| 674 | cfs_rq->load_avg /= 2; | 700 | cfs_rq->load_avg /= 2; |
| 675 | } | 701 | } |
| 702 | |||
| 703 | if (lb && !cfs_rq->nr_running) { | ||
| 704 | if (cfs_rq->load_avg < (period / 8)) | ||
| 705 | list_del_leaf_cfs_rq(cfs_rq); | ||
| 706 | } | ||
| 676 | } | 707 | } |
| 677 | 708 | ||
| 678 | static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, | 709 | static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, |
| @@ -719,7 +750,7 @@ static void update_cfs_shares(struct cfs_rq *cfs_rq) | |||
| 719 | reweight_entity(cfs_rq_of(se), se, shares); | 750 | reweight_entity(cfs_rq_of(se), se, shares); |
| 720 | } | 751 | } |
| 721 | #else /* CONFIG_FAIR_GROUP_SCHED */ | 752 | #else /* CONFIG_FAIR_GROUP_SCHED */ |
| 722 | static inline void update_cfs_load(struct cfs_rq *cfs_rq) | 753 | static inline void update_cfs_load(struct cfs_rq *cfs_rq, int lb) |
| 723 | { | 754 | { |
| 724 | } | 755 | } |
| 725 | 756 | ||
| @@ -849,7 +880,7 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) | |||
| 849 | * Update run-time statistics of the 'current'. | 880 | * Update run-time statistics of the 'current'. |
| 850 | */ | 881 | */ |
| 851 | update_curr(cfs_rq); | 882 | update_curr(cfs_rq); |
| 852 | update_cfs_load(cfs_rq); | 883 | update_cfs_load(cfs_rq, 0); |
| 853 | account_entity_enqueue(cfs_rq, se); | 884 | account_entity_enqueue(cfs_rq, se); |
| 854 | update_cfs_shares(cfs_rq); | 885 | update_cfs_shares(cfs_rq); |
| 855 | 886 | ||
| @@ -863,6 +894,9 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) | |||
| 863 | if (se != cfs_rq->curr) | 894 | if (se != cfs_rq->curr) |
| 864 | __enqueue_entity(cfs_rq, se); | 895 | __enqueue_entity(cfs_rq, se); |
| 865 | se->on_rq = 1; | 896 | se->on_rq = 1; |
| 897 | |||
| 898 | if (cfs_rq->nr_running == 1) | ||
| 899 | list_add_leaf_cfs_rq(cfs_rq); | ||
| 866 | } | 900 | } |
| 867 | 901 | ||
| 868 | static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) | 902 | static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) |
| @@ -907,7 +941,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) | |||
| 907 | if (se != cfs_rq->curr) | 941 | if (se != cfs_rq->curr) |
| 908 | __dequeue_entity(cfs_rq, se); | 942 | __dequeue_entity(cfs_rq, se); |
| 909 | se->on_rq = 0; | 943 | se->on_rq = 0; |
| 910 | update_cfs_load(cfs_rq); | 944 | update_cfs_load(cfs_rq, 0); |
| 911 | account_entity_dequeue(cfs_rq, se); | 945 | account_entity_dequeue(cfs_rq, se); |
| 912 | update_min_vruntime(cfs_rq); | 946 | update_min_vruntime(cfs_rq); |
| 913 | update_cfs_shares(cfs_rq); | 947 | update_cfs_shares(cfs_rq); |
| @@ -1142,7 +1176,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags) | |||
| 1142 | for_each_sched_entity(se) { | 1176 | for_each_sched_entity(se) { |
| 1143 | struct cfs_rq *cfs_rq = cfs_rq_of(se); | 1177 | struct cfs_rq *cfs_rq = cfs_rq_of(se); |
| 1144 | 1178 | ||
| 1145 | update_cfs_load(cfs_rq); | 1179 | update_cfs_load(cfs_rq, 0); |
| 1146 | update_cfs_shares(cfs_rq); | 1180 | update_cfs_shares(cfs_rq); |
| 1147 | } | 1181 | } |
| 1148 | 1182 | ||
| @@ -1172,7 +1206,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) | |||
| 1172 | for_each_sched_entity(se) { | 1206 | for_each_sched_entity(se) { |
| 1173 | struct cfs_rq *cfs_rq = cfs_rq_of(se); | 1207 | struct cfs_rq *cfs_rq = cfs_rq_of(se); |
| 1174 | 1208 | ||
| 1175 | update_cfs_load(cfs_rq); | 1209 | update_cfs_load(cfs_rq, 0); |
| 1176 | update_cfs_shares(cfs_rq); | 1210 | update_cfs_shares(cfs_rq); |
| 1177 | } | 1211 | } |
| 1178 | 1212 | ||
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index bea7d79f7e9c..c914ec747ca6 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c | |||
| @@ -183,6 +183,17 @@ static inline u64 sched_rt_period(struct rt_rq *rt_rq) | |||
| 183 | return ktime_to_ns(rt_rq->tg->rt_bandwidth.rt_period); | 183 | return ktime_to_ns(rt_rq->tg->rt_bandwidth.rt_period); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static inline void list_add_leaf_rt_rq(struct rt_rq *rt_rq) | ||
| 187 | { | ||
| 188 | list_add_rcu(&rt_rq->leaf_rt_rq_list, | ||
| 189 | &rq_of_rt_rq(rt_rq)->leaf_rt_rq_list); | ||
| 190 | } | ||
| 191 | |||
| 192 | static inline void list_del_leaf_rt_rq(struct rt_rq *rt_rq) | ||
| 193 | { | ||
| 194 | list_del_rcu(&rt_rq->leaf_rt_rq_list); | ||
| 195 | } | ||
| 196 | |||
| 186 | #define for_each_leaf_rt_rq(rt_rq, rq) \ | 197 | #define for_each_leaf_rt_rq(rt_rq, rq) \ |
| 187 | list_for_each_entry_rcu(rt_rq, &rq->leaf_rt_rq_list, leaf_rt_rq_list) | 198 | list_for_each_entry_rcu(rt_rq, &rq->leaf_rt_rq_list, leaf_rt_rq_list) |
| 188 | 199 | ||
| @@ -276,6 +287,14 @@ static inline u64 sched_rt_period(struct rt_rq *rt_rq) | |||
| 276 | return ktime_to_ns(def_rt_bandwidth.rt_period); | 287 | return ktime_to_ns(def_rt_bandwidth.rt_period); |
| 277 | } | 288 | } |
| 278 | 289 | ||
| 290 | static inline void list_add_leaf_rt_rq(struct rt_rq *rt_rq) | ||
| 291 | { | ||
| 292 | } | ||
| 293 | |||
| 294 | static inline void list_del_leaf_rt_rq(struct rt_rq *rt_rq) | ||
| 295 | { | ||
| 296 | } | ||
| 297 | |||
| 279 | #define for_each_leaf_rt_rq(rt_rq, rq) \ | 298 | #define for_each_leaf_rt_rq(rt_rq, rq) \ |
| 280 | for (rt_rq = &rq->rt; rt_rq; rt_rq = NULL) | 299 | for (rt_rq = &rq->rt; rt_rq; rt_rq = NULL) |
| 281 | 300 | ||
| @@ -825,6 +844,9 @@ static void __enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head) | |||
| 825 | if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running)) | 844 | if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running)) |
| 826 | return; | 845 | return; |
| 827 | 846 | ||
| 847 | if (!rt_rq->rt_nr_running) | ||
| 848 | list_add_leaf_rt_rq(rt_rq); | ||
| 849 | |||
| 828 | if (head) | 850 | if (head) |
| 829 | list_add(&rt_se->run_list, queue); | 851 | list_add(&rt_se->run_list, queue); |
| 830 | else | 852 | else |
| @@ -844,6 +866,8 @@ static void __dequeue_rt_entity(struct sched_rt_entity *rt_se) | |||
| 844 | __clear_bit(rt_se_prio(rt_se), array->bitmap); | 866 | __clear_bit(rt_se_prio(rt_se), array->bitmap); |
| 845 | 867 | ||
| 846 | dec_rt_tasks(rt_se, rt_rq); | 868 | dec_rt_tasks(rt_se, rt_rq); |
| 869 | if (!rt_rq->rt_nr_running) | ||
| 870 | list_del_leaf_rt_rq(rt_rq); | ||
| 847 | } | 871 | } |
| 848 | 872 | ||
| 849 | /* | 873 | /* |
