diff options
Diffstat (limited to 'kernel/time/tick-sched.c')
-rw-r--r-- | kernel/time/tick-sched.c | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index c65ba0faa98f..a80b4644fe6b 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -208,6 +208,7 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
208 | struct tick_sched *ts; | 208 | struct tick_sched *ts; |
209 | ktime_t last_update, expires, now; | 209 | ktime_t last_update, expires, now; |
210 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; | 210 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; |
211 | u64 time_delta; | ||
211 | int cpu; | 212 | int cpu; |
212 | 213 | ||
213 | local_irq_save(flags); | 214 | local_irq_save(flags); |
@@ -262,6 +263,17 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
262 | seq = read_seqbegin(&xtime_lock); | 263 | seq = read_seqbegin(&xtime_lock); |
263 | last_update = last_jiffies_update; | 264 | last_update = last_jiffies_update; |
264 | last_jiffies = jiffies; | 265 | last_jiffies = jiffies; |
266 | |||
267 | /* | ||
268 | * On SMP we really should only care for the CPU which | ||
269 | * has the do_timer duty assigned. All other CPUs can | ||
270 | * sleep as long as they want. | ||
271 | */ | ||
272 | if (cpu == tick_do_timer_cpu || | ||
273 | tick_do_timer_cpu == TICK_DO_TIMER_NONE) | ||
274 | time_delta = timekeeping_max_deferment(); | ||
275 | else | ||
276 | time_delta = KTIME_MAX; | ||
265 | } while (read_seqretry(&xtime_lock, seq)); | 277 | } while (read_seqretry(&xtime_lock, seq)); |
266 | 278 | ||
267 | if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) || | 279 | if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) || |
@@ -284,11 +296,26 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
284 | if ((long)delta_jiffies >= 1) { | 296 | if ((long)delta_jiffies >= 1) { |
285 | 297 | ||
286 | /* | 298 | /* |
287 | * calculate the expiry time for the next timer wheel | 299 | * calculate the expiry time for the next timer wheel |
288 | * timer | 300 | * timer. delta_jiffies >= NEXT_TIMER_MAX_DELTA signals |
289 | */ | 301 | * that there is no timer pending or at least extremely |
290 | expires = ktime_add_ns(last_update, tick_period.tv64 * | 302 | * far into the future (12 days for HZ=1000). In this |
291 | delta_jiffies); | 303 | * case we set the expiry to the end of time. |
304 | */ | ||
305 | if (likely(delta_jiffies < NEXT_TIMER_MAX_DELTA)) { | ||
306 | /* | ||
307 | * Calculate the time delta for the next timer event. | ||
308 | * If the time delta exceeds the maximum time delta | ||
309 | * permitted by the current clocksource then adjust | ||
310 | * the time delta accordingly to ensure the | ||
311 | * clocksource does not wrap. | ||
312 | */ | ||
313 | time_delta = min_t(u64, time_delta, | ||
314 | tick_period.tv64 * delta_jiffies); | ||
315 | expires = ktime_add_ns(last_update, time_delta); | ||
316 | } else { | ||
317 | expires.tv64 = KTIME_MAX; | ||
318 | } | ||
292 | 319 | ||
293 | /* | 320 | /* |
294 | * If this cpu is the one which updates jiffies, then | 321 | * If this cpu is the one which updates jiffies, then |
@@ -332,22 +359,19 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
332 | 359 | ||
333 | ts->idle_sleeps++; | 360 | ts->idle_sleeps++; |
334 | 361 | ||
362 | /* Mark expires */ | ||
363 | ts->idle_expires = expires; | ||
364 | |||
335 | /* | 365 | /* |
336 | * delta_jiffies >= NEXT_TIMER_MAX_DELTA signals that | 366 | * If the expiration time == KTIME_MAX, then |
337 | * there is no timer pending or at least extremly far | 367 | * in this case we simply stop the tick timer. |
338 | * into the future (12 days for HZ=1000). In this case | ||
339 | * we simply stop the tick timer: | ||
340 | */ | 368 | */ |
341 | if (unlikely(delta_jiffies >= NEXT_TIMER_MAX_DELTA)) { | 369 | if (unlikely(expires.tv64 == KTIME_MAX)) { |
342 | ts->idle_expires.tv64 = KTIME_MAX; | ||
343 | if (ts->nohz_mode == NOHZ_MODE_HIGHRES) | 370 | if (ts->nohz_mode == NOHZ_MODE_HIGHRES) |
344 | hrtimer_cancel(&ts->sched_timer); | 371 | hrtimer_cancel(&ts->sched_timer); |
345 | goto out; | 372 | goto out; |
346 | } | 373 | } |
347 | 374 | ||
348 | /* Mark expiries */ | ||
349 | ts->idle_expires = expires; | ||
350 | |||
351 | if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { | 375 | if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { |
352 | hrtimer_start(&ts->sched_timer, expires, | 376 | hrtimer_start(&ts->sched_timer, expires, |
353 | HRTIMER_MODE_ABS_PINNED); | 377 | HRTIMER_MODE_ABS_PINNED); |