sched/core: Do not free task while holding rq lock

Clearing the hmp request can cause a task to be freed. When a task is
freed the free call might wake up a kworker which will cause a
spinlock lockup (rq lock). Fix this by avoiding calling put_task_struct
when holding the rq lock.

In addition move call to clear_hmp_request out of stopper thread context
since it is not necessary to do this on the cpu being isolated.

Change-Id: Ie577db4701a88849560df385869ff7cf73695a05
Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
This commit is contained in:
Olav Haugan 2016-11-27 19:17:28 -08:00
parent 841264c505
commit e5c095a2c7
2 changed files with 6 additions and 2 deletions

View file

@ -5600,7 +5600,6 @@ int do_isolation_work_cpu_stop(void *data)
*/
nohz_balance_clear_nohz_mask(cpu);
clear_hmp_request(cpu);
local_irq_enable();
return 0;
}
@ -5725,6 +5724,7 @@ int sched_isolate_cpu(int cpu)
migrate_sync_cpu(cpu, cpumask_first(&avail_cpus));
stop_cpus(cpumask_of(cpu), do_isolation_work_cpu_stop, 0);
clear_hmp_request(cpu);
calc_load_migrate(rq);
update_max_interval();

View file

@ -641,14 +641,18 @@ void clear_hmp_request(int cpu)
clear_boost_kick(cpu);
clear_reserved(cpu);
if (rq->push_task) {
struct task_struct *push_task = NULL;
raw_spin_lock_irqsave(&rq->lock, flags);
if (rq->push_task) {
clear_reserved(rq->push_cpu);
put_task_struct(rq->push_task);
push_task = rq->push_task;
rq->push_task = NULL;
}
rq->active_balance = 0;
raw_spin_unlock_irqrestore(&rq->lock, flags);
if (push_task)
put_task_struct(push_task);
}
}