diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 77c07c2928b9..e75b301b5340 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -4712,6 +4712,57 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu) | |||
4712 | #define sched_domain_debug(sd, cpu) {} | 4712 | #define sched_domain_debug(sd, cpu) {} |
4713 | #endif | 4713 | #endif |
4714 | 4714 | ||
4715 | static int __devinit sd_degenerate(struct sched_domain *sd) | ||
4716 | { | ||
4717 | if (cpus_weight(sd->span) == 1) | ||
4718 | return 1; | ||
4719 | |||
4720 | /* Following flags need at least 2 groups */ | ||
4721 | if (sd->flags & (SD_LOAD_BALANCE | | ||
4722 | SD_BALANCE_NEWIDLE | | ||
4723 | SD_BALANCE_FORK | | ||
4724 | SD_BALANCE_EXEC)) { | ||
4725 | if (sd->groups != sd->groups->next) | ||
4726 | return 0; | ||
4727 | } | ||
4728 | |||
4729 | /* Following flags don't use groups */ | ||
4730 | if (sd->flags & (SD_WAKE_IDLE | | ||
4731 | SD_WAKE_AFFINE | | ||
4732 | SD_WAKE_BALANCE)) | ||
4733 | return 0; | ||
4734 | |||
4735 | return 1; | ||
4736 | } | ||
4737 | |||
4738 | static int __devinit sd_parent_degenerate(struct sched_domain *sd, | ||
4739 | struct sched_domain *parent) | ||
4740 | { | ||
4741 | unsigned long cflags = sd->flags, pflags = parent->flags; | ||
4742 | |||
4743 | if (sd_degenerate(parent)) | ||
4744 | return 1; | ||
4745 | |||
4746 | if (!cpus_equal(sd->span, parent->span)) | ||
4747 | return 0; | ||
4748 | |||
4749 | /* Does parent contain flags not in child? */ | ||
4750 | /* WAKE_BALANCE is a subset of WAKE_AFFINE */ | ||
4751 | if (cflags & SD_WAKE_AFFINE) | ||
4752 | pflags &= ~SD_WAKE_BALANCE; | ||
4753 | /* Flags needing groups don't count if only 1 group in parent */ | ||
4754 | if (parent->groups == parent->groups->next) { | ||
4755 | pflags &= ~(SD_LOAD_BALANCE | | ||
4756 | SD_BALANCE_NEWIDLE | | ||
4757 | SD_BALANCE_FORK | | ||
4758 | SD_BALANCE_EXEC); | ||
4759 | } | ||
4760 | if (~cflags & pflags) | ||
4761 | return 0; | ||
4762 | |||
4763 | return 1; | ||
4764 | } | ||
4765 | |||
4715 | /* | 4766 | /* |
4716 | * Attach the domain 'sd' to 'cpu' as its base domain. Callers must | 4767 | * Attach the domain 'sd' to 'cpu' as its base domain. Callers must |
4717 | * hold the hotplug lock. | 4768 | * hold the hotplug lock. |
@@ -4722,6 +4773,19 @@ void __devinit cpu_attach_domain(struct sched_domain *sd, int cpu) | |||
4722 | unsigned long flags; | 4773 | unsigned long flags; |
4723 | runqueue_t *rq = cpu_rq(cpu); | 4774 | runqueue_t *rq = cpu_rq(cpu); |
4724 | int local = 1; | 4775 | int local = 1; |
4776 | struct sched_domain *tmp; | ||
4777 | |||
4778 | /* Remove the sched domains which do not contribute to scheduling. */ | ||
4779 | for (tmp = sd; tmp; tmp = tmp->parent) { | ||
4780 | struct sched_domain *parent = tmp->parent; | ||
4781 | if (!parent) | ||
4782 | break; | ||
4783 | if (sd_parent_degenerate(tmp, parent)) | ||
4784 | tmp->parent = parent->parent; | ||
4785 | } | ||
4786 | |||
4787 | if (sd && sd_degenerate(sd)) | ||
4788 | sd = sd->parent; | ||
4725 | 4789 | ||
4726 | sched_domain_debug(sd, cpu); | 4790 | sched_domain_debug(sd, cpu); |
4727 | 4791 | ||