diff options
author | Konstantin Khlebnikov <khlebnikov@openvz.org> | 2012-12-14 18:22:02 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-03 07:11:18 -0500 |
commit | 56836fb4dab8fe906b934b231b04c33c180f8da5 (patch) | |
tree | 4ad98361223482eeb8b0f3a4485b7bb4ba4c012d /drivers/cpufreq/cpufreq_stats.c | |
parent | d1c3ed669a2d452cacfb48c2d171a1f364dae2ed (diff) |
cpufreq / stats: fix race between stats allocation and first usage
This patch forces complete struct cpufreq_stats allocation for all cpus before
registering CPUFREQ_TRANSITION_NOTIFIER notifier, otherwise in some conditions
cpufreq_stat_notifier_trans() can be called in the middle of stats allocation,
in this case cpufreq_stats_table already exists, but stat->freq_table is NULL.
Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cpufreq_stats.c')
-rw-r--r-- | drivers/cpufreq/cpufreq_stats.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index e40e50809644..9d7732b81044 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
@@ -364,18 +364,21 @@ static int __init cpufreq_stats_init(void) | |||
364 | if (ret) | 364 | if (ret) |
365 | return ret; | 365 | return ret; |
366 | 366 | ||
367 | register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); | ||
368 | for_each_online_cpu(cpu) | ||
369 | cpufreq_update_policy(cpu); | ||
370 | |||
367 | ret = cpufreq_register_notifier(¬ifier_trans_block, | 371 | ret = cpufreq_register_notifier(¬ifier_trans_block, |
368 | CPUFREQ_TRANSITION_NOTIFIER); | 372 | CPUFREQ_TRANSITION_NOTIFIER); |
369 | if (ret) { | 373 | if (ret) { |
370 | cpufreq_unregister_notifier(¬ifier_policy_block, | 374 | cpufreq_unregister_notifier(¬ifier_policy_block, |
371 | CPUFREQ_POLICY_NOTIFIER); | 375 | CPUFREQ_POLICY_NOTIFIER); |
376 | unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); | ||
377 | for_each_online_cpu(cpu) | ||
378 | cpufreq_stats_free_table(cpu); | ||
372 | return ret; | 379 | return ret; |
373 | } | 380 | } |
374 | 381 | ||
375 | register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); | ||
376 | for_each_online_cpu(cpu) { | ||
377 | cpufreq_update_policy(cpu); | ||
378 | } | ||
379 | return 0; | 382 | return 0; |
380 | } | 383 | } |
381 | static void __exit cpufreq_stats_exit(void) | 384 | static void __exit cpufreq_stats_exit(void) |