public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] hrtimers: calculate expires_next after all timers are executed
@ 2014-03-17 14:37 Stanislav Fomichev
  2014-03-19 10:59 ` Thomas Gleixner
  0 siblings, 1 reply; 15+ messages in thread
From: Stanislav Fomichev @ 2014-03-17 14:37 UTC (permalink / raw)
  To: tglx, john.stultz, prarit, paul.gortmaker, juri.lelli,
	ddaney.cavm, mbohan, david.vrabel, david.engraf
  Cc: linux-kernel

I think I'm hitting particularly subtle issue with NOHZ_IDLE kernel.

The sequence is as follows:
- CPU enters idle, we disable tick
- hrtimer interrupt fires (for hrtimer_wakeup)
- for clock base #1 (REALTIME) we wake up SCHED_RT thread and
  start RT period timer (from start_rt_bandwidth) for clock base #0 (MONOTONIC)
- because we already checked expiry time for clock base #0
  we end up programming wrong wake up time (minutes, from tick_sched_timer)
- then, we exit idle loop and restart tick;
  but because tick_sched_timer is not leftmost (the leftmost one
  is RT period timer) we don't program it

So in the end, I see working CPU without tick interrupt.
This eventually leads to RCU stall on that CPU: rcu_gp_kthread
is not woken up because there is no tick (this is the reason
I started digging this up).

The proposed fix runs expired timers first and only then tries to find
next expiry time for all clocks.

Signed-off-by: Stanislav Fomichev <stfomichev@yandex-team.ru>
---
 kernel/hrtimer.c | 38 ++++++++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 09094361dce5..63805f9f9531 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1282,6 +1282,9 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
  */
 void hrtimer_interrupt(struct clock_event_device *dev)
 {
+	struct hrtimer_clock_base *base;
+	struct timerqueue_node *node;
+	struct hrtimer *timer;
 	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
 	ktime_t expires_next, now, entry_time, delta;
 	int i, retries = 0;
@@ -1304,8 +1307,6 @@ retry:
 	cpu_base->expires_next.tv64 = KTIME_MAX;
 
 	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
-		struct hrtimer_clock_base *base;
-		struct timerqueue_node *node;
 		ktime_t basenow;
 
 		if (!(cpu_base->active_bases & (1 << i)))
@@ -1315,8 +1316,6 @@ retry:
 		basenow = ktime_add(now, base->offset);
 
 		while ((node = timerqueue_getnext(&base->active))) {
-			struct hrtimer *timer;
-
 			timer = container_of(node, struct hrtimer, node);
 
 			/*
@@ -1332,22 +1331,33 @@ retry:
 			 * timer will have to trigger a wakeup anyway.
 			 */
 
-			if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer)) {
-				ktime_t expires;
-
-				expires = ktime_sub(hrtimer_get_expires(timer),
-						    base->offset);
-				if (expires.tv64 < 0)
-					expires.tv64 = KTIME_MAX;
-				if (expires.tv64 < expires_next.tv64)
-					expires_next = expires;
+			if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer))
 				break;
-			}
 
 			__run_hrtimer(timer, &basenow);
 		}
 	}
 
+	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+		ktime_t expires;
+
+		if (!(cpu_base->active_bases & (1 << i)))
+			continue;
+
+		base = cpu_base->clock_base + i;
+
+		node = timerqueue_getnext(&base->active);
+		if (!node)
+			continue;
+
+		timer = container_of(node, struct hrtimer, node);
+		expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
+		if (expires.tv64 < 0)
+			expires.tv64 = KTIME_MAX;
+		if (expires.tv64 < expires_next.tv64)
+			expires_next = expires;
+	}
+
 	/*
 	 * Store the new expiry value so the migration code can verify
 	 * against it.
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2014-12-29 12:25 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-17 14:37 [PATCH] hrtimers: calculate expires_next after all timers are executed Stanislav Fomichev
2014-03-19 10:59 ` Thomas Gleixner
2014-03-19 14:16   ` [PATCH v2] " Stanislav Fomichev
2014-03-24  8:42     ` Stanislav Fomichev
2014-03-24  9:04       ` Thomas Gleixner
2014-05-05  9:26         ` Stanislav Fomichev
2014-06-04 15:47     ` Stanislav Fomichev
2014-06-04 20:06       ` Thomas Gleixner
2014-06-22 14:46     ` Thomas Gleixner
2014-06-23 11:03       ` Stanislav Fomichev
2014-06-23 17:19         ` Thomas Gleixner
2014-06-23 18:04           ` Stanislav Fomichev
2014-06-24 17:18             ` Stanislav Fomichev
2014-12-26 23:34       ` Stephen Boyd
2014-12-29 12:24         ` Stanislav Fomichev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox