diff options
author | Pavankumar Kondeti <pkondeti@codeaurora.org> | 2016-12-22 19:21:42 +0530 |
---|---|---|
committer | Pavankumar Kondeti <pkondeti@codeaurora.org> | 2016-12-30 12:31:01 +0530 |
commit | f67dcbea7f75a70601ac408416e572eac3f7d272 (patch) | |
tree | c2c0653503d7b83f876efbb75e8cf36d85028c17 /kernel/sched/hmp.c | |
parent | 55e8426a192811d7567f19d7e781727f46b0406d (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.c | 27 |
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; } |