All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@elte.hu>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: linux-kernel@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>,
	Thomas Gleixner <tglx@linutronix.de>
Subject: [git pull] timer fixes
Date: Sat, 31 Jan 2009 00:07:24 +0100	[thread overview]
Message-ID: <20090130230724.GA31001@elte.hu> (raw)

Linus,

Please pull the latest timers-fixes-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git timers-fixes-for-linus

Special mention for this commit:

      hrtimers: increase clock min delta threshold while interrupt hanging

We found it useful in the case where a very slow (or very emulated) system 
is overwhelmed with HZ irqs - we get a kernel message and some throttling, 
instead of a hard lockup in essence. If that kind of approach is not 
acceptable we can remove this patch and resend the other fixes.

 Thanks,

	Ingo

------------------>
Frederic Weisbecker (1):
      hrtimers: increase clock min delta threshold while interrupt hanging

Sebastien Dugue (1):
      hrtimers: allow the hot-unplugging of all cpus

Thomas Gleixner (1):
      hrtimer: prevent negative expiry value after clock_was_set()


 include/linux/clockchips.h |    1 +
 kernel/hrtimer.c           |   41 ++++++++++++++++++++++++++++++++++++++++-
 kernel/time/tick-common.c  |   26 +++++++++++++++++++-------
 3 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index cea1536..3a1dbba 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -36,6 +36,7 @@ enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
 	CLOCK_EVT_NOTIFY_SUSPEND,
 	CLOCK_EVT_NOTIFY_RESUME,
+	CLOCK_EVT_NOTIFY_CPU_DYING,
 	CLOCK_EVT_NOTIFY_CPU_DEAD,
 };
 
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index f33afb0..f394d2a 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -501,6 +501,13 @@ static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base)
 			continue;
 		timer = rb_entry(base->first, struct hrtimer, node);
 		expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
+		/*
+		 * clock_was_set() has changed base->offset so the
+		 * result might be negative. Fix it up to prevent a
+		 * false positive in clockevents_program_event()
+		 */
+		if (expires.tv64 < 0)
+			expires.tv64 = 0;
 		if (expires.tv64 < cpu_base->expires_next.tv64)
 			cpu_base->expires_next = expires;
 	}
@@ -1158,6 +1165,29 @@ static void __run_hrtimer(struct hrtimer *timer)
 
 #ifdef CONFIG_HIGH_RES_TIMERS
 
+static int force_clock_reprogram;
+
+/*
+ * After 5 iteration's attempts, we consider that hrtimer_interrupt()
+ * is hanging, which could happen with something that slows the interrupt
+ * such as the tracing. Then we force the clock reprogramming for each future
+ * hrtimer interrupts to avoid infinite loops and use the min_delta_ns
+ * threshold that we will overwrite.
+ * The next tick event will be scheduled to 3 times we currently spend on
+ * hrtimer_interrupt(). This gives a good compromise, the cpus will spend
+ * 1/4 of their time to process the hrtimer interrupts. This is enough to
+ * let it running without serious starvation.
+ */
+
+static inline void
+hrtimer_interrupt_hanging(struct clock_event_device *dev,
+			ktime_t try_time)
+{
+	force_clock_reprogram = 1;
+	dev->min_delta_ns = (unsigned long)try_time.tv64 * 3;
+	printk(KERN_WARNING "hrtimer: interrupt too slow, "
+		"forcing clock min delta to %lu ns\n", dev->min_delta_ns);
+}
 /*
  * High resolution timer interrupt
  * Called with interrupts disabled
@@ -1167,6 +1197,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
 	struct hrtimer_clock_base *base;
 	ktime_t expires_next, now;
+	int nr_retries = 0;
 	int i;
 
 	BUG_ON(!cpu_base->hres_active);
@@ -1174,6 +1205,10 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 	dev->next_event.tv64 = KTIME_MAX;
 
  retry:
+	/* 5 retries is enough to notice a hang */
+	if (!(++nr_retries % 5))
+		hrtimer_interrupt_hanging(dev, ktime_sub(ktime_get(), now));
+
 	now = ktime_get();
 
 	expires_next.tv64 = KTIME_MAX;
@@ -1226,7 +1261,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 
 	/* Reprogramming necessary ? */
 	if (expires_next.tv64 != KTIME_MAX) {
-		if (tick_program_event(expires_next, 0))
+		if (tick_program_event(expires_next, force_clock_reprogram))
 			goto retry;
 	}
 }
@@ -1580,6 +1615,10 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
 		break;
 
 #ifdef CONFIG_HOTPLUG_CPU
+	case CPU_DYING:
+	case CPU_DYING_FROZEN:
+		clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DYING, &scpu);
+		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
 	{
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 63e05d4..21a5ca8 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -274,6 +274,21 @@ out_bc:
 }
 
 /*
+ * Transfer the do_timer job away from a dying cpu.
+ *
+ * Called with interrupts disabled.
+ */
+static void tick_handover_do_timer(int *cpup)
+{
+	if (*cpup == tick_do_timer_cpu) {
+		int cpu = cpumask_first(cpu_online_mask);
+
+		tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu :
+			TICK_DO_TIMER_NONE;
+	}
+}
+
+/*
  * Shutdown an event device on a given cpu:
  *
  * This is called on a life CPU, when a CPU is dead. So we cannot
@@ -297,13 +312,6 @@ static void tick_shutdown(unsigned int *cpup)
 		clockevents_exchange_device(dev, NULL);
 		td->evtdev = NULL;
 	}
-	/* Transfer the do_timer job away from this cpu */
-	if (*cpup == tick_do_timer_cpu) {
-		int cpu = cpumask_first(cpu_online_mask);
-
-		tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu :
-			TICK_DO_TIMER_NONE;
-	}
 	spin_unlock_irqrestore(&tick_device_lock, flags);
 }
 
