cpufreq: governor: Fix race in dbs_update_util_handler()
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 22 Feb 2016 13:14:34 +0000 (14:14 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 9 Mar 2016 13:41:10 +0000 (14:41 +0100)
commit27de34823984e844f5dc042d39bb43f5dc98966f
treeadf647f0f42df0e3ef274b3035bd8bd3c04cabcd
parent94ab5e030fe10cfcc700050cc21535b824943077
cpufreq: governor: Fix race in dbs_update_util_handler()

There is a scenario that may lead to undesired results in
dbs_update_util_handler().  Namely, if two CPUs sharing a policy
enter the funtion at the same time, pass the sample delay check
and then one of them is stalled until dbs_work_handler() (queued
up by the other CPU) clears the work counter, it may update the
work counter and queue up another work item prematurely.

To prevent that from happening, use the observation that the CPU
queuing up a work item in dbs_update_util_handler() updates the
last sample time.  This means that if another CPU was stalling after
passing the sample delay check and now successfully updated the work
counter as a result of the race described above, it will see the new
value of the last sample time which is different from what it used in
the sample delay check before.  If that happens, the sample delay
check passed previously is not valid any more, so the CPU should not
continue.

Fixes: f17cbb53783c (cpufreq: governor: Avoid atomic operations in hot paths)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
drivers/cpufreq/cpufreq_governor.c