sched: fix rq->lock recursion

Enabling SCHED_HRTICK currently results in rq->lock recursion and a hard
hang at bootup.  Essentially try_to_wakeup() grabs rq->lock and tries
arming a hrtimer via hrtimer_restart(), which deep down tries waking up
ksoftirqd, which leads to a recursive call to try_to_wakeup() and thus
attempt to take rq->lock recursively!!

This is fixed by having scheduler queue hrtimer via
__hrtimer_start_range_ns() which avoids waking up ksoftirqd.

Signed-off-by: Srivatsa Vaddagiri <vatsa@codeaurora.org>
Change-Id: I11a13be1d9db3a749614ccf3d4f5fb7bf6f18fa1
(cherry picked from commit 4ca1d04ea0bdc225cc7db302172f3375a63f44de)
This commit is contained in:
Srivatsa Vaddagiri 2012-11-28 15:50:20 -08:00 committed by Rohit Vaswani
parent 90b392ea77
commit 948432de62

View file

@ -401,9 +401,16 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer)
static void __hrtick_start(void *arg)
{
struct rq *rq = arg;
struct hrtimer *timer = &rq->hrtick_timer;
ktime_t soft, hard;
unsigned long delta;
soft = hrtimer_get_softexpires(timer);
hard = hrtimer_get_expires(timer);
delta = ktime_to_ns(ktime_sub(hard, soft));
raw_spin_lock(&rq->lock);
hrtimer_restart(&rq->hrtick_timer);
__hrtimer_start_range_ns(timer, soft, delta, HRTIMER_MODE_ABS, 0);
rq->hrtick_csd_pending = 0;
raw_spin_unlock(&rq->lock);
}
@ -421,7 +428,8 @@ void hrtick_start(struct rq *rq, u64 delay)
hrtimer_set_expires(timer, time);
if (rq == this_rq()) {
hrtimer_restart(timer);
__hrtimer_start_range_ns(timer, ns_to_ktime(delay), 0,
HRTIMER_MODE_REL_PINNED, 0);
} else if (!rq->hrtick_csd_pending) {
__smp_call_function_single(cpu_of(rq), &rq->hrtick_csd, 0);
rq->hrtick_csd_pending = 1;