diff options
Diffstat (limited to 'kernel/timer.c')
| -rw-r--r-- | kernel/timer.c | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index c01e568935ea..a7f07d5a6241 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/tick.h> | 38 | #include <linux/tick.h> |
| 39 | #include <linux/kallsyms.h> | 39 | #include <linux/kallsyms.h> |
| 40 | #include <linux/perf_counter.h> | 40 | #include <linux/perf_counter.h> |
| 41 | #include <linux/sched.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
| 43 | #include <asm/unistd.h> | 44 | #include <asm/unistd.h> |
| @@ -379,6 +380,8 @@ static void timer_stats_account_timer(struct timer_list *timer) | |||
| 379 | { | 380 | { |
| 380 | unsigned int flag = 0; | 381 | unsigned int flag = 0; |
| 381 | 382 | ||
| 383 | if (likely(!timer->start_site)) | ||
| 384 | return; | ||
| 382 | if (unlikely(tbase_get_deferrable(timer->base))) | 385 | if (unlikely(tbase_get_deferrable(timer->base))) |
| 383 | flag |= TIMER_STATS_FLAG_DEFERRABLE; | 386 | flag |= TIMER_STATS_FLAG_DEFERRABLE; |
| 384 | 387 | ||
| @@ -605,13 +608,12 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer, | |||
| 605 | } | 608 | } |
| 606 | 609 | ||
| 607 | static inline int | 610 | static inline int |
| 608 | __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only) | 611 | __mod_timer(struct timer_list *timer, unsigned long expires, |
| 612 | bool pending_only, int pinned) | ||
| 609 | { | 613 | { |
| 610 | struct tvec_base *base, *new_base; | 614 | struct tvec_base *base, *new_base; |
| 611 | unsigned long flags; | 615 | unsigned long flags; |
| 612 | int ret; | 616 | int ret = 0 , cpu; |
| 613 | |||
| 614 | ret = 0; | ||
| 615 | 617 | ||
| 616 | timer_stats_timer_set_start_info(timer); | 618 | timer_stats_timer_set_start_info(timer); |
| 617 | BUG_ON(!timer->function); | 619 | BUG_ON(!timer->function); |
| @@ -630,6 +632,18 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only) | |||
| 630 | 632 | ||
| 631 | new_base = __get_cpu_var(tvec_bases); | 633 | new_base = __get_cpu_var(tvec_bases); |
| 632 | 634 | ||
| 635 | cpu = smp_processor_id(); | ||
| 636 | |||
| 637 | #if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP) | ||
| 638 | if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) { | ||
| 639 | int preferred_cpu = get_nohz_load_balancer(); | ||
| 640 | |||
| 641 | if (preferred_cpu >= 0) | ||
| 642 | cpu = preferred_cpu; | ||
| 643 | } | ||
| 644 | #endif | ||
| 645 | new_base = per_cpu(tvec_bases, cpu); | ||
| 646 | |||
| 633 | if (base != new_base) { | 647 | if (base != new_base) { |
| 634 | /* | 648 | /* |
| 635 | * We are trying to schedule the timer on the local CPU. | 649 | * We are trying to schedule the timer on the local CPU. |
| @@ -669,7 +683,7 @@ out_unlock: | |||
| 669 | */ | 683 | */ |
| 670 | int mod_timer_pending(struct timer_list *timer, unsigned long expires) | 684 | int mod_timer_pending(struct timer_list *timer, unsigned long expires) |
| 671 | { | 685 | { |
| 672 | return __mod_timer(timer, expires, true); | 686 | return __mod_timer(timer, expires, true, TIMER_NOT_PINNED); |
| 673 | } | 687 | } |
| 674 | EXPORT_SYMBOL(mod_timer_pending); | 688 | EXPORT_SYMBOL(mod_timer_pending); |
| 675 | 689 | ||
| @@ -700,14 +714,36 @@ int mod_timer(struct timer_list *timer, unsigned long expires) | |||
| 700 | * networking code - if the timer is re-modified | 714 | * networking code - if the timer is re-modified |
| 701 | * to be the same thing then just return: | 715 | * to be the same thing then just return: |
| 702 | */ | 716 | */ |
| 703 | if (timer->expires == expires && timer_pending(timer)) | 717 | if (timer_pending(timer) && timer->expires == expires) |
| 704 | return 1; | 718 | return 1; |
| 705 | 719 | ||
| 706 | return __mod_timer(timer, expires, false); | 720 | return __mod_timer(timer, expires, false, TIMER_NOT_PINNED); |
| 707 | } | 721 | } |
| 708 | EXPORT_SYMBOL(mod_timer); | 722 | EXPORT_SYMBOL(mod_timer); |
| 709 | 723 | ||
| 710 | /** | 724 | /** |
| 725 | * mod_timer_pinned - modify a timer's timeout | ||
| 726 | * @timer: the timer to be modified | ||
| 727 | * @expires: new timeout in jiffies | ||
| 728 | * | ||
| 729 | * mod_timer_pinned() is a way to update the expire field of an | ||
| 730 | * active timer (if the timer is inactive it will be activated) | ||
| 731 | * and not allow the timer to be migrated to a different CPU. | ||
| 732 | * | ||
| 733 | * mod_timer_pinned(timer, expires) is equivalent to: | ||
| 734 | * | ||
| 735 | * del_timer(timer); timer->expires = expires; add_timer(timer); | ||
| 736 | */ | ||
| 737 | int mod_timer_pinned(struct timer_list *timer, unsigned long expires) | ||
| 738 | { | ||
| 739 | if (timer->expires == expires && timer_pending(timer)) | ||
| 740 | return 1; | ||
| 741 | |||
| 742 | return __mod_timer(timer, expires, false, TIMER_PINNED); | ||
| 743 | } | ||
| 744 | EXPORT_SYMBOL(mod_timer_pinned); | ||
| 745 | |||
| 746 | /** | ||
| 711 | * add_timer - start a timer | 747 | * add_timer - start a timer |
| 712 | * @timer: the timer to be added | 748 | * @timer: the timer to be added |
| 713 | * | 749 | * |
| @@ -757,6 +793,7 @@ void add_timer_on(struct timer_list *timer, int cpu) | |||
| 757 | wake_up_idle_cpu(cpu); | 793 | wake_up_idle_cpu(cpu); |
| 758 | spin_unlock_irqrestore(&base->lock, flags); | 794 | spin_unlock_irqrestore(&base->lock, flags); |
| 759 | } | 795 | } |
| 796 | EXPORT_SYMBOL_GPL(add_timer_on); | ||
| 760 | 797 | ||
| 761 | /** | 798 | /** |
| 762 | * del_timer - deactive a timer. | 799 | * del_timer - deactive a timer. |
| @@ -1016,6 +1053,9 @@ cascade: | |||
| 1016 | index = slot = timer_jiffies & TVN_MASK; | 1053 | index = slot = timer_jiffies & TVN_MASK; |
| 1017 | do { | 1054 | do { |
| 1018 | list_for_each_entry(nte, varp->vec + slot, entry) { | 1055 | list_for_each_entry(nte, varp->vec + slot, entry) { |
| 1056 | if (tbase_get_deferrable(nte->base)) | ||
| 1057 | continue; | ||
| 1058 | |||
| 1019 | found = 1; | 1059 | found = 1; |
| 1020 | if (time_before(nte->expires, expires)) | 1060 | if (time_before(nte->expires, expires)) |
| 1021 | expires = nte->expires; | 1061 | expires = nte->expires; |
| @@ -1306,7 +1346,7 @@ signed long __sched schedule_timeout(signed long timeout) | |||
| 1306 | expire = timeout + jiffies; | 1346 | expire = timeout + jiffies; |
| 1307 | 1347 | ||
| 1308 | setup_timer_on_stack(&timer, process_timeout, (unsigned long)current); | 1348 | setup_timer_on_stack(&timer, process_timeout, (unsigned long)current); |
| 1309 | __mod_timer(&timer, expire, false); | 1349 | __mod_timer(&timer, expire, false, TIMER_NOT_PINNED); |
| 1310 | schedule(); | 1350 | schedule(); |
| 1311 | del_singleshot_timer_sync(&timer); | 1351 | del_singleshot_timer_sync(&timer); |
| 1312 | 1352 | ||
