diff options
| author | Pavankumar Kondeti <pkondeti@codeaurora.org> | 2016-01-28 16:19:17 +0530 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 21:30:42 -0700 |
| commit | bd887e4a589d5fcd3e20ebc2a75fd59b889a3640 (patch) | |
| tree | 6b0b4feeefc1520b6c0990eb9ed6ad790c4b5dac /kernel | |
| parent | 7a649da27817813c3c89dff59797f083acf30004 (diff) | |
sched: fix circular dependency of rq->lock and kswadp waitqueue lock
There is a deadlock scenario due to the circular dependency of CPU's
rq->lock and kswapd's waitqueue lock.
(1) when kswapd is woken up, try_to_wake_up() is called with it's
waitqueue lock held. It's previous CPU is offline, so it is woken
up on a different CPU. We try to acquire the offline CPU's rq->lock
in either cpufreq change callback or fixup_busy_time()
(2) At the same time, the offline CPU is coming online and init_idle()
is called from __cpu_up(). init_idle() calls __sched_fork() with
rq->lock held. A debug object allocation in hrtimer_init() called
from __sched_fork() is trying to wakeup the kswapd and attempts to
take the waitqueue lock held in the (1) path.
Task specific initialization is done in __sched_fork() and rq->lock
is not held when it is called for other tasks. The same holds true for
the idle task as well. __sched_fork() for the idle task is called only
when the CPU is not active.
Acquire the rq->lock after calling __sched_fork() in init_idle()
to fix this deadlock.
CRs-Fixed: 965873
Change-Id: Ib8a265835c29861dba571c9b2a6b7e75b5cb43ee
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
[satyap: trivial merge conflicts resolution and omitted changes for QHMP]
Signed-off-by: Satya Durga Srinivasu Prabhala <satyap@codeaurora.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched/core.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index d40ace8eafee..8f14efd8ea06 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7868,10 +7868,11 @@ void init_idle(struct task_struct *idle, int cpu) struct rq *rq = cpu_rq(cpu); unsigned long flags; + __sched_fork(0, idle); + raw_spin_lock_irqsave(&idle->pi_lock, flags); raw_spin_lock(&rq->lock); - __sched_fork(0, idle); idle->state = TASK_RUNNING; idle->se.exec_start = sched_clock(); |