@@ -357,6 +365,10 @@ static int tick_notify(struct notifier_block *nb, unsigned long reason,
 		tick_broadcast_oneshot_control(reason);
 		break;
 
+	case CLOCK_EVT_NOTIFY_CPU_DYING:
+		tick_handover_do_timer(dev);
+		break;
+
 	case CLOCK_EVT_NOTIFY_CPU_DEAD:
 		tick_shutdown_broadcast_oneshot(dev);
 		tick_shutdown_broadcast(dev);

             reply	other threads:[~2009-01-30 23:07 UTC|newest]

Thread overview: 73+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-30 23:07 Ingo Molnar [this message]
  -- strict thread matches above, loose matches on Subject: below --
2024-04-14  8:42 [GIT PULL] timer fixes Ingo Molnar
2024-04-14 18:48 ` pr-tracker-bot
2024-04-07  8:03 Ingo Molnar
2024-04-07 16:44 ` pr-tracker-bot
2023-01-12 14:44 Ingo Molnar
2023-01-12 23:01 ` pr-tracker-bot
2022-08-13 10:25 Ingo Molnar
2022-08-13 16:25 ` Borislav Petkov
2022-08-13 20:27   ` Linus Torvalds
2022-08-14  8:57     ` Ingo Molnar
2022-08-14 12:41     ` Borislav Petkov
2022-08-14 17:24       ` Paul E. McKenney
2022-08-14 17:42         ` Borislav Petkov
2022-08-13 21:48 ` pr-tracker-bot
2020-12-27  9:26 Ingo Molnar
2020-12-27 17:27 ` pr-tracker-bot
2019-12-17 11:55 Ingo Molnar
2019-12-17 19:14 ` Linus Torvalds
2019-12-17 19:30   ` Peter Zijlstra
2019-12-17 20:16     ` Linus Torvalds
2019-12-17 20:35       ` Peter Zijlstra
2019-12-17 20:43         ` Linus Torvalds
2019-12-17 20:54           ` Peter Zijlstra
2019-12-17 19:20 ` pr-tracker-bot
2019-05-16 16:09 Ingo Molnar
2019-05-16 18:20 ` pr-tracker-bot
2019-04-20  7:45 Ingo Molnar
2019-04-20 19:25 ` pr-tracker-bot
2018-07-13 20:01 Ingo Molnar
2017-03-07 20:36 Ingo Molnar
2016-10-28  8:38 Ingo Molnar
2016-08-18 20:46 Ingo Molnar
2016-08-12 19:43 Ingo Molnar
2016-01-14 10:12 Ingo Molnar
2015-10-03 10:20 Ingo Molnar
2015-09-17  8:13 Ingo Molnar
2015-03-28 13:50 Ingo Molnar
2015-03-17 16:50 Ingo Molnar
2015-03-01 17:06 Ingo Molnar
2013-12-17 13:52 Ingo Molnar
2013-09-28 18:19 Ingo Molnar
2013-08-19  9:41 Ingo Molnar
2013-02-26 11:32 Ingo Molnar
2012-09-21 19:12 Ingo Molnar
2012-08-03 16:47 Ingo Molnar
2011-12-20 19:25 Ingo Molnar
2011-12-05 19:00 Ingo Molnar
2011-06-19  8:51 Ingo Molnar
2011-06-13  9:55 Ingo Molnar
2011-06-06 19:10 [GIT pull] " Thomas Gleixner
2011-05-20 17:52 Thomas Gleixner
2011-04-19 16:03 [GIT PULL] " Ingo Molnar
2011-04-16 10:09 Ingo Molnar
2011-04-07 17:42 Ingo Molnar
2011-02-06 12:06 Ingo Molnar
2011-01-24 13:24 Ingo Molnar
2010-11-26 13:40 Ingo Molnar
2010-03-26 15:34 Ingo Molnar
2009-12-18 18:49 Ingo Molnar
2009-10-08 18:35 Ingo Molnar
2009-08-25 18:04 Ingo Molnar
2009-06-26 19:03 Ingo Molnar
2009-04-09 15:43 Ingo Molnar
2009-01-26 17:21 [git pull] " Ingo Molnar
2009-01-06 16:18 Ingo Molnar
2008-12-04 20:52 Ingo Molnar
2008-11-11 18:47 Ingo Molnar
2008-09-23 19:41 Ingo Molnar
2008-09-17  9:59 Ingo Molnar
2008-08-25 17:52 Ingo Molnar
2008-08-22 12:24 Ingo Molnar
2008-07-24 15:18 Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090130230724.GA31001@elte.hu \
    --to=mingo@elte.hu \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.