summaryrefslogtreecommitdiff
path: root/kernel/sched/hmp.c
diff options
context:
space:
mode:
authorPavankumar Kondeti <pkondeti@codeaurora.org>2016-12-22 19:21:42 +0530
committerPavankumar Kondeti <pkondeti@codeaurora.org>2016-12-30 12:31:01 +0530
commitf67dcbea7f75a70601ac408416e572eac3f7d272 (patch)
treec2c0653503d7b83f876efbb75e8cf36d85028c17 /kernel/sched/hmp.c
parent55e8426a192811d7567f19d7e781727f46b0406d (diff)
sched: Fix deadlock between cpu hotplug and upmigrate change
There is a circular dependency between cpu_hotplug.lock and HMP scheduler policy mutex. Prevent this by enforcing the same lock order. Here CPU0 and CPU4 are governed by different cpufreq policies. ---------------- -------------------- CPU 0 CPU 4 --------------- -------------------- proc_sys_call_handler() cpu_up() --> acquired cpu_hotplug.lock sched_hmp_proc_update_handler() cpufreq_cpu_callback() --> acquired policy_mutex cpufreq_governor_interactive() get_online_cpus() sched_set_window() --> waiting for cpu_hotplug.lock --> waiting for policy_mutex Change-Id: I39efc394f4f00815b72adc975021fdb16fe6e30a Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
Diffstat (limited to 'kernel/sched/hmp.c')
-rw-r--r--kernel/sched/hmp.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c
index a8bf39c6d7d7..ab5587309760 100644
--- a/kernel/sched/hmp.c
+++ b/kernel/sched/hmp.c
@@ -1470,7 +1470,20 @@ int sched_hmp_proc_update_handler(struct ctl_table *table, int write,
int ret;
unsigned int old_val;
unsigned int *data = (unsigned int *)table->data;
- int update_min_nice = 0;
+ int update_task_count = 0;
+
+ if (!sched_enable_hmp)
+ return 0;
+
+ /*
+ * The policy mutex is acquired with cpu_hotplug.lock
+ * held from cpu_up()->cpufreq_governor_interactive()->
+ * sched_set_window(). So enforce the same order here.
+ */
+ if (write && (data == &sysctl_sched_upmigrate_pct)) {
+ update_task_count = 1;
+ get_online_cpus();
+ }
mutex_lock(&policy_mutex);
@@ -1478,7 +1491,7 @@ int sched_hmp_proc_update_handler(struct ctl_table *table, int write,
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
- if (ret || !write || !sched_enable_hmp)
+ if (ret || !write)
goto done;
if (write && (old_val == *data))
@@ -1500,20 +1513,18 @@ int sched_hmp_proc_update_handler(struct ctl_table *table, int write,
* includes taking runqueue lock of all online cpus and re-initiatizing
* their big counter values based on changed criteria.
*/
- if ((data == &sysctl_sched_upmigrate_pct || update_min_nice)) {
- get_online_cpus();
+ if (update_task_count)
pre_big_task_count_change(cpu_online_mask);
- }
set_hmp_defaults();
- if ((data == &sysctl_sched_upmigrate_pct || update_min_nice)) {
+ if (update_task_count)
post_big_task_count_change(cpu_online_mask);
- put_online_cpus();
- }
done:
mutex_unlock(&policy_mutex);
+ if (update_task_count)
+ put_online_cpus();
return ret;
}