diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-15 13:06:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-15 13:06:19 -0400 |
commit | 19035e5b5d1e3127b4925d86f6a77964f91f2c3c (patch) | |
tree | c9e7e9073970176a5b0970da715cb6430c3c9069 /kernel/timer.c | |
parent | f9db6e095115f9411b9647bdb9d81fe11f3d8b54 (diff) | |
parent | eea08f32adb3f97553d49a4f79a119833036000a (diff) |
Merge branch 'timers-for-linus-migration' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-for-linus-migration' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
timers: Logic to move non pinned timers
timers: /proc/sys sysctl hook to enable timer migration
timers: Identifying the existing pinned timers
timers: Framework for identifying pinned timers
timers: allow deferrable timers for intervals tv2-tv5 to be deferred
Fix up conflicts in kernel/sched.c and kernel/timer.c manually
Diffstat (limited to 'kernel/timer.c')
-rw-r--r-- | kernel/timer.c | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index faf2db897de4..54d3912f8cad 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> |
@@ -605,13 +606,12 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer, | |||
605 | } | 606 | } |
606 | 607 | ||
607 | static inline int | 608 | static inline int |
608 | __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only) | 609 | __mod_timer(struct timer_list *timer, unsigned long expires, |
610 | bool pending_only, int pinned) | ||
609 | { | 611 | { |
610 | struct tvec_base *base, *new_base; | 612 | struct tvec_base *base, *new_base; |
611 | unsigned long flags; | 613 | unsigned long flags; |
612 | int ret; | 614 | int ret = 0 , cpu; |
613 | |||
614 | ret = 0; | ||
615 | 615 | ||
616 | timer_stats_timer_set_start_info(timer); | 616 | timer_stats_timer_set_start_info(timer); |
617 | BUG_ON(!timer->function); | 617 | BUG_ON(!timer->function); |
@@ -630,6 +630,18 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only) | |||
630 | 630 | ||
631 | new_base = __get_cpu_var(tvec_bases); | 631 | new_base = __get_cpu_var(tvec_bases); |
632 | 632 | ||
633 | cpu = smp_processor_id(); | ||
634 | |||
635 | #if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP) | ||
636 | if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) { | ||
637 | int preferred_cpu = get_nohz_load_balancer(); | ||
638 | |||
639 | if (preferred_cpu >= 0) | ||
640 | cpu = preferred_cpu; | ||
641 | } | ||
642 | #endif | ||
643 | new_base = per_cpu(tvec_bases, cpu); | ||
644 | |||
633 | if (base != new_base) { | 645 | if (base != new_base) { |
634 | /* | 646 | /* |
635 | * We are trying to schedule the timer on the local CPU. | 647 | * We are trying to schedule the timer on the local CPU. |
@@ -669,7 +681,7 @@ out_unlock: | |||
669 | */ | 681 | */ |
670 | int mod_timer_pending(struct timer_list *timer, unsigned long expires) | 682 | int mod_timer_pending(struct timer_list *timer, unsigned long expires) |
671 | { | 683 | { |
672 | return __mod_timer(timer, expires, true); | 684 | return __mod_timer(timer, expires, true, TIMER_NOT_PINNED); |
673 | } | 685 | } |
674 | EXPORT_SYMBOL(mod_timer_pending); | 686 | EXPORT_SYMBOL(mod_timer_pending); |
675 | 687 | ||
@@ -703,11 +715,33 @@ int mod_timer(struct timer_list *timer, unsigned long expires) | |||
703 | if (timer->expires == expires && timer_pending(timer)) | 715 | if (timer->expires == expires && timer_pending(timer)) |
704 | return 1; | 716 | return 1; |
705 | 717 | ||
706 | return __mod_timer(timer, expires, false); | 718 | return __mod_timer(timer, expires, false, TIMER_NOT_PINNED); |
707 | } | 719 | } |
708 | EXPORT_SYMBOL(mod_timer); | 720 | EXPORT_SYMBOL(mod_timer); |
709 | 721 | ||
710 | /** | 722 | /** |
723 | * mod_timer_pinned - modify a timer's timeout | ||
724 | * @timer: the timer to be modified | ||
725 | * @expires: new timeout in jiffies | ||
726 | * | ||
727 | * mod_timer_pinned() is a way to update the expire field of an | ||
728 | * active timer (if the timer is inactive it will be activated) | ||
729 | * and not allow the timer to be migrated to a different CPU. | ||
730 | * | ||
731 | * mod_timer_pinned(timer, expires) is equivalent to: | ||
732 | * | ||
733 | * del_timer(timer); timer->expires = expires; add_timer(timer); | ||
734 | */ | ||
735 | int mod_timer_pinned(struct timer_list *timer, unsigned long expires) | ||
736 | { | ||
737 | if (timer->expires == expires && timer_pending(timer)) | ||
738 | return 1; | ||
739 | |||
740 | return __mod_timer(timer, expires, false, TIMER_PINNED); | ||
741 | } | ||
742 | EXPORT_SYMBOL(mod_timer_pinned); | ||
743 | |||
744 | /** | ||
711 | * add_timer - start a timer | 745 | * add_timer - start a timer |
712 | * @timer: the timer to be added | 746 | * @timer: the timer to be added |
713 | * | 747 | * |
@@ -1017,6 +1051,9 @@ cascade: | |||
1017 | index = slot = timer_jiffies & TVN_MASK; | 1051 | index = slot = timer_jiffies & TVN_MASK; |
1018 | do { | 1052 | do { |
1019 | list_for_each_entry(nte, varp->vec + slot, entry) { | 1053 | list_for_each_entry(nte, varp->vec + slot, entry) { |
1054 | if (tbase_get_deferrable(nte->base)) | ||
1055 | continue; | ||
1056 | |||
1020 | found = 1; | 1057 | found = 1; |
1021 | if (time_before(nte->expires, expires)) | 1058 | if (time_before(nte->expires, expires)) |
1022 | expires = nte->expires; | 1059 | expires = nte->expires; |
@@ -1307,7 +1344,7 @@ signed long __sched schedule_timeout(signed long timeout) | |||
1307 | expire = timeout + jiffies; | 1344 | expire = timeout + jiffies; |
1308 | 1345 | ||
1309 | setup_timer_on_stack(&timer, process_timeout, (unsigned long)current); | 1346 | setup_timer_on_stack(&timer, process_timeout, (unsigned long)current); |
1310 | __mod_timer(&timer, expire, false); | 1347 | __mod_timer(&timer, expire, false, TIMER_NOT_PINNED); |
1311 | schedule(); | 1348 | schedule(); |
1312 | del_singleshot_timer_sync(&timer); | 1349 | del_singleshot_timer_sync(&timer); |
1313 | 1350 | ||