diff options
Diffstat (limited to 'kernel/time/tick-sched.c')
-rw-r--r-- | kernel/time/tick-sched.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 6a3a5b9ff561..869997833928 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -274,6 +274,7 @@ EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us); | |||
274 | static void tick_nohz_stop_sched_tick(struct tick_sched *ts) | 274 | static void tick_nohz_stop_sched_tick(struct tick_sched *ts) |
275 | { | 275 | { |
276 | unsigned long seq, last_jiffies, next_jiffies, delta_jiffies; | 276 | unsigned long seq, last_jiffies, next_jiffies, delta_jiffies; |
277 | unsigned long rcu_delta_jiffies; | ||
277 | ktime_t last_update, expires, now; | 278 | ktime_t last_update, expires, now; |
278 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; | 279 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; |
279 | u64 time_delta; | 280 | u64 time_delta; |
@@ -322,7 +323,7 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) | |||
322 | time_delta = timekeeping_max_deferment(); | 323 | time_delta = timekeeping_max_deferment(); |
323 | } while (read_seqretry(&xtime_lock, seq)); | 324 | } while (read_seqretry(&xtime_lock, seq)); |
324 | 325 | ||
325 | if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) || | 326 | if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) || printk_needs_cpu(cpu) || |
326 | arch_needs_cpu(cpu)) { | 327 | arch_needs_cpu(cpu)) { |
327 | next_jiffies = last_jiffies + 1; | 328 | next_jiffies = last_jiffies + 1; |
328 | delta_jiffies = 1; | 329 | delta_jiffies = 1; |
@@ -330,6 +331,10 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) | |||
330 | /* Get the next timer wheel timer */ | 331 | /* Get the next timer wheel timer */ |
331 | next_jiffies = get_next_timer_interrupt(last_jiffies); | 332 | next_jiffies = get_next_timer_interrupt(last_jiffies); |
332 | delta_jiffies = next_jiffies - last_jiffies; | 333 | delta_jiffies = next_jiffies - last_jiffies; |
334 | if (rcu_delta_jiffies < delta_jiffies) { | ||
335 | next_jiffies = last_jiffies + rcu_delta_jiffies; | ||
336 | delta_jiffies = rcu_delta_jiffies; | ||
337 | } | ||
333 | } | 338 | } |
334 | /* | 339 | /* |
335 | * Do not stop the tick, if we are only one off | 340 | * Do not stop the tick, if we are only one off |
@@ -576,6 +581,7 @@ void tick_nohz_idle_exit(void) | |||
576 | /* Update jiffies first */ | 581 | /* Update jiffies first */ |
577 | select_nohz_load_balancer(0); | 582 | select_nohz_load_balancer(0); |
578 | tick_do_update_jiffies64(now); | 583 | tick_do_update_jiffies64(now); |
584 | update_cpu_load_nohz(); | ||
579 | 585 | ||
580 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | 586 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING |
581 | /* | 587 | /* |
@@ -814,6 +820,16 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) | |||
814 | return HRTIMER_RESTART; | 820 | return HRTIMER_RESTART; |
815 | } | 821 | } |
816 | 822 | ||
823 | static int sched_skew_tick; | ||
824 | |||
825 | static int __init skew_tick(char *str) | ||
826 | { | ||
827 | get_option(&str, &sched_skew_tick); | ||
828 | |||
829 | return 0; | ||
830 | } | ||
831 | early_param("skew_tick", skew_tick); | ||
832 | |||
817 | /** | 833 | /** |
818 | * tick_setup_sched_timer - setup the tick emulation timer | 834 | * tick_setup_sched_timer - setup the tick emulation timer |
819 | */ | 835 | */ |
@@ -831,6 +847,14 @@ void tick_setup_sched_timer(void) | |||
831 | /* Get the next period (per cpu) */ | 847 | /* Get the next period (per cpu) */ |
832 | hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); | 848 | hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); |
833 | 849 | ||
850 | /* Offset the tick to avert xtime_lock contention. */ | ||
851 | if (sched_skew_tick) { | ||
852 | u64 offset = ktime_to_ns(tick_period) >> 1; | ||
853 | do_div(offset, num_possible_cpus()); | ||
854 | offset *= smp_processor_id(); | ||
855 | hrtimer_add_expires_ns(&ts->sched_timer, offset); | ||
856 | } | ||
857 | |||
834 | for (;;) { | 858 | for (;;) { |
835 | hrtimer_forward(&ts->sched_timer, now, tick_period); | 859 | hrtimer_forward(&ts->sched_timer, now, tick_period); |
836 | hrtimer_start_expires(&ts->sched_timer, | 860 | hrtimer_start_expires(&ts->sched_timer, |