diff options
Diffstat (limited to 'kernel/timer.c')
-rw-r--r-- | kernel/timer.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index d78de047599b..87bd529879c2 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -81,6 +81,7 @@ struct tvec_base { | |||
81 | unsigned long timer_jiffies; | 81 | unsigned long timer_jiffies; |
82 | unsigned long next_timer; | 82 | unsigned long next_timer; |
83 | unsigned long active_timers; | 83 | unsigned long active_timers; |
84 | unsigned long all_timers; | ||
84 | struct tvec_root tv1; | 85 | struct tvec_root tv1; |
85 | struct tvec tv2; | 86 | struct tvec tv2; |
86 | struct tvec tv3; | 87 | struct tvec tv3; |
@@ -337,6 +338,20 @@ void set_timer_slack(struct timer_list *timer, int slack_hz) | |||
337 | } | 338 | } |
338 | EXPORT_SYMBOL_GPL(set_timer_slack); | 339 | EXPORT_SYMBOL_GPL(set_timer_slack); |
339 | 340 | ||
341 | /* | ||
342 | * If the list is empty, catch up ->timer_jiffies to the current time. | ||
343 | * The caller must hold the tvec_base lock. Returns true if the list | ||
344 | * was empty and therefore ->timer_jiffies was updated. | ||
345 | */ | ||
346 | static bool catchup_timer_jiffies(struct tvec_base *base) | ||
347 | { | ||
348 | if (!base->all_timers) { | ||
349 | base->timer_jiffies = jiffies; | ||
350 | return true; | ||
351 | } | ||
352 | return false; | ||
353 | } | ||
354 | |||
340 | static void | 355 | static void |
341 | __internal_add_timer(struct tvec_base *base, struct timer_list *timer) | 356 | __internal_add_timer(struct tvec_base *base, struct timer_list *timer) |
342 | { | 357 | { |
@@ -383,15 +398,17 @@ __internal_add_timer(struct tvec_base *base, struct timer_list *timer) | |||
383 | 398 | ||
384 | static void internal_add_timer(struct tvec_base *base, struct timer_list *timer) | 399 | static void internal_add_timer(struct tvec_base *base, struct timer_list *timer) |
385 | { | 400 | { |
401 | (void)catchup_timer_jiffies(base); | ||
386 | __internal_add_timer(base, timer); | 402 | __internal_add_timer(base, timer); |
387 | /* | 403 | /* |
388 | * Update base->active_timers and base->next_timer | 404 | * Update base->active_timers and base->next_timer |
389 | */ | 405 | */ |
390 | if (!tbase_get_deferrable(timer->base)) { | 406 | if (!tbase_get_deferrable(timer->base)) { |
391 | if (time_before(timer->expires, base->next_timer)) | 407 | if (!base->active_timers++ || |
408 | time_before(timer->expires, base->next_timer)) | ||
392 | base->next_timer = timer->expires; | 409 | base->next_timer = timer->expires; |
393 | base->active_timers++; | ||
394 | } | 410 | } |
411 | base->all_timers++; | ||
395 | } | 412 | } |
396 | 413 | ||
397 | #ifdef CONFIG_TIMER_STATS | 414 | #ifdef CONFIG_TIMER_STATS |
@@ -671,6 +688,8 @@ detach_expired_timer(struct timer_list *timer, struct tvec_base *base) | |||
671 | detach_timer(timer, true); | 688 | detach_timer(timer, true); |
672 | if (!tbase_get_deferrable(timer->base)) | 689 | if (!tbase_get_deferrable(timer->base)) |
673 | base->active_timers--; | 690 | base->active_timers--; |
691 | base->all_timers--; | ||
692 | (void)catchup_timer_jiffies(base); | ||
674 | } | 693 | } |
675 | 694 | ||
676 | static int detach_if_pending(struct timer_list *timer, struct tvec_base *base, | 695 | static int detach_if_pending(struct timer_list *timer, struct tvec_base *base, |
@@ -685,6 +704,8 @@ static int detach_if_pending(struct timer_list *timer, struct tvec_base *base, | |||
685 | if (timer->expires == base->next_timer) | 704 | if (timer->expires == base->next_timer) |
686 | base->next_timer = base->timer_jiffies; | 705 | base->next_timer = base->timer_jiffies; |
687 | } | 706 | } |
707 | base->all_timers--; | ||
708 | (void)catchup_timer_jiffies(base); | ||
688 | return 1; | 709 | return 1; |
689 | } | 710 | } |
690 | 711 | ||
@@ -739,12 +760,7 @@ __mod_timer(struct timer_list *timer, unsigned long expires, | |||
739 | 760 | ||
740 | debug_activate(timer, expires); | 761 | debug_activate(timer, expires); |
741 | 762 | ||
742 | cpu = smp_processor_id(); | 763 | cpu = get_nohz_timer_target(pinned); |
743 | |||
744 | #if defined(CONFIG_NO_HZ_COMMON) && defined(CONFIG_SMP) | ||
745 | if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) | ||
746 | cpu = get_nohz_timer_target(); | ||
747 | #endif | ||
748 | new_base = per_cpu(tvec_bases, cpu); | 764 | new_base = per_cpu(tvec_bases, cpu); |
749 | 765 | ||
750 | if (base != new_base) { | 766 | if (base != new_base) { |
@@ -939,8 +955,15 @@ void add_timer_on(struct timer_list *timer, int cpu) | |||
939 | * with the timer by holding the timer base lock. This also | 955 | * with the timer by holding the timer base lock. This also |
940 | * makes sure that a CPU on the way to stop its tick can not | 956 | * makes sure that a CPU on the way to stop its tick can not |
941 | * evaluate the timer wheel. | 957 | * evaluate the timer wheel. |
958 | * | ||
959 | * Spare the IPI for deferrable timers on idle targets though. | ||
960 | * The next busy ticks will take care of it. Except full dynticks | ||
961 | * require special care against races with idle_cpu(), lets deal | ||
962 | * with that later. | ||
942 | */ | 963 | */ |
943 | wake_up_nohz_cpu(cpu); | 964 | if (!tbase_get_deferrable(timer->base) || tick_nohz_full_cpu(cpu)) |
965 | wake_up_nohz_cpu(cpu); | ||
966 | |||
944 | spin_unlock_irqrestore(&base->lock, flags); | 967 | spin_unlock_irqrestore(&base->lock, flags); |
945 | } | 968 | } |
946 | EXPORT_SYMBOL_GPL(add_timer_on); | 969 | EXPORT_SYMBOL_GPL(add_timer_on); |
@@ -1146,6 +1169,10 @@ static inline void __run_timers(struct tvec_base *base) | |||
1146 | struct timer_list *timer; | 1169 | struct timer_list *timer; |
1147 | 1170 | ||
1148 | spin_lock_irq(&base->lock); | 1171 | spin_lock_irq(&base->lock); |
1172 | if (catchup_timer_jiffies(base)) { | ||
1173 | spin_unlock_irq(&base->lock); | ||
1174 | return; | ||
1175 | } | ||
1149 | while (time_after_eq(jiffies, base->timer_jiffies)) { | 1176 | while (time_after_eq(jiffies, base->timer_jiffies)) { |
1150 | struct list_head work_list; | 1177 | struct list_head work_list; |
1151 | struct list_head *head = &work_list; | 1178 | struct list_head *head = &work_list; |
@@ -1160,7 +1187,7 @@ static inline void __run_timers(struct tvec_base *base) | |||
1160 | !cascade(base, &base->tv4, INDEX(2))) | 1187 | !cascade(base, &base->tv4, INDEX(2))) |
1161 | cascade(base, &base->tv5, INDEX(3)); | 1188 | cascade(base, &base->tv5, INDEX(3)); |
1162 | ++base->timer_jiffies; | 1189 | ++base->timer_jiffies; |
1163 | list_replace_init(base->tv1.vec + index, &work_list); | 1190 | list_replace_init(base->tv1.vec + index, head); |
1164 | while (!list_empty(head)) { | 1191 | while (!list_empty(head)) { |
1165 | void (*fn)(unsigned long); | 1192 | void (*fn)(unsigned long); |
1166 | unsigned long data; | 1193 | unsigned long data; |
@@ -1523,9 +1550,8 @@ static int init_timers_cpu(int cpu) | |||
1523 | if (!base) | 1550 | if (!base) |
1524 | return -ENOMEM; | 1551 | return -ENOMEM; |
1525 | 1552 | ||
1526 | /* Make sure that tvec_base is 2 byte aligned */ | 1553 | /* Make sure tvec_base has TIMER_FLAG_MASK bits free */ |
1527 | if (tbase_get_deferrable(base)) { | 1554 | if (WARN_ON(base != tbase_get_base(base))) { |
1528 | WARN_ON(1); | ||
1529 | kfree(base); | 1555 | kfree(base); |
1530 | return -ENOMEM; | 1556 | return -ENOMEM; |
1531 | } | 1557 | } |
@@ -1559,6 +1585,7 @@ static int init_timers_cpu(int cpu) | |||
1559 | base->timer_jiffies = jiffies; | 1585 | base->timer_jiffies = jiffies; |
1560 | base->next_timer = base->timer_jiffies; | 1586 | base->next_timer = base->timer_jiffies; |
1561 | base->active_timers = 0; | 1587 | base->active_timers = 0; |
1588 | base->all_timers = 0; | ||
1562 | return 0; | 1589 | return 0; |
1563 | } | 1590 | } |
1564 | 1591 | ||
@@ -1648,9 +1675,9 @@ void __init init_timers(void) | |||
1648 | 1675 | ||
1649 | err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, | 1676 | err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, |
1650 | (void *)(long)smp_processor_id()); | 1677 | (void *)(long)smp_processor_id()); |
1651 | init_timer_stats(); | ||
1652 | |||
1653 | BUG_ON(err != NOTIFY_OK); | 1678 | BUG_ON(err != NOTIFY_OK); |
1679 | |||
1680 | init_timer_stats(); | ||
1654 | register_cpu_notifier(&timers_nb); | 1681 | register_cpu_notifier(&timers_nb); |
1655 | open_softirq(TIMER_SOFTIRQ, run_timer_softirq); | 1682 | open_softirq(TIMER_SOFTIRQ, run_timer_softirq); |
1656 | } | 1683 | } |