aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/hrtimer.h7
-rw-r--r--include/linux/timer.h3
-rw-r--r--kernel/hrtimer.c7
-rw-r--r--kernel/timer.c31
4 files changed, 39 insertions, 9 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 0d2f7c8a33d6..7400900de94a 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -30,8 +30,11 @@ struct hrtimer_cpu_base;
30 * Mode arguments of xxx_hrtimer functions: 30 * Mode arguments of xxx_hrtimer functions:
31 */ 31 */
32enum hrtimer_mode { 32enum hrtimer_mode {
33 HRTIMER_MODE_ABS, /* Time value is absolute */ 33 HRTIMER_MODE_ABS = 0x0, /* Time value is absolute */
34 HRTIMER_MODE_REL, /* Time value is relative to now */ 34 HRTIMER_MODE_REL = 0x1, /* Time value is relative to now */
35 HRTIMER_MODE_PINNED = 0x02, /* Timer is bound to CPU */
36 HRTIMER_MODE_ABS_PINNED = 0x02,
37 HRTIMER_MODE_REL_PINNED = 0x03,
35}; 38};
36 39
37/* 40/*
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 6cdb6f3331f1..ccf882eed8f8 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -163,7 +163,10 @@ extern void add_timer_on(struct timer_list *timer, int cpu);
163extern int del_timer(struct timer_list * timer); 163extern int del_timer(struct timer_list * timer);
164extern int mod_timer(struct timer_list *timer, unsigned long expires); 164extern int mod_timer(struct timer_list *timer, unsigned long expires);
165extern int mod_timer_pending(struct timer_list *timer, unsigned long expires); 165extern int mod_timer_pending(struct timer_list *timer, unsigned long expires);
166extern int mod_timer_pinned(struct timer_list *timer, unsigned long expires);
166 167
168#define TIMER_NOT_PINNED 0
169#define TIMER_PINNED 1
167/* 170/*
168 * The jiffies value which is added to now, when there is no timer 171 * The jiffies value which is added to now, when there is no timer
169 * in the timer wheel: 172 * in the timer wheel:
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index cb8a15c19583..c71bcd549241 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -193,7 +193,8 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
193 * Switch the timer base to the current CPU when possible. 193 * Switch the timer base to the current CPU when possible.
194 */ 194 */
195static inline struct hrtimer_clock_base * 195static inline struct hrtimer_clock_base *
196switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base) 196switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
197 int pinned)
197{ 198{
198 struct hrtimer_clock_base *new_base; 199 struct hrtimer_clock_base *new_base;
199 struct hrtimer_cpu_base *new_cpu_base; 200 struct hrtimer_cpu_base *new_cpu_base;
@@ -907,9 +908,9 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
907 ret = remove_hrtimer(timer, base); 908 ret = remove_hrtimer(timer, base);
908 909
909 /* Switch the timer base, if necessary: */ 910 /* Switch the timer base, if necessary: */
910 new_base = switch_hrtimer_base(timer, base); 911 new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED);
911 912
912 if (mode == HRTIMER_MODE_REL) { 913 if (mode & HRTIMER_MODE_REL) {
913 tim = ktime_add_safe(tim, new_base->get_time()); 914 tim = ktime_add_safe(tim, new_base->get_time());
914 /* 915 /*
915 * CONFIG_TIME_LOW_RES is a temporary way for architectures 916 * CONFIG_TIME_LOW_RES is a temporary way for architectures
diff --git a/kernel/timer.c b/kernel/timer.c
index 5c1e84beaf4a..3424dfd11d50 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -604,7 +604,8 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer,
604} 604}
605 605
606static inline int 606static inline int
607__mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only) 607__mod_timer(struct timer_list *timer, unsigned long expires,
608 bool pending_only, int pinned)
608{ 609{
609 struct tvec_base *base, *new_base; 610 struct tvec_base *base, *new_base;
610 unsigned long flags; 611 unsigned long flags;
@@ -668,7 +669,7 @@ out_unlock:
668 */ 669 */
669int mod_timer_pending(struct timer_list *timer, unsigned long expires) 670int mod_timer_pending(struct timer_list *timer, unsigned long expires)
670{ 671{
671 return __mod_timer(timer, expires, true); 672 return __mod_timer(timer, expires, true, TIMER_NOT_PINNED);
672} 673}
673EXPORT_SYMBOL(mod_timer_pending); 674EXPORT_SYMBOL(mod_timer_pending);
674 675
@@ -702,11 +703,33 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
702 if (timer->expires == expires && timer_pending(timer)) 703 if (timer->expires == expires && timer_pending(timer))
703 return 1; 704 return 1;
704 705
705 return __mod_timer(timer, expires, false); 706 return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
706} 707}
707EXPORT_SYMBOL(mod_timer); 708EXPORT_SYMBOL(mod_timer);
708 709
709/** 710/**
711 * mod_timer_pinned - modify a timer's timeout
712 * @timer: the timer to be modified
713 * @expires: new timeout in jiffies
714 *
715 * mod_timer_pinned() is a way to update the expire field of an
716 * active timer (if the timer is inactive it will be activated)
717 * and not allow the timer to be migrated to a different CPU.
718 *
719 * mod_timer_pinned(timer, expires) is equivalent to:
720 *
721 * del_timer(timer); timer->expires = expires; add_timer(timer);
722 */
723int mod_timer_pinned(struct timer_list *timer, unsigned long expires)
724{
725 if (timer->expires == expires && timer_pending(timer))
726 return 1;
727
728 return __mod_timer(timer, expires, false, TIMER_PINNED);
729}
730EXPORT_SYMBOL(mod_timer_pinned);
731
732/**
710 * add_timer - start a timer 733 * add_timer - start a timer
711 * @timer: the timer to be added 734 * @timer: the timer to be added
712 * 735 *
@@ -1356,7 +1379,7 @@ signed long __sched schedule_timeout(signed long timeout)
1356 expire = timeout + jiffies; 1379 expire = timeout + jiffies;
1357 1380
1358 setup_timer_on_stack(&timer, process_timeout, (unsigned long)current); 1381 setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
1359 __mod_timer(&timer, expire, false); 1382 __mod_timer(&timer, expire, false, TIMER_NOT_PINNED);
1360 schedule(); 1383 schedule();
1361 del_singleshot_timer_sync(&timer); 1384 del_singleshot_timer_sync(&timer);
1362 1385