forked from Minki/linux
d0b7306d20
When multiple thermal zones are bound to the same cooling device, multiple kernel threads may want to update the cooling device state by calling thermal_cdev_update(). Having cdev not protected by a mutex can lead to a race condition. Consider the following situation with two kernel threads k1 and k2: Thread k1 Thread k2 || || call thermal_cdev_update() || ... || set_cur_state(cdev, target); call power_actor_set_power() || ... || instance->target = state; || cdev->updated = false; || || cdev->updated = true; || // completes execution call thermal_cdev_update() || // cdev->updated == true || return; || \/ time k2 has already looped through the thermal instances looking for the deepest cooling device state and is preempted right before setting cdev->updated to true. Now, k1 runs, modifies the thermal instance state and sets cdev->updated to false. Then, k1 is preempted and k2 continues the execution by setting cdev->updated to true, therefore preventing k1 from performing the update. Notice that this is not an issue if k2 looks at the instance->target modified by k1 "after" it is assigned by k1. In fact, in this case the update will happen anyway and k1 can safely return immediately from thermal_cdev_update(). This may lead to a situation where a thermal governor never updates the cooling device. For example, this is the case for the step_wise governor: when calling the function thermal_zone_trip_update(), the governor may always get a new state equal to the old one (which, however, wasn't notified to the cooling device) and will therefore skip the update. CC: Zhang Rui <rui.zhang@intel.com> CC: Eduardo Valentin <edubezval@gmail.com> CC: Peter Feuerer <peter@piie.net> Reported-by: Toby Huang <toby.huang@arm.com> Signed-off-by: Michele Di Giorgio <michele.digiorgio@arm.com> Reviewed-by: Javi Merino <javi.merino@arm.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> |
||
---|---|---|
.. | ||
int340x_thermal | ||
samsung | ||
st | ||
tegra | ||
ti-soc-thermal | ||
armada_thermal.c | ||
clock_cooling.c | ||
cpu_cooling.c | ||
db8500_cpufreq_cooling.c | ||
db8500_thermal.c | ||
devfreq_cooling.c | ||
dove_thermal.c | ||
fair_share.c | ||
gov_bang_bang.c | ||
hisi_thermal.c | ||
imx_thermal.c | ||
intel_pch_thermal.c | ||
intel_powerclamp.c | ||
intel_quark_dts_thermal.c | ||
intel_soc_dts_iosf.c | ||
intel_soc_dts_iosf.h | ||
intel_soc_dts_thermal.c | ||
Kconfig | ||
kirkwood_thermal.c | ||
Makefile | ||
mtk_thermal.c | ||
of-thermal.c | ||
power_allocator.c | ||
qcom-spmi-temp-alarm.c | ||
rcar_thermal.c | ||
rockchip_thermal.c | ||
spear_thermal.c | ||
step_wise.c | ||
tango_thermal.c | ||
thermal_core.c | ||
thermal_core.h | ||
thermal_hwmon.c | ||
thermal_hwmon.h | ||
thermal-generic-adc.c | ||
user_space.c | ||
x86_pkg_temp_thermal.c |