aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/sched.c64
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
4715static 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
4738static 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