[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen stable-4.9] cpufreq/ondemand: fix race while offlining CPU
commit 3620279d776a8ab7806546d046040307418a764e Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Tue Mar 20 14:34:24 2018 +0100 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Mar 20 14:34:24 2018 +0100 cpufreq/ondemand: fix race while offlining CPU Offlining a CPU involves stopping the cpufreq governor. The on-demand governor will kill the timer before letting generic code proceed, but since that generally isn't happening on the subject CPU, cpufreq_dbs_timer_resume() may run in parallel. If that managed to invoke the timer handler, that handler needs to run to completion before dbs_timer_exit() may safely exit. Make the "stoppable" field a tristate, changing it from +1 to -1 around the timer function invocation, and make dbs_timer_exit() wait for it to become non-negative (still writing zero if it's +1). Also adjust coding style in cpufreq_dbs_timer_resume(). Reported-by: Martin Cerveny <martin@xxxxxxxxx> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Tested-by: Martin Cerveny <martin@xxxxxxxxx> Reviewed-by: Wei Liu <wei.liu2@xxxxxxxxxx> master commit: 185413355fe331cbc926d48568838227234c9a20 master date: 2018-03-09 17:30:49 +0100 --- xen/drivers/cpufreq/cpufreq_ondemand.c | 32 +++++++++++++++++++------------- xen/include/acpi/cpufreq/cpufreq.h | 2 +- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/xen/drivers/cpufreq/cpufreq_ondemand.c b/xen/drivers/cpufreq/cpufreq_ondemand.c index fe6c63da8e..6b905d7cfc 100644 --- a/xen/drivers/cpufreq/cpufreq_ondemand.c +++ b/xen/drivers/cpufreq/cpufreq_ondemand.c @@ -204,7 +204,14 @@ static void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) static void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) { dbs_info->enable = 0; - dbs_info->stoppable = 0; + + /* + * The timer function may be running (from cpufreq_dbs_timer_resume) - + * wait for it to complete. + */ + while ( cmpxchg(&dbs_info->stoppable, 1, 0) < 0 ) + cpu_relax(); + kill_timer(&per_cpu(dbs_timer, dbs_info->cpu)); } @@ -369,23 +376,22 @@ void cpufreq_dbs_timer_suspend(void) void cpufreq_dbs_timer_resume(void) { - int cpu; - struct timer* t; - s_time_t now; + unsigned int cpu = smp_processor_id(); + int8_t *stoppable = &per_cpu(cpu_dbs_info, cpu).stoppable; - cpu = smp_processor_id(); - - if ( per_cpu(cpu_dbs_info,cpu).stoppable ) + if ( *stoppable ) { - now = NOW(); - t = &per_cpu(dbs_timer, cpu); - if (t->expires <= now) + s_time_t now = NOW(); + struct timer *t = &per_cpu(dbs_timer, cpu); + + if ( t->expires <= now ) { + if ( !cmpxchg(stoppable, 1, -1) ) + return; t->function(t->data); + (void)cmpxchg(stoppable, -1, 1); } else - { - set_timer(t, align_timer(now , dbs_tuners_ins.sampling_rate)); - } + set_timer(t, align_timer(now, dbs_tuners_ins.sampling_rate)); } } diff --git a/xen/include/acpi/cpufreq/cpufreq.h b/xen/include/acpi/cpufreq/cpufreq.h index 48ad1d0004..c26aa8dee8 100644 --- a/xen/include/acpi/cpufreq/cpufreq.h +++ b/xen/include/acpi/cpufreq/cpufreq.h @@ -227,8 +227,8 @@ struct cpu_dbs_info_s { struct cpufreq_frequency_table *freq_table; int cpu; unsigned int enable:1; - unsigned int stoppable:1; unsigned int turbo_enabled:1; + int8_t stoppable; }; int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event); -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.9 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |