]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/sched.c
[PATCH] sched: remove degenerate domains
[linux-2.6-omap-h63xx.git] / kernel / sched.c
index 77c07c2928b9488a9ad28498527ba20d774ef1ba..e75b301b5340b91ac5dbdc9c2b22e958366744d0 100644 (file)
@@ -4712,6 +4712,57 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
 #define sched_domain_debug(sd, cpu) {}
 #endif
 
+static int __devinit sd_degenerate(struct sched_domain *sd)
+{
+       if (cpus_weight(sd->span) == 1)
+               return 1;
+
+       /* Following flags need at least 2 groups */
+       if (sd->flags & (SD_LOAD_BALANCE |
+                        SD_BALANCE_NEWIDLE |
+                        SD_BALANCE_FORK |
+                        SD_BALANCE_EXEC)) {
+               if (sd->groups != sd->groups->next)
+                       return 0;
+       }
+
+       /* Following flags don't use groups */
+       if (sd->flags & (SD_WAKE_IDLE |
+                        SD_WAKE_AFFINE |
+                        SD_WAKE_BALANCE))
+               return 0;
+
+       return 1;
+}
+
+static int __devinit sd_parent_degenerate(struct sched_domain *sd,
+                                               struct sched_domain *parent)
+{
+       unsigned long cflags = sd->flags, pflags = parent->flags;
+
+       if (sd_degenerate(parent))
+               return 1;
+
+       if (!cpus_equal(sd->span, parent->span))
+               return 0;
+
+       /* Does parent contain flags not in child? */
+       /* WAKE_BALANCE is a subset of WAKE_AFFINE */
+       if (cflags & SD_WAKE_AFFINE)
+               pflags &= ~SD_WAKE_BALANCE;
+       /* Flags needing groups don't count if only 1 group in parent */
+       if (parent->groups == parent->groups->next) {
+               pflags &= ~(SD_LOAD_BALANCE |
+                               SD_BALANCE_NEWIDLE |
+                               SD_BALANCE_FORK |
+                               SD_BALANCE_EXEC);
+       }
+       if (~cflags & pflags)
+               return 0;
+
+       return 1;
+}
+
 /*
  * Attach the domain 'sd' to 'cpu' as its base domain.  Callers must
  * hold the hotplug lock.
@@ -4722,6 +4773,19 @@ void __devinit cpu_attach_domain(struct sched_domain *sd, int cpu)
        unsigned long flags;
        runqueue_t *rq = cpu_rq(cpu);
        int local = 1;
+       struct sched_domain *tmp;
+
+       /* Remove the sched domains which do not contribute to scheduling. */
+       for (tmp = sd; tmp; tmp = tmp->parent) {
+               struct sched_domain *parent = tmp->parent;
+               if (!parent)
+                       break;
+               if (sd_parent_degenerate(tmp, parent))
+                       tmp->parent = parent->parent;
+       }
+
+       if (sd && sd_degenerate(sd))
+               sd = sd->parent;
 
        sched_domain_debug(sd, cpu);