aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/timer.c')
-rw-r--r--kernel/timer.c56
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
607static inline int 610static 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 */
670int mod_timer_pending(struct timer_list *timer, unsigned long expires) 684int 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}
674EXPORT_SYMBOL(mod_timer_pending); 688EXPORT_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}
708EXPORT_SYMBOL(mod_timer); 722EXPORT_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 */
737int 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}
744EXPORT_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}
796EXPORT_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