aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/timer.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2015-04-14 17:08:58 -0400
committerThomas Gleixner <tglx@linutronix.de>2015-04-22 11:06:50 -0400
commitc1ad348b452aacd784fb97403d03d71723c72ee1 (patch)
tree8f57456095d7125463a9647701acfe24b9d96ffc /kernel/time/timer.c
parent157d29e101c7d032e886df067aeea1b21a366cc5 (diff)
tick: Nohz: Rework next timer evaluation
The evaluation of the next timer in the nohz code is based on jiffies while all the tick internals are nano seconds based. We have also to convert hrtimer nanoseconds to jiffies in the !highres case. That's just wrong and introduces interesting corner cases. Turn it around and convert the next timer wheel timer expiry and the rcu event to clock monotonic and base all calculations on nanoseconds. That identifies the case where no timer is pending clearly with an absolute expiry value of KTIME_MAX. Makes the code more readable and gets rid of the jiffies magic in the nohz code. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Peter Zijlstra <peterz@infradead.org> Cc: Preeti U Murthy <preeti@linux.vnet.ibm.com> Cc: Viresh Kumar <viresh.kumar@linaro.org> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Josh Triplett <josh@joshtriplett.org> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: John Stultz <john.stultz@linaro.org> Cc: Marcelo Tosatti <mtosatti@redhat.com> Link: http://lkml.kernel.org/r/20150414203502.184198593@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/timer.c')
-rw-r--r--kernel/time/timer.c71
1 files changed, 34 insertions, 37 deletions
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index b31f13f4fe41..172b83cd2f8e 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -49,6 +49,8 @@
49#include <asm/timex.h> 49#include <asm/timex.h>
50#include <asm/io.h> 50#include <asm/io.h>
51 51
52#include "tick-internal.h"
53
52#define CREATE_TRACE_POINTS 54#define CREATE_TRACE_POINTS
53#include <trace/events/timer.h> 55#include <trace/events/timer.h>
54 56
@@ -1311,54 +1313,48 @@ cascade:
1311 * Check, if the next hrtimer event is before the next timer wheel 1313 * Check, if the next hrtimer event is before the next timer wheel
1312 * event: 1314 * event:
1313 */ 1315 */
1314static unsigned long cmp_next_hrtimer_event(unsigned long now, 1316static u64 cmp_next_hrtimer_event(u64 basem, u64 expires)
1315 unsigned long expires)
1316{ 1317{
1317 ktime_t hr_delta = hrtimer_get_next_event(); 1318 u64 nextevt = hrtimer_get_next_event();
1318 struct timespec tsdelta;
1319 unsigned long delta;
1320
1321 if (hr_delta.tv64 == KTIME_MAX)
1322 return expires;
1323 1319
1324 /* 1320 /*
1325 * Expired timer available, let it expire in the next tick 1321 * If high resolution timers are enabled
1322 * hrtimer_get_next_event() returns KTIME_MAX.
1326 */ 1323 */
1327 if (hr_delta.tv64 <= 0) 1324 if (expires <= nextevt)
1328 return now + 1; 1325 return expires;
1329
1330 tsdelta = ktime_to_timespec(hr_delta);
1331 delta = timespec_to_jiffies(&tsdelta);
1332 1326
1333 /* 1327 /*
1334 * Limit the delta to the max value, which is checked in 1328 * If the next timer is already expired, return the tick base
1335 * tick_nohz_stop_sched_tick(): 1329 * time so the tick is fired immediately.
1336 */ 1330 */
1337 if (delta > NEXT_TIMER_MAX_DELTA) 1331 if (nextevt <= basem)
1338 delta = NEXT_TIMER_MAX_DELTA; 1332 return basem;
1339 1333
1340 /* 1334 /*
1341 * Take rounding errors in to account and make sure, that it 1335 * Round up to the next jiffie. High resolution timers are
1342 * expires in the next tick. Otherwise we go into an endless 1336 * off, so the hrtimers are expired in the tick and we need to
1343 * ping pong due to tick_nohz_stop_sched_tick() retriggering 1337 * make sure that this tick really expires the timer to avoid
1344 * the timer softirq 1338 * a ping pong of the nohz stop code.
1339 *
1340 * Use DIV_ROUND_UP_ULL to prevent gcc calling __divdi3
1345 */ 1341 */
1346 if (delta < 1) 1342 return DIV_ROUND_UP_ULL(nextevt, TICK_NSEC) * TICK_NSEC;
1347 delta = 1;
1348 now += delta;
1349 if (time_before(now, expires))
1350 return now;
1351 return expires;
1352} 1343}
1353 1344
1354/** 1345/**
1355 * get_next_timer_interrupt - return the jiffy of the next pending timer 1346 * get_next_timer_interrupt - return the time (clock mono) of the next timer
1356 * @now: current time (in jiffies) 1347 * @basej: base time jiffies
1348 * @basem: base time clock monotonic
1349 *
1350 * Returns the tick aligned clock monotonic time of the next pending
1351 * timer or KTIME_MAX if no timer is pending.
1357 */ 1352 */
1358unsigned long get_next_timer_interrupt(unsigned long now) 1353u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
1359{ 1354{
1360 struct tvec_base *base = __this_cpu_read(tvec_bases); 1355 struct tvec_base *base = __this_cpu_read(tvec_bases);
1361 unsigned long expires = now + NEXT_TIMER_MAX_DELTA; 1356 u64 expires = KTIME_MAX;
1357 unsigned long nextevt;
1362 1358
1363 /* 1359 /*
1364 * Pretend that there is no timer pending if the cpu is offline. 1360 * Pretend that there is no timer pending if the cpu is offline.
@@ -1371,14 +1367,15 @@ unsigned long get_next_timer_interrupt(unsigned long now)
1371 if (base->active_timers) { 1367 if (base->active_timers) {
1372 if (time_before_eq(base->next_timer, base->timer_jiffies)) 1368 if (time_before_eq(base->next_timer, base->timer_jiffies))
1373 base->next_timer = __next_timer_interrupt(base); 1369 base->next_timer = __next_timer_interrupt(base);
1374 expires = base->next_timer; 1370 nextevt = base->next_timer;
1371 if (time_before_eq(nextevt, basej))
1372 expires = basem;
1373 else
1374 expires = basem + (nextevt - basej) * TICK_NSEC;
1375 } 1375 }
1376 spin_unlock(&base->lock); 1376 spin_unlock(&base->lock);
1377 1377
1378 if (time_before_eq(expires, now)) 1378 return cmp_next_hrtimer_event(basem, expires);
1379 return now;
1380
1381 return cmp_next_hrtimer_event(now, expires);
1382} 1379}
1383#endif 1380#endif
1384 1381