Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d267f87f authored by Venkatesh Pallipadi's avatar Venkatesh Pallipadi Committed by Ingo Molnar
Browse files

sched: Call tick_check_idle before __irq_enter



When CPU is idle and on first interrupt, irq_enter calls tick_check_idle()
to notify interruption from idle. But, there is a problem if this call
is done after __irq_enter, as all routines in __irq_enter may find
stale time due to yet to be done tick_check_idle.

Specifically, trace calls in __irq_enter when they use global clock and also
account_system_vtime change in this patch as it wants to use sched_clock_cpu()
to do proper irq timing.

But, tick_check_idle was moved after __irq_enter intentionally to
prevent problem of unneeded ksoftirqd wakeups by the commit ee5f80a9:

    irq: call __irq_enter() before calling the tick_idle_check
    Impact: avoid spurious ksoftirqd wakeups

Moving tick_check_idle() before __irq_enter and wrapping it with
local_bh_enable/disable would solve both the problems.

Fixed-by: default avatarYong Zhang <yong.zhang0@gmail.com>
Signed-off-by: default avatarVenkatesh Pallipadi <venki@google.com>
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <1286237003-12406-9-git-send-email-venki@google.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent aa483808
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1974,8 +1974,8 @@ void account_system_vtime(struct task_struct *curr)

	local_irq_save(flags);

	now = sched_clock();
	cpu = smp_processor_id();
	now = sched_clock_cpu(cpu);
	delta = now - per_cpu(irq_start_time, cpu);
	per_cpu(irq_start_time, cpu) = now;
	/*
+9 −3
Original line number Diff line number Diff line
@@ -296,9 +296,15 @@ void irq_enter(void)

	rcu_irq_enter();
	if (idle_cpu(cpu) && !in_interrupt()) {
		__irq_enter();
		/*
		 * Prevent raise_softirq from needlessly waking up ksoftirqd
		 * here, as softirq will be serviced on return from interrupt.
		 */
		local_bh_disable();
		tick_check_idle(cpu);
	} else
		_local_bh_enable();
	}

	__irq_enter();
}