diff options
-rw-r--r-- | include/linux/hrtimer.h | 7 | ||||
-rw-r--r-- | include/linux/timer.h | 3 | ||||
-rw-r--r-- | kernel/hrtimer.c | 7 | ||||
-rw-r--r-- | kernel/timer.c | 31 |
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 | */ |
32 | enum hrtimer_mode { | 32 | enum 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); | |||
163 | extern int del_timer(struct timer_list * timer); | 163 | extern int del_timer(struct timer_list * timer); |
164 | extern int mod_timer(struct timer_list *timer, unsigned long expires); | 164 | extern int mod_timer(struct timer_list *timer, unsigned long expires); |
165 | extern int mod_timer_pending(struct timer_list *timer, unsigned long expires); | 165 | extern int mod_timer_pending(struct timer_list *timer, unsigned long expires); |
166 | extern 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 | */ |
195 | static inline struct hrtimer_clock_base * | 195 | static inline struct hrtimer_clock_base * |
196 | switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base) | 196 | switch_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 | ||
606 | static inline int | 606 | static 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 | */ |
669 | int mod_timer_pending(struct timer_list *timer, unsigned long expires) | 670 | int 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 | } |
673 | EXPORT_SYMBOL(mod_timer_pending); | 674 | EXPORT_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 | } |
707 | EXPORT_SYMBOL(mod_timer); | 708 | EXPORT_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 | */ | ||
723 | int 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 | } | ||
730 | EXPORT_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 | ||