diff options
Diffstat (limited to 'kernel/time/tick-sched.c')
-rw-r--r-- | kernel/time/tick-sched.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 0581c11fe6c6..5bbb1044f847 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -300,7 +300,7 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
300 | goto out; | 300 | goto out; |
301 | } | 301 | } |
302 | 302 | ||
303 | ts->idle_tick = ts->sched_timer.expires; | 303 | ts->idle_tick = hrtimer_get_expires(&ts->sched_timer); |
304 | ts->tick_stopped = 1; | 304 | ts->tick_stopped = 1; |
305 | ts->idle_jiffies = last_jiffies; | 305 | ts->idle_jiffies = last_jiffies; |
306 | rcu_enter_nohz(); | 306 | rcu_enter_nohz(); |
@@ -380,21 +380,21 @@ ktime_t tick_nohz_get_sleep_length(void) | |||
380 | static void tick_nohz_restart(struct tick_sched *ts, ktime_t now) | 380 | static void tick_nohz_restart(struct tick_sched *ts, ktime_t now) |
381 | { | 381 | { |
382 | hrtimer_cancel(&ts->sched_timer); | 382 | hrtimer_cancel(&ts->sched_timer); |
383 | ts->sched_timer.expires = ts->idle_tick; | 383 | hrtimer_set_expires(&ts->sched_timer, ts->idle_tick); |
384 | 384 | ||
385 | while (1) { | 385 | while (1) { |
386 | /* Forward the time to expire in the future */ | 386 | /* Forward the time to expire in the future */ |
387 | hrtimer_forward(&ts->sched_timer, now, tick_period); | 387 | hrtimer_forward(&ts->sched_timer, now, tick_period); |
388 | 388 | ||
389 | if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { | 389 | if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { |
390 | hrtimer_start(&ts->sched_timer, | 390 | hrtimer_start_expires(&ts->sched_timer, |
391 | ts->sched_timer.expires, | ||
392 | HRTIMER_MODE_ABS); | 391 | HRTIMER_MODE_ABS); |
393 | /* Check, if the timer was already in the past */ | 392 | /* Check, if the timer was already in the past */ |
394 | if (hrtimer_active(&ts->sched_timer)) | 393 | if (hrtimer_active(&ts->sched_timer)) |
395 | break; | 394 | break; |
396 | } else { | 395 | } else { |
397 | if (!tick_program_event(ts->sched_timer.expires, 0)) | 396 | if (!tick_program_event( |
397 | hrtimer_get_expires(&ts->sched_timer), 0)) | ||
398 | break; | 398 | break; |
399 | } | 399 | } |
400 | /* Update jiffies and reread time */ | 400 | /* Update jiffies and reread time */ |
@@ -456,14 +456,16 @@ void tick_nohz_restart_sched_tick(void) | |||
456 | */ | 456 | */ |
457 | ts->tick_stopped = 0; | 457 | ts->tick_stopped = 0; |
458 | ts->idle_exittime = now; | 458 | ts->idle_exittime = now; |
459 | |||
459 | tick_nohz_restart(ts, now); | 460 | tick_nohz_restart(ts, now); |
461 | |||
460 | local_irq_enable(); | 462 | local_irq_enable(); |
461 | } | 463 | } |
462 | 464 | ||
463 | static int tick_nohz_reprogram(struct tick_sched *ts, ktime_t now) | 465 | static int tick_nohz_reprogram(struct tick_sched *ts, ktime_t now) |
464 | { | 466 | { |
465 | hrtimer_forward(&ts->sched_timer, now, tick_period); | 467 | hrtimer_forward(&ts->sched_timer, now, tick_period); |
466 | return tick_program_event(ts->sched_timer.expires, 0); | 468 | return tick_program_event(hrtimer_get_expires(&ts->sched_timer), 0); |
467 | } | 469 | } |
468 | 470 | ||
469 | /* | 471 | /* |
@@ -542,7 +544,7 @@ static void tick_nohz_switch_to_nohz(void) | |||
542 | next = tick_init_jiffy_update(); | 544 | next = tick_init_jiffy_update(); |
543 | 545 | ||
544 | for (;;) { | 546 | for (;;) { |
545 | ts->sched_timer.expires = next; | 547 | hrtimer_set_expires(&ts->sched_timer, next); |
546 | if (!tick_program_event(next, 0)) | 548 | if (!tick_program_event(next, 0)) |
547 | break; | 549 | break; |
548 | next = ktime_add(next, tick_period); | 550 | next = ktime_add(next, tick_period); |
@@ -567,11 +569,21 @@ static void tick_nohz_switch_to_nohz(void) | |||
567 | static void tick_nohz_kick_tick(int cpu) | 569 | static void tick_nohz_kick_tick(int cpu) |
568 | { | 570 | { |
569 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 571 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); |
572 | ktime_t delta, now; | ||
570 | 573 | ||
571 | if (!ts->tick_stopped) | 574 | if (!ts->tick_stopped) |
572 | return; | 575 | return; |
573 | 576 | ||
574 | tick_nohz_restart(ts, ktime_get()); | 577 | /* |
578 | * Do not touch the tick device, when the next expiry is either | ||
579 | * already reached or less/equal than the tick period. | ||
580 | */ | ||
581 | now = ktime_get(); | ||
582 | delta = ktime_sub(hrtimer_get_expires(&ts->sched_timer), now); | ||
583 | if (delta.tv64 <= tick_period.tv64) | ||
584 | return; | ||
585 | |||
586 | tick_nohz_restart(ts, now); | ||
575 | } | 587 | } |
576 | 588 | ||
577 | #else | 589 | #else |
@@ -668,16 +680,15 @@ void tick_setup_sched_timer(void) | |||
668 | ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU; | 680 | ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU; |
669 | 681 | ||
670 | /* Get the next period (per cpu) */ | 682 | /* Get the next period (per cpu) */ |
671 | ts->sched_timer.expires = tick_init_jiffy_update(); | 683 | hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); |
672 | offset = ktime_to_ns(tick_period) >> 1; | 684 | offset = ktime_to_ns(tick_period) >> 1; |
673 | do_div(offset, num_possible_cpus()); | 685 | do_div(offset, num_possible_cpus()); |
674 | offset *= smp_processor_id(); | 686 | offset *= smp_processor_id(); |
675 | ts->sched_timer.expires = ktime_add_ns(ts->sched_timer.expires, offset); | 687 | hrtimer_add_expires_ns(&ts->sched_timer, offset); |
676 | 688 | ||
677 | for (;;) { | 689 | for (;;) { |
678 | hrtimer_forward(&ts->sched_timer, now, tick_period); | 690 | hrtimer_forward(&ts->sched_timer, now, tick_period); |
679 | hrtimer_start(&ts->sched_timer, ts->sched_timer.expires, | 691 | hrtimer_start_expires(&ts->sched_timer, HRTIMER_MODE_ABS); |
680 | HRTIMER_MODE_ABS); | ||
681 | /* Check, if the timer was already in the past */ | 692 | /* Check, if the timer was already in the past */ |
682 | if (hrtimer_active(&ts->sched_timer)) | 693 | if (hrtimer_active(&ts->sched_timer)) |
683 | break; | 694 | break; |