diff options
Diffstat (limited to 'kernel/timer.c')
| -rw-r--r-- | kernel/timer.c | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index accfd241b9e5..87bd529879c2 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | #define CREATE_TRACE_POINTS | 52 | #define CREATE_TRACE_POINTS |
| 53 | #include <trace/events/timer.h> | 53 | #include <trace/events/timer.h> |
| 54 | 54 | ||
| 55 | u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; | 55 | __visible u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; |
| 56 | 56 | ||
| 57 | EXPORT_SYMBOL(jiffies_64); | 57 | EXPORT_SYMBOL(jiffies_64); |
| 58 | 58 | ||
| @@ -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 | } |
