diff options
| author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2008-08-19 06:33:05 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-08-19 07:10:11 -0400 |
| commit | eb755805f21bd5ded84026e167b7a90887ac42e5 (patch) | |
| tree | fab10d5e9189f93a5ee3f3f614ed1fbdbb34de6e /kernel | |
| parent | 0b148fa04852859972abbf848177b92daeef138a (diff) | |
sched: extract walk_tg_tree()
Extract walk_tg_tree() and make it a little more generic so we can use it
in the schedulablity test.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched.c | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index c1bee5fb8154..8c019a19d052 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -1387,38 +1387,24 @@ static inline void dec_cpu_load(struct rq *rq, unsigned long load) | |||
| 1387 | update_load_sub(&rq->load, load); | 1387 | update_load_sub(&rq->load, load); |
| 1388 | } | 1388 | } |
| 1389 | 1389 | ||
| 1390 | #ifdef CONFIG_SMP | 1390 | #if (defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)) |
| 1391 | static unsigned long source_load(int cpu, int type); | 1391 | typedef int (*tg_visitor)(struct task_group *, void *); |
| 1392 | static unsigned long target_load(int cpu, int type); | ||
| 1393 | static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd); | ||
| 1394 | |||
| 1395 | static unsigned long cpu_avg_load_per_task(int cpu) | ||
| 1396 | { | ||
| 1397 | struct rq *rq = cpu_rq(cpu); | ||
| 1398 | |||
| 1399 | if (rq->nr_running) | ||
| 1400 | rq->avg_load_per_task = rq->load.weight / rq->nr_running; | ||
| 1401 | |||
| 1402 | return rq->avg_load_per_task; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | #ifdef CONFIG_FAIR_GROUP_SCHED | ||
| 1406 | |||
| 1407 | typedef void (*tg_visitor)(struct task_group *, int, struct sched_domain *); | ||
| 1408 | 1392 | ||
| 1409 | /* | 1393 | /* |
| 1410 | * Iterate the full tree, calling @down when first entering a node and @up when | 1394 | * Iterate the full tree, calling @down when first entering a node and @up when |
| 1411 | * leaving it for the final time. | 1395 | * leaving it for the final time. |
| 1412 | */ | 1396 | */ |
| 1413 | static void | 1397 | static int walk_tg_tree(tg_visitor down, tg_visitor up, void *data) |
| 1414 | walk_tg_tree(tg_visitor down, tg_visitor up, int cpu, struct sched_domain *sd) | ||
| 1415 | { | 1398 | { |
| 1416 | struct task_group *parent, *child; | 1399 | struct task_group *parent, *child; |
| 1400 | int ret; | ||
| 1417 | 1401 | ||
| 1418 | rcu_read_lock(); | 1402 | rcu_read_lock(); |
| 1419 | parent = &root_task_group; | 1403 | parent = &root_task_group; |
| 1420 | down: | 1404 | down: |
| 1421 | (*down)(parent, cpu, sd); | 1405 | ret = (*down)(parent, data); |
| 1406 | if (ret) | ||
| 1407 | goto out_unlock; | ||
| 1422 | list_for_each_entry_rcu(child, &parent->children, siblings) { | 1408 | list_for_each_entry_rcu(child, &parent->children, siblings) { |
| 1423 | parent = child; | 1409 | parent = child; |
| 1424 | goto down; | 1410 | goto down; |
| @@ -1426,14 +1412,42 @@ down: | |||
| 1426 | up: | 1412 | up: |
| 1427 | continue; | 1413 | continue; |
| 1428 | } | 1414 | } |
| 1429 | (*up)(parent, cpu, sd); | 1415 | ret = (*up)(parent, data); |
| 1416 | if (ret) | ||
| 1417 | goto out_unlock; | ||
| 1430 | 1418 | ||
| 1431 | child = parent; | 1419 | child = parent; |
| 1432 | parent = parent->parent; | 1420 | parent = parent->parent; |
| 1433 | if (parent) | 1421 | if (parent) |
| 1434 | goto up; | 1422 | goto up; |
| 1423 | out_unlock: | ||
| 1435 | rcu_read_unlock(); | 1424 | rcu_read_unlock(); |
| 1425 | |||
| 1426 | return ret; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | static int tg_nop(struct task_group *tg, void *data) | ||
| 1430 | { | ||
| 1431 | return 0; | ||
| 1436 | } | 1432 | } |
| 1433 | #endif | ||
| 1434 | |||
| 1435 | #ifdef CONFIG_SMP | ||
| 1436 | static unsigned long source_load(int cpu, int type); | ||
| 1437 | static unsigned long target_load(int cpu, int type); | ||
| 1438 | static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd); | ||
| 1439 | |||
| 1440 | static unsigned long cpu_avg_load_per_task(int cpu) | ||
| 1441 | { | ||
| 1442 | struct rq *rq = cpu_rq(cpu); | ||
| 1443 | |||
| 1444 | if (rq->nr_running) | ||
| 1445 | rq->avg_load_per_task = rq->load.weight / rq->nr_running; | ||
| 1446 | |||
| 1447 | return rq->avg_load_per_task; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | #ifdef CONFIG_FAIR_GROUP_SCHED | ||
| 1437 | 1451 | ||
| 1438 | static void __set_se_shares(struct sched_entity *se, unsigned long shares); | 1452 | static void __set_se_shares(struct sched_entity *se, unsigned long shares); |
| 1439 | 1453 | ||
| @@ -1493,11 +1507,11 @@ __update_group_shares_cpu(struct task_group *tg, int cpu, | |||
| 1493 | * This needs to be done in a bottom-up fashion because the rq weight of a | 1507 | * This needs to be done in a bottom-up fashion because the rq weight of a |
| 1494 | * parent group depends on the shares of its child groups. | 1508 | * parent group depends on the shares of its child groups. |
| 1495 | */ | 1509 | */ |
| 1496 | static void | 1510 | static int tg_shares_up(struct task_group *tg, void *data) |
| 1497 | tg_shares_up(struct task_group *tg, int cpu, struct sched_domain *sd) | ||
| 1498 | { | 1511 | { |
| 1499 | unsigned long rq_weight = 0; | 1512 | unsigned long rq_weight = 0; |
| 1500 | unsigned long shares = 0; | 1513 | unsigned long shares = 0; |
| 1514 | struct sched_domain *sd = data; | ||
| 1501 | int i; | 1515 | int i; |
| 1502 | 1516 | ||
| 1503 | for_each_cpu_mask(i, sd->span) { | 1517 | for_each_cpu_mask(i, sd->span) { |
| @@ -1522,6 +1536,8 @@ tg_shares_up(struct task_group *tg, int cpu, struct sched_domain *sd) | |||
| 1522 | __update_group_shares_cpu(tg, i, shares, rq_weight); | 1536 | __update_group_shares_cpu(tg, i, shares, rq_weight); |
| 1523 | spin_unlock_irqrestore(&rq->lock, flags); | 1537 | spin_unlock_irqrestore(&rq->lock, flags); |
| 1524 | } | 1538 | } |
| 1539 | |||
| 1540 | return 0; | ||
| 1525 | } | 1541 | } |
| 1526 | 1542 | ||
| 1527 | /* | 1543 | /* |
| @@ -1529,10 +1545,10 @@ tg_shares_up(struct task_group *tg, int cpu, struct sched_domain *sd) | |||
| 1529 | * This needs to be done in a top-down fashion because the load of a child | 1545 | * This needs to be done in a top-down fashion because the load of a child |
| 1530 | * group is a fraction of its parents load. | 1546 | * group is a fraction of its parents load. |
| 1531 | */ | 1547 | */ |
| 1532 | static void | 1548 | static int tg_load_down(struct task_group *tg, void *data) |
| 1533 | tg_load_down(struct task_group *tg, int cpu, struct sched_domain *sd) | ||
| 1534 | { | 1549 | { |
| 1535 | unsigned long load; | 1550 | unsigned long load; |
| 1551 | long cpu = (long)data; | ||
| 1536 | 1552 | ||
| 1537 | if (!tg->parent) { | 1553 | if (!tg->parent) { |
| 1538 | load = cpu_rq(cpu)->load.weight; | 1554 | load = cpu_rq(cpu)->load.weight; |
| @@ -1543,11 +1559,8 @@ tg_load_down(struct task_group *tg, int cpu, struct sched_domain *sd) | |||
| 1543 | } | 1559 | } |
| 1544 | 1560 | ||
| 1545 | tg->cfs_rq[cpu]->h_load = load; | 1561 | tg->cfs_rq[cpu]->h_load = load; |
| 1546 | } | ||
| 1547 | 1562 | ||
| 1548 | static void | 1563 | return 0; |
| 1549 | tg_nop(struct task_group *tg, int cpu, struct sched_domain *sd) | ||
| 1550 | { | ||
| 1551 | } | 1564 | } |
| 1552 | 1565 | ||
| 1553 | static void update_shares(struct sched_domain *sd) | 1566 | static void update_shares(struct sched_domain *sd) |
| @@ -1557,7 +1570,7 @@ static void update_shares(struct sched_domain *sd) | |||
| 1557 | 1570 | ||
| 1558 | if (elapsed >= (s64)(u64)sysctl_sched_shares_ratelimit) { | 1571 | if (elapsed >= (s64)(u64)sysctl_sched_shares_ratelimit) { |
| 1559 | sd->last_update = now; | 1572 | sd->last_update = now; |
| 1560 | walk_tg_tree(tg_nop, tg_shares_up, 0, sd); | 1573 | walk_tg_tree(tg_nop, tg_shares_up, sd); |
| 1561 | } | 1574 | } |
| 1562 | } | 1575 | } |
| 1563 | 1576 | ||
| @@ -1568,9 +1581,9 @@ static void update_shares_locked(struct rq *rq, struct sched_domain *sd) | |||
| 1568 | spin_lock(&rq->lock); | 1581 | spin_lock(&rq->lock); |
| 1569 | } | 1582 | } |
| 1570 | 1583 | ||
| 1571 | static void update_h_load(int cpu) | 1584 | static void update_h_load(long cpu) |
| 1572 | { | 1585 | { |
| 1573 | walk_tg_tree(tg_load_down, tg_nop, cpu, NULL); | 1586 | walk_tg_tree(tg_load_down, tg_nop, (void *)cpu); |
| 1574 | } | 1587 | } |
| 1575 | 1588 | ||
| 1576 | #else | 1589 | #else |
