diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sched.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 8f8a98eab9db..523e20a62695 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1515,30 +1515,29 @@ static unsigned long cpu_avg_load_per_task(int cpu) | |||
1515 | 1515 | ||
1516 | #ifdef CONFIG_FAIR_GROUP_SCHED | 1516 | #ifdef CONFIG_FAIR_GROUP_SCHED |
1517 | 1517 | ||
1518 | struct update_shares_data { | ||
1519 | unsigned long rq_weight[NR_CPUS]; | ||
1520 | }; | ||
1521 | |||
1522 | static DEFINE_PER_CPU(struct update_shares_data, update_shares_data); | ||
1523 | |||
1518 | static void __set_se_shares(struct sched_entity *se, unsigned long shares); | 1524 | static void __set_se_shares(struct sched_entity *se, unsigned long shares); |
1519 | 1525 | ||
1520 | /* | 1526 | /* |
1521 | * Calculate and set the cpu's group shares. | 1527 | * Calculate and set the cpu's group shares. |
1522 | */ | 1528 | */ |
1523 | static void | 1529 | static void update_group_shares_cpu(struct task_group *tg, int cpu, |
1524 | update_group_shares_cpu(struct task_group *tg, int cpu, | 1530 | unsigned long sd_shares, |
1525 | unsigned long sd_shares, unsigned long sd_rq_weight, | 1531 | unsigned long sd_rq_weight, |
1526 | unsigned long sd_eff_weight) | 1532 | struct update_shares_data *usd) |
1527 | { | 1533 | { |
1528 | unsigned long rq_weight; | 1534 | unsigned long shares, rq_weight; |
1529 | unsigned long shares; | ||
1530 | int boost = 0; | 1535 | int boost = 0; |
1531 | 1536 | ||
1532 | if (!tg->se[cpu]) | 1537 | rq_weight = usd->rq_weight[cpu]; |
1533 | return; | ||
1534 | |||
1535 | rq_weight = tg->cfs_rq[cpu]->rq_weight; | ||
1536 | if (!rq_weight) { | 1538 | if (!rq_weight) { |
1537 | boost = 1; | 1539 | boost = 1; |
1538 | rq_weight = NICE_0_LOAD; | 1540 | rq_weight = NICE_0_LOAD; |
1539 | if (sd_rq_weight == sd_eff_weight) | ||
1540 | sd_eff_weight += NICE_0_LOAD; | ||
1541 | sd_rq_weight = sd_eff_weight; | ||
1542 | } | 1541 | } |
1543 | 1542 | ||
1544 | /* | 1543 | /* |
@@ -1555,6 +1554,7 @@ update_group_shares_cpu(struct task_group *tg, int cpu, | |||
1555 | unsigned long flags; | 1554 | unsigned long flags; |
1556 | 1555 | ||
1557 | spin_lock_irqsave(&rq->lock, flags); | 1556 | spin_lock_irqsave(&rq->lock, flags); |
1557 | tg->cfs_rq[cpu]->rq_weight = boost ? 0 : rq_weight; | ||
1558 | tg->cfs_rq[cpu]->shares = boost ? 0 : shares; | 1558 | tg->cfs_rq[cpu]->shares = boost ? 0 : shares; |
1559 | __set_se_shares(tg->se[cpu], shares); | 1559 | __set_se_shares(tg->se[cpu], shares); |
1560 | spin_unlock_irqrestore(&rq->lock, flags); | 1560 | spin_unlock_irqrestore(&rq->lock, flags); |
@@ -1568,25 +1568,31 @@ update_group_shares_cpu(struct task_group *tg, int cpu, | |||
1568 | */ | 1568 | */ |
1569 | static int tg_shares_up(struct task_group *tg, void *data) | 1569 | static int tg_shares_up(struct task_group *tg, void *data) |
1570 | { | 1570 | { |
1571 | unsigned long weight, rq_weight = 0, eff_weight = 0; | 1571 | unsigned long weight, rq_weight = 0, shares = 0; |
1572 | unsigned long shares = 0; | 1572 | struct update_shares_data *usd; |
1573 | struct sched_domain *sd = data; | 1573 | struct sched_domain *sd = data; |
1574 | unsigned long flags; | ||
1574 | int i; | 1575 | int i; |
1575 | 1576 | ||
1577 | if (!tg->se[0]) | ||
1578 | return 0; | ||
1579 | |||
1580 | local_irq_save(flags); | ||
1581 | usd = &__get_cpu_var(update_shares_data); | ||
1582 | |||
1576 | for_each_cpu(i, sched_domain_span(sd)) { | 1583 | for_each_cpu(i, sched_domain_span(sd)) { |
1584 | weight = tg->cfs_rq[i]->load.weight; | ||
1585 | usd->rq_weight[i] = weight; | ||
1586 | |||
1577 | /* | 1587 | /* |
1578 | * If there are currently no tasks on the cpu pretend there | 1588 | * If there are currently no tasks on the cpu pretend there |
1579 | * is one of average load so that when a new task gets to | 1589 | * is one of average load so that when a new task gets to |
1580 | * run here it will not get delayed by group starvation. | 1590 | * run here it will not get delayed by group starvation. |
1581 | */ | 1591 | */ |
1582 | weight = tg->cfs_rq[i]->load.weight; | ||
1583 | tg->cfs_rq[i]->rq_weight = weight; | ||
1584 | rq_weight += weight; | ||
1585 | |||
1586 | if (!weight) | 1592 | if (!weight) |
1587 | weight = NICE_0_LOAD; | 1593 | weight = NICE_0_LOAD; |
1588 | 1594 | ||
1589 | eff_weight += weight; | 1595 | rq_weight += weight; |
1590 | shares += tg->cfs_rq[i]->shares; | 1596 | shares += tg->cfs_rq[i]->shares; |
1591 | } | 1597 | } |
1592 | 1598 | ||
@@ -1597,7 +1603,9 @@ static int tg_shares_up(struct task_group *tg, void *data) | |||
1597 | shares = tg->shares; | 1603 | shares = tg->shares; |
1598 | 1604 | ||
1599 | for_each_cpu(i, sched_domain_span(sd)) | 1605 | for_each_cpu(i, sched_domain_span(sd)) |
1600 | update_group_shares_cpu(tg, i, shares, rq_weight, eff_weight); | 1606 | update_group_shares_cpu(tg, i, shares, rq_weight, usd); |
1607 | |||
1608 | local_irq_restore(flags); | ||
1601 | 1609 | ||
1602 | return 0; | 1610 | return 0; |
1603 | } | 1611 | } |