ARM64: sched: fix bug: avoid infinite loop
authorChen Liang <cl@rock-chips.com>
Fri, 8 Jul 2016 02:12:43 +0000 (10:12 +0800)
committerChen Liang <cl@rock-chips.com>
Mon, 11 Jul 2016 09:08:55 +0000 (17:08 +0800)
All of the sched domains will be destroied and then rebuilded when a cpu
online/offline, if a softirq comes after the shced domains are destroied,
this cpu will be stucked in the infinite loop in sched_group_energy(),
because of it can not get the shced donmain in for_each_domain(cpu, sd).

Change-Id: I154cf560e4e1af4a7a2547154ad321e936196ce3
Signed-off-by: Chen Liang <cl@rock-chips.com>
kernel/sched/fair.c

index 6d84df9366edaa0535b24636ad41f3f4d6a36d37..67629fa15d58e44b72c428afdb37cf31024381d5 100644 (file)
@@ -4866,6 +4866,7 @@ static int sched_group_energy(struct energy_env *eenv)
                struct sched_group *sg_shared_cap = NULL;
 
                cpu = cpumask_first(&visit_cpus);
                struct sched_group *sg_shared_cap = NULL;
 
                cpu = cpumask_first(&visit_cpus);
+               cpumask_clear_cpu(cpu, &visit_cpus);
 
                /*
                 * Is the group utilization affected by cpus outside this
 
                /*
                 * Is the group utilization affected by cpus outside this
@@ -4928,8 +4929,12 @@ static int sched_group_energy(struct energy_env *eenv)
 
                                total_energy += sg_busy_energy + sg_idle_energy;
 
 
                                total_energy += sg_busy_energy + sg_idle_energy;
 
-                               if (!sd->child)
-                                       cpumask_xor(&visit_cpus, &visit_cpus, sched_group_cpus(sg));
+                               if (!sd->child) {
+                                       int i;
+
+                                       for_each_cpu(i, sched_group_cpus(sg))
+                                               cpumask_clear_cpu(i, &visit_cpus);
+                               }
 
                                if (cpumask_equal(sched_group_cpus(sg), sched_group_cpus(eenv->sg_top)))
                                        goto next_cpu;
 
                                if (cpumask_equal(sched_group_cpus(sg), sched_group_cpus(eenv->sg_top)))
                                        goto next_cpu;