Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751538AbdFEJSw (ORCPT ); Mon, 5 Jun 2017 05:18:52 -0400 Received: from terminus.zytor.com ([65.50.211.136]:57853 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751279AbdFEJSv (ORCPT ); Mon, 5 Jun 2017 05:18:51 -0400 Date: Mon, 5 Jun 2017 02:14:14 -0700 From: tip-bot for Frederic Weisbecker Message-ID: Cc: linux-kernel@vger.kernel.org, peterz@infradead.org, tglx@linutronix.de, hpa@zytor.com, octavian.purdila@nxp.com, mingo@kernel.org, torvalds@linux-foundation.org, fweisbec@gmail.com, riel@redhat.com Reply-To: mingo@kernel.org, fweisbec@gmail.com, torvalds@linux-foundation.org, riel@redhat.com, peterz@infradead.org, linux-kernel@vger.kernel.org, octavian.purdila@nxp.com, hpa@zytor.com, tglx@linutronix.de In-Reply-To: <1496328429-13317-1-git-send-email-fweisbec@gmail.com> References: <1496328429-13317-1-git-send-email-fweisbec@gmail.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:timers/nohz] nohz: Fix buggy tick delay on IRQ storms Git-Commit-ID: f99973e18b65ca1fff8c81532e3132b8f622aea8 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3429 Lines: 84 Commit-ID: f99973e18b65ca1fff8c81532e3132b8f622aea8 Gitweb: http://git.kernel.org/tip/f99973e18b65ca1fff8c81532e3132b8f622aea8 Author: Frederic Weisbecker AuthorDate: Thu, 1 Jun 2017 16:47:09 +0200 Committer: Ingo Molnar CommitDate: Mon, 5 Jun 2017 09:33:50 +0200 nohz: Fix buggy tick delay on IRQ storms When the tick is stopped and we reach the dynticks evaluation code on IRQ exit, we perform a soft tick restart if we observe an expired timer from there. It means we program the nearest possible tick but we stay in dynticks mode (ts->tick_stopped = 1) because we may need to stop the tick again after that expired timer is handled. Now this solution works most of the time but if we suffer an IRQ storm and those interrupts trigger faster than the hardware clockevents min delay, our tick won't fire until that IRQ storm is finished. Here is the problem: on IRQ exit we reprog the timer to at least NOW() + min_clockevents_delay. Another IRQ fires before the tick so we reschedule again to NOW() + min_clockevents_delay, etc... The tick is eternally rescheduled min_clockevents_delay ahead. A solution is to simply remove this soft tick restart. After all the normal dynticks evaluation path can handle 0 delay just fine. And by doing that we benefit from the optimization branch which avoids clock reprogramming if the clockevents deadline hasn't changed since the last reprog. This fixes our issue because we don't do repetitive clock reprog that always add hardware min delay. As a side effect it should even optimize the 0 delay path in general. Reported-and-tested-by: Octavian Purdila Signed-off-by: Frederic Weisbecker Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rik van Riel Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1496328429-13317-1-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/time/tick-sched.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index e304387..9d31f1e 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -713,8 +713,6 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, */ delta = next_tick - basemono; if (delta <= (u64)TICK_NSEC) { - tick = 0; - /* * Tell the timer code that the base is not idle, i.e. undo * the effect of get_next_timer_interrupt(): @@ -724,23 +722,8 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, * We've not stopped the tick yet, and there's a timer in the * next period, so no point in stopping it either, bail. */ - if (!ts->tick_stopped) - goto out; - - /* - * If, OTOH, we did stop it, but there's a pending (expired) - * timer reprogram the timer hardware to fire now. - * - * We will not restart the tick proper, just prod the timer - * hardware into firing an interrupt to process the pending - * timers. Just like tick_irq_exit() will not restart the tick - * for 'normal' interrupts. - * - * Only once we exit the idle loop will we re-enable the tick, - * see tick_nohz_idle_exit(). - */ - if (delta == 0) { - tick_nohz_restart(ts, now); + if (!ts->tick_stopped) { + tick = 0; goto out; } }