diff options
| -rw-r--r-- | include/linux/timer.h | 6 | ||||
| -rw-r--r-- | kernel/timer.c | 21 |
2 files changed, 17 insertions, 10 deletions
diff --git a/include/linux/timer.h b/include/linux/timer.h index 6abd9138beda..cbd32ec4dd15 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h | |||
| @@ -58,7 +58,9 @@ extern struct tvec_base boot_tvec_bases; | |||
| 58 | * the timer will be serviced when the CPU eventually wakes up with a | 58 | * the timer will be serviced when the CPU eventually wakes up with a |
| 59 | * subsequent non-deferrable timer. | 59 | * subsequent non-deferrable timer. |
| 60 | */ | 60 | */ |
| 61 | #define TBASE_DEFERRABLE_FLAG (0x1) | 61 | #define TIMER_DEFERRABLE 0x1LU |
| 62 | |||
| 63 | #define TIMER_FLAG_MASK 0x1LU | ||
| 62 | 64 | ||
| 63 | #define TIMER_INITIALIZER(_function, _expires, _data) { \ | 65 | #define TIMER_INITIALIZER(_function, _expires, _data) { \ |
| 64 | .entry = { .prev = TIMER_ENTRY_STATIC }, \ | 66 | .entry = { .prev = TIMER_ENTRY_STATIC }, \ |
| @@ -72,7 +74,7 @@ extern struct tvec_base boot_tvec_bases; | |||
| 72 | } | 74 | } |
| 73 | 75 | ||
| 74 | #define TBASE_MAKE_DEFERRED(ptr) ((struct tvec_base *) \ | 76 | #define TBASE_MAKE_DEFERRED(ptr) ((struct tvec_base *) \ |
| 75 | ((unsigned char *)(ptr) + TBASE_DEFERRABLE_FLAG)) | 77 | ((unsigned char *)(ptr) + TIMER_DEFERRABLE)) |
| 76 | 78 | ||
| 77 | #define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) {\ | 79 | #define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) {\ |
| 78 | .entry = { .prev = TIMER_ENTRY_STATIC }, \ | 80 | .entry = { .prev = TIMER_ENTRY_STATIC }, \ |
diff --git a/kernel/timer.c b/kernel/timer.c index a61c09374eba..cf7af56940b7 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
| @@ -92,12 +92,12 @@ static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases; | |||
| 92 | /* Functions below help us manage 'deferrable' flag */ | 92 | /* Functions below help us manage 'deferrable' flag */ |
| 93 | static inline unsigned int tbase_get_deferrable(struct tvec_base *base) | 93 | static inline unsigned int tbase_get_deferrable(struct tvec_base *base) |
| 94 | { | 94 | { |
| 95 | return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG); | 95 | return ((unsigned int)(unsigned long)base & TIMER_DEFERRABLE); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static inline struct tvec_base *tbase_get_base(struct tvec_base *base) | 98 | static inline struct tvec_base *tbase_get_base(struct tvec_base *base) |
| 99 | { | 99 | { |
| 100 | return ((struct tvec_base *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG)); | 100 | return ((struct tvec_base *)((unsigned long)base & ~TIMER_FLAG_MASK)); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | static inline void timer_set_deferrable(struct timer_list *timer) | 103 | static inline void timer_set_deferrable(struct timer_list *timer) |
| @@ -108,8 +108,9 @@ static inline void timer_set_deferrable(struct timer_list *timer) | |||
| 108 | static inline void | 108 | static inline void |
| 109 | timer_set_base(struct timer_list *timer, struct tvec_base *new_base) | 109 | timer_set_base(struct timer_list *timer, struct tvec_base *new_base) |
| 110 | { | 110 | { |
| 111 | timer->base = (struct tvec_base *)((unsigned long)(new_base) | | 111 | unsigned long flags = (unsigned long)timer->base & TIMER_FLAG_MASK; |
| 112 | tbase_get_deferrable(timer->base)); | 112 | |
| 113 | timer->base = (struct tvec_base *)((unsigned long)(new_base) | flags); | ||
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | static unsigned long round_jiffies_common(unsigned long j, int cpu, | 116 | static unsigned long round_jiffies_common(unsigned long j, int cpu, |
| @@ -686,7 +687,7 @@ detach_expired_timer(struct timer_list *timer, struct tvec_base *base) | |||
| 686 | { | 687 | { |
| 687 | detach_timer(timer, true); | 688 | detach_timer(timer, true); |
| 688 | if (!tbase_get_deferrable(timer->base)) | 689 | if (!tbase_get_deferrable(timer->base)) |
| 689 | timer->base->active_timers--; | 690 | base->active_timers--; |
| 690 | } | 691 | } |
| 691 | 692 | ||
| 692 | static int detach_if_pending(struct timer_list *timer, struct tvec_base *base, | 693 | static int detach_if_pending(struct timer_list *timer, struct tvec_base *base, |
| @@ -697,7 +698,7 @@ static int detach_if_pending(struct timer_list *timer, struct tvec_base *base, | |||
| 697 | 698 | ||
| 698 | detach_timer(timer, clear_pending); | 699 | detach_timer(timer, clear_pending); |
| 699 | if (!tbase_get_deferrable(timer->base)) { | 700 | if (!tbase_get_deferrable(timer->base)) { |
| 700 | timer->base->active_timers--; | 701 | base->active_timers--; |
| 701 | if (timer->expires == base->next_timer) | 702 | if (timer->expires == base->next_timer) |
| 702 | base->next_timer = base->timer_jiffies; | 703 | base->next_timer = base->timer_jiffies; |
| 703 | } | 704 | } |
| @@ -1800,9 +1801,13 @@ static struct notifier_block __cpuinitdata timers_nb = { | |||
| 1800 | 1801 | ||
| 1801 | void __init init_timers(void) | 1802 | void __init init_timers(void) |
| 1802 | { | 1803 | { |
| 1803 | int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, | 1804 | int err; |
| 1804 | (void *)(long)smp_processor_id()); | 1805 | |
| 1806 | /* ensure there are enough low bits for flags in timer->base pointer */ | ||
| 1807 | BUILD_BUG_ON(__alignof__(struct tvec_base) & TIMER_FLAG_MASK); | ||
| 1805 | 1808 | ||
| 1809 | err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, | ||
| 1810 | (void *)(long)smp_processor_id()); | ||
| 1806 | init_timer_stats(); | 1811 | init_timer_stats(); |
| 1807 | 1812 | ||
| 1808 | BUG_ON(err != NOTIFY_OK); | 1813 | BUG_ON(err != NOTIFY_OK); |
