Race condition in cpufreq
Arun KS <[email protected]> Wed, 19 Nov 2014 11:25:21 +0530
| Newsgroups | org.kernel.vger.cpufreq |
|---|---|
| Message-ID | <CAKZGPAMLm0iHRgfojbxP+Tzbt4eUFovM3NYz83Lnexw3G2QiYA@mail.gmail.com> |
Hello,
Seen a race condition in cpufrequency driver.
cpu2 is being hot-plugged out. And this started at say, 20th msec.
-000|context_switch(inline)
-000|need_resched()
-001|preempt_schedule(inline)
-001|preempt_schedule()
-002|static_key_false(inline)
-002|trace_sched_cpu_hotplug(inline)
-002|cpu_down(cpu = 2, ?)
-003|cpu_down(cpu = 2)
-004|update_offline_cores(?)
-005|do_hotplug(?)
-006|kthread(_create = 0xEE85BEBC)
cpu1 is updating the governor at say 60th msec.
echo "some_governor" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
at 60th msec, cpu2 is already hot-plugged but CPU_POST_DEAD has not
called because __cpu_down was scheduled out at cpu_hotplug_done(while
unlocking mutex)
now store_scaling_governor calls cpufreq_set_policy
CPUFREQ_GOV_START iterates through all cpus in policy->cpus(which is
not the correct one now, because cpu2 is already hot-plugged out(DEAD)
but not updated in policy->cpus).
One suggestion is to use CPU_DEAD instead of CPU_POST_DEAD in cpufreq.c
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 644b54e..5fdaf06 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2325,7 +2325,7 @@ static int cpufreq_cpu_callback(struct
notifier_block *nfb,
__cpufreq_remove_dev_prepare(dev, NULL);
break;
- case CPU_POST_DEAD:
+ case CPU_DEAD:
__cpufreq_remove_dev_finish(dev, NULL);
break;
Or add a mutex to serialize the context.
Appreciate your valuable comments.
Thanks,
Arun