diff options
| author | Oleg Nesterov <oleg@tv-sign.ru> | 2006-03-31 05:30:30 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-31 15:18:52 -0500 |
| commit | 3691c5199e8a4be1c7a91b5ab925db5feb866e19 (patch) | |
| tree | 025210545818b080df13faa31c9266432579794c | |
| parent | 5ce29646ebe352587e3b3160d599010c5da1b9dd (diff) | |
[PATCH] kill __init_timer_base in favor of boot_tvec_bases
Commit a4a6198b80cf82eb8160603c98da218d1bd5e104:
[PATCH] tvec_bases too large for per-cpu data
introduced "struct tvec_t_base_s boot_tvec_bases" which is visible at
compile time. This means we can kill __init_timer_base and move
timer_base_s's content into tvec_t_base_s.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | include/linux/timer.h | 8 | ||||
| -rw-r--r-- | kernel/timer.c | 84 |
2 files changed, 39 insertions, 53 deletions
diff --git a/include/linux/timer.h b/include/linux/timer.h index b5caabca55..0a485beba9 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <linux/spinlock.h> | 6 | #include <linux/spinlock.h> |
| 7 | #include <linux/stddef.h> | 7 | #include <linux/stddef.h> |
| 8 | 8 | ||
| 9 | struct timer_base_s; | 9 | struct tvec_t_base_s; |
| 10 | 10 | ||
| 11 | struct timer_list { | 11 | struct timer_list { |
| 12 | struct list_head entry; | 12 | struct list_head entry; |
| @@ -15,16 +15,16 @@ struct timer_list { | |||
| 15 | void (*function)(unsigned long); | 15 | void (*function)(unsigned long); |
| 16 | unsigned long data; | 16 | unsigned long data; |
| 17 | 17 | ||
| 18 | struct timer_base_s *base; | 18 | struct tvec_t_base_s *base; |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | extern struct timer_base_s __init_timer_base; | 21 | extern struct tvec_t_base_s boot_tvec_bases; |
| 22 | 22 | ||
| 23 | #define TIMER_INITIALIZER(_function, _expires, _data) { \ | 23 | #define TIMER_INITIALIZER(_function, _expires, _data) { \ |
| 24 | .function = (_function), \ | 24 | .function = (_function), \ |
| 25 | .expires = (_expires), \ | 25 | .expires = (_expires), \ |
| 26 | .data = (_data), \ | 26 | .data = (_data), \ |
| 27 | .base = &__init_timer_base, \ | 27 | .base = &boot_tvec_bases, \ |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | #define DEFINE_TIMER(_name, _function, _expires, _data) \ | 30 | #define DEFINE_TIMER(_name, _function, _expires, _data) \ |
diff --git a/kernel/timer.c b/kernel/timer.c index ab189dd187..b04dc03b59 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
| @@ -54,7 +54,6 @@ EXPORT_SYMBOL(jiffies_64); | |||
| 54 | /* | 54 | /* |
| 55 | * per-CPU timer vector definitions: | 55 | * per-CPU timer vector definitions: |
| 56 | */ | 56 | */ |
| 57 | |||
| 58 | #define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6) | 57 | #define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6) |
| 59 | #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8) | 58 | #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8) |
| 60 | #define TVN_SIZE (1 << TVN_BITS) | 59 | #define TVN_SIZE (1 << TVN_BITS) |
| @@ -62,11 +61,6 @@ EXPORT_SYMBOL(jiffies_64); | |||
| 62 | #define TVN_MASK (TVN_SIZE - 1) | 61 | #define TVN_MASK (TVN_SIZE - 1) |
| 63 | #define TVR_MASK (TVR_SIZE - 1) | 62 | #define TVR_MASK (TVR_SIZE - 1) |
| 64 | 63 | ||
| 65 | struct timer_base_s { | ||
| 66 | spinlock_t lock; | ||
| 67 | struct timer_list *running_timer; | ||
| 68 | }; | ||
| 69 | |||
| 70 | typedef struct tvec_s { | 64 | typedef struct tvec_s { |
| 71 | struct list_head vec[TVN_SIZE]; | 65 | struct list_head vec[TVN_SIZE]; |
| 72 | } tvec_t; | 66 | } tvec_t; |
| @@ -76,7 +70,8 @@ typedef struct tvec_root_s { | |||
| 76 | } tvec_root_t; | 70 | } tvec_root_t; |
| 77 | 71 | ||
| 78 | struct tvec_t_base_s { | 72 | struct tvec_t_base_s { |
| 79 | struct timer_base_s t_base; | 73 | spinlock_t lock; |
| 74 | struct timer_list *running_timer; | ||
| 80 | unsigned long timer_jiffies; | 75 | unsigned long timer_jiffies; |
| 81 | tvec_root_t tv1; | 76 | tvec_root_t tv1; |
| 82 | tvec_t tv2; | 77 | tvec_t tv2; |
| @@ -87,13 +82,14 @@ struct tvec_t_base_s { | |||
| 87 | 82 | ||
| 88 | typedef struct tvec_t_base_s tvec_base_t; | 83 | typedef struct tvec_t_base_s tvec_base_t; |
| 89 | static DEFINE_PER_CPU(tvec_base_t *, tvec_bases); | 84 | static DEFINE_PER_CPU(tvec_base_t *, tvec_bases); |
| 90 | static tvec_base_t boot_tvec_bases; | 85 | tvec_base_t boot_tvec_bases; |
| 86 | EXPORT_SYMBOL(boot_tvec_bases); | ||
| 91 | 87 | ||
| 92 | static inline void set_running_timer(tvec_base_t *base, | 88 | static inline void set_running_timer(tvec_base_t *base, |
| 93 | struct timer_list *timer) | 89 | struct timer_list *timer) |
| 94 | { | 90 | { |
| 95 | #ifdef CONFIG_SMP | 91 | #ifdef CONFIG_SMP |
| 96 | base->t_base.running_timer = timer; | 92 | base->running_timer = timer; |
| 97 | #endif | 93 | #endif |
| 98 | } | 94 | } |
| 99 | 95 | ||
| @@ -139,15 +135,6 @@ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer) | |||
| 139 | list_add_tail(&timer->entry, vec); | 135 | list_add_tail(&timer->entry, vec); |
| 140 | } | 136 | } |
| 141 | 137 | ||
| 142 | typedef struct timer_base_s timer_base_t; | ||
| 143 | /* | ||
| 144 | * Used by TIMER_INITIALIZER, we can't use per_cpu(tvec_bases) | ||
| 145 | * at compile time, and we need timer->base to lock the timer. | ||
| 146 | */ | ||
| 147 | timer_base_t __init_timer_base | ||
| 148 | ____cacheline_aligned_in_smp = { .lock = SPIN_LOCK_UNLOCKED }; | ||
| 149 | EXPORT_SYMBOL(__init_timer_base); | ||
| 150 | |||
| 151 | /*** | 138 | /*** |
| 152 | * init_timer - initialize a timer. | 139 | * init_timer - initialize a timer. |
| 153 | * @timer: the timer to be initialized | 140 | * @timer: the timer to be initialized |
| @@ -158,7 +145,7 @@ EXPORT_SYMBOL(__init_timer_base); | |||
| 158 | void fastcall init_timer(struct timer_list *timer) | 145 | void fastcall init_timer(struct timer_list *timer) |
| 159 | { | 146 | { |
| 160 | timer->entry.next = NULL; | 147 | timer->entry.next = NULL; |
| 161 | timer->base = &per_cpu(tvec_bases, raw_smp_processor_id())->t_base; | 148 | timer->base = per_cpu(tvec_bases, raw_smp_processor_id()); |
| 162 | } | 149 | } |
| 163 | EXPORT_SYMBOL(init_timer); | 150 | EXPORT_SYMBOL(init_timer); |
| 164 | 151 | ||
| @@ -174,7 +161,7 @@ static inline void detach_timer(struct timer_list *timer, | |||
| 174 | } | 161 | } |
| 175 | 162 | ||
| 176 | /* | 163 | /* |
| 177 | * We are using hashed locking: holding per_cpu(tvec_bases).t_base.lock | 164 | * We are using hashed locking: holding per_cpu(tvec_bases).lock |
| 178 | * means that all timers which are tied to this base via timer->base are | 165 | * means that all timers which are tied to this base via timer->base are |
| 179 | * locked, and the base itself is locked too. | 166 | * locked, and the base itself is locked too. |
| 180 | * | 167 | * |
| @@ -185,10 +172,10 @@ static inline void detach_timer(struct timer_list *timer, | |||
| 185 | * possible to set timer->base = NULL and drop the lock: the timer remains | 172 | * possible to set timer->base = NULL and drop the lock: the timer remains |
| 186 | * locked. | 173 | * locked. |
| 187 | */ | 174 | */ |
| 188 | static timer_base_t *lock_timer_base(struct timer_list *timer, | 175 | static tvec_base_t *lock_timer_base(struct timer_list *timer, |
| 189 | unsigned long *flags) | 176 | unsigned long *flags) |
| 190 | { | 177 | { |
| 191 | timer_base_t *base; | 178 | tvec_base_t *base; |
| 192 | 179 | ||
| 193 | for (;;) { | 180 | for (;;) { |
| 194 | base = timer->base; | 181 | base = timer->base; |
| @@ -205,8 +192,7 @@ static timer_base_t *lock_timer_base(struct timer_list *timer, | |||
| 205 | 192 | ||
| 206 | int __mod_timer(struct timer_list *timer, unsigned long expires) | 193 | int __mod_timer(struct timer_list *timer, unsigned long expires) |
| 207 | { | 194 | { |
| 208 | timer_base_t *base; | 195 | tvec_base_t *base, *new_base; |
| 209 | tvec_base_t *new_base; | ||
| 210 | unsigned long flags; | 196 | unsigned long flags; |
| 211 | int ret = 0; | 197 | int ret = 0; |
| 212 | 198 | ||
| @@ -221,7 +207,7 @@ int __mod_timer(struct timer_list *timer, unsigned long expires) | |||
| 221 | 207 | ||
| 222 | new_base = __get_cpu_var(tvec_bases); | 208 | new_base = __get_cpu_var(tvec_bases); |
| 223 | 209 | ||
| 224 | if (base != &new_base->t_base) { | 210 | if (base != new_base) { |
| 225 | /* | 211 | /* |
| 226 | * We are trying to schedule the timer on the local CPU. | 212 | * We are trying to schedule the timer on the local CPU. |
| 227 | * However we can't change timer's base while it is running, | 213 | * However we can't change timer's base while it is running, |
| @@ -231,19 +217,19 @@ int __mod_timer(struct timer_list *timer, unsigned long expires) | |||
| 231 | */ | 217 | */ |
| 232 | if (unlikely(base->running_timer == timer)) { | 218 | if (unlikely(base->running_timer == timer)) { |
| 233 | /* The timer remains on a former base */ | 219 | /* The timer remains on a former base */ |
| 234 | new_base = container_of(base, tvec_base_t, t_base); | 220 | new_base = base; |
| 235 | } else { | 221 | } else { |
| 236 | /* See the comment in lock_timer_base() */ | 222 | /* See the comment in lock_timer_base() */ |
| 237 | timer->base = NULL; | 223 | timer->base = NULL; |
| 238 | spin_unlock(&base->lock); | 224 | spin_unlock(&base->lock); |
| 239 | spin_lock(&new_base->t_base.lock); | 225 | spin_lock(&new_base->lock); |
| 240 | timer->base = &new_base->t_base; | 226 | timer->base = new_base; |
| 241 | } | 227 | } |
| 242 | } | 228 | } |
| 243 | 229 | ||
| 244 | timer->expires = expires; | 230 | timer->expires = expires; |
| 245 | internal_add_timer(new_base, timer); | 231 | internal_add_timer(new_base, timer); |
| 246 | spin_unlock_irqrestore(&new_base->t_base.lock, flags); | 232 | spin_unlock_irqrestore(&new_base->lock, flags); |
| 247 | 233 | ||
| 248 | return ret; | 234 | return ret; |
| 249 | } | 235 | } |
| @@ -263,10 +249,10 @@ void add_timer_on(struct timer_list *timer, int cpu) | |||
| 263 | unsigned long flags; | 249 | unsigned long flags; |
| 264 | 250 | ||
| 265 | BUG_ON(timer_pending(timer) || !timer->function); | 251 | BUG_ON(timer_pending(timer) || !timer->function); |
| 266 | spin_lock_irqsave(&base->t_base.lock, flags); | 252 | spin_lock_irqsave(&base->lock, flags); |
| 267 | timer->base = &base->t_base; | 253 | timer->base = base; |
| 268 | internal_add_timer(base, timer); | 254 | internal_add_timer(base, timer); |
| 269 | spin_unlock_irqrestore(&base->t_base.lock, flags); | 255 | spin_unlock_irqrestore(&base->lock, flags); |
| 270 | } | 256 | } |
| 271 | 257 | ||
| 272 | |||
