On Tue, 26 Dec 2017, Frederic Weisbecker wrote:
On Fri, Dec 22, 2017 at 03:51:13PM +0100, Thomas Gleixner wrote:
The conditions in irq_exit() to invoke tick_nohz_irq_exit() are:
if ((idle_cpu(cpu) && !need_resched()) || tick_nohz_full_cpu(cpu))
This is too permissive in various aspects:
- If need_resched() is set, then the tick cannot be stopped whether the CPU is idle or in nohz full mode.
That's not exactly true. In nohz full mode the tick is not restarted on the switch from idle to a single task. And if an idle interrupt wakes up a single task and enqueues a timer, we want that timer to be programmed even though we have need_resched().
Hrmm, so the check for softirq_pending() should be sufficient, right?
--- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -382,7 +382,8 @@ static inline void tick_irq_exit(void) int cpu = smp_processor_id();
/* Make sure that timer wheel updates are propagated */ - if ((idle_cpu(cpu) && !need_resched()) || tick_nohz_full_cpu(cpu)) { + if (((idle_cpu(cpu) && !need_resched()) || tick_nohz_full_cpu(cpu)) && + if ((idle_cpu(cpu) || tick_nohz_full_cpu(cpu)) && + !local_softirq_pending()) { if (!in_interrupt()) tick_nohz_irq_exit(); }