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 | ||
