aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/timer.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2006-03-24 06:15:54 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-24 10:33:21 -0500
commita4a6198b80cf82eb8160603c98da218d1bd5e104 (patch)
tree8c59e9088840b6b95e46c00ddda4fd7a134154c2 /kernel/timer.c
parentc98d8cfbc600af88e9e6cffc84dd342280445760 (diff)
[PATCH] tvec_bases too large for per-cpu data
With internal Xen-enabled kernels we see the kernel's static per-cpu data area exceed the limit of 32k on x86-64, and even native x86-64 kernels get fairly close to that limit. I generally question whether it is reasonable to have data structures several kb in size allocated as per-cpu data when the space there is rather limited. The biggest arch-independent consumer is tvec_bases (over 4k on 32-bit archs, over 8k on 64-bit ones), which now gets converted to use dynamically allocated memory instead. Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/timer.c')
-rw-r--r--kernel/timer.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/kernel/timer.c b/kernel/timer.c
index 2410c18dbeb1..4427e725ccdd 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -86,7 +86,8 @@ struct tvec_t_base_s {
86} ____cacheline_aligned_in_smp; 86} ____cacheline_aligned_in_smp;
87 87
88typedef struct tvec_t_base_s tvec_base_t; 88typedef struct tvec_t_base_s tvec_base_t;
89static DEFINE_PER_CPU(tvec_base_t, tvec_bases); 89static DEFINE_PER_CPU(tvec_base_t *, tvec_bases);
90static tvec_base_t boot_tvec_bases;
90 91
91static inline void set_running_timer(tvec_base_t *base, 92static inline void set_running_timer(tvec_base_t *base,
92 struct timer_list *timer) 93 struct timer_list *timer)
@@ -157,7 +158,7 @@ EXPORT_SYMBOL(__init_timer_base);
157void fastcall init_timer(struct timer_list *timer) 158void fastcall init_timer(struct timer_list *timer)
158{ 159{
159 timer->entry.next = NULL; 160 timer->entry.next = NULL;
160 timer->base = &per_cpu(tvec_bases, raw_smp_processor_id()).t_base; 161 timer->base = &per_cpu(tvec_bases, raw_smp_processor_id())->t_base;
161} 162}
162EXPORT_SYMBOL(init_timer); 163EXPORT_SYMBOL(init_timer);
163 164
@@ -218,7 +219,7 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
218 ret = 1; 219 ret = 1;
219 } 220 }
220 221
221 new_base = &__get_cpu_var(tvec_bases); 222 new_base = __get_cpu_var(tvec_bases);
222 223
223 if (base != &new_base->t_base) { 224 if (base != &new_base->t_base) {
224 /* 225 /*
@@ -258,7 +259,7 @@ EXPORT_SYMBOL(__mod_timer);
258 */ 259 */
259void add_timer_on(struct timer_list *timer, int cpu) 260void add_timer_on(struct timer_list *timer, int cpu)
260{ 261{
261 tvec_base_t *base = &per_cpu(tvec_bases, cpu); 262 tvec_base_t *base = per_cpu(tvec_bases, cpu);
262 unsigned long flags; 263 unsigned long flags;
263 264
264 BUG_ON(timer_pending(timer) || !timer->function); 265 BUG_ON(timer_pending(timer) || !timer->function);
@@ -504,7 +505,7 @@ unsigned long next_timer_interrupt(void)
504 } 505 }
505 hr_expires += jiffies; 506 hr_expires += jiffies;
506 507
507 base = &__get_cpu_var(tvec_bases); 508 base = __get_cpu_var(tvec_bases);
508 spin_lock(&base->t_base.lock); 509 spin_lock(&base->t_base.lock);
509 expires = base->timer_jiffies + (LONG_MAX >> 1); 510 expires = base->timer_jiffies + (LONG_MAX >> 1);
510 list = NULL; 511 list = NULL;
@@ -901,7 +902,7 @@ EXPORT_SYMBOL(xtime_lock);
901 */ 902 */
902static void run_timer_softirq(struct softirq_action *h) 903static void run_timer_softirq(struct softirq_action *h)
903{ 904{
904 tvec_base_t *base = &__get_cpu_var(tvec_bases); 905 tvec_base_t *base = __get_cpu_var(tvec_bases);
905 906
906 hrtimer_run_queues(); 907 hrtimer_run_queues();
907 if (time_after_eq(jiffies, base->timer_jiffies)) 908 if (time_after_eq(jiffies, base->timer_jiffies))
@@ -1256,12 +1257,32 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info)
1256 return 0; 1257 return 0;
1257} 1258}
1258 1259
1259static void __devinit init_timers_cpu(int cpu) 1260static int __devinit init_timers_cpu(int cpu)
1260{ 1261{
1261 int j; 1262 int j;
1262 tvec_base_t *base; 1263 tvec_base_t *base;
1263 1264
1264 base = &per_cpu(tvec_bases, cpu); 1265 base = per_cpu(tvec_bases, cpu);
1266 if (!base) {
1267 static char boot_done;
1268
1269 /*
1270 * Cannot do allocation in init_timers as that runs before the
1271 * allocator initializes (and would waste memory if there are
1272 * more possible CPUs than will ever be installed/brought up).
1273 */
1274 if (boot_done) {
1275 base = kmalloc_node(sizeof(*base), GFP_KERNEL,
1276 cpu_to_node(cpu));
1277 if (!base)
1278 return -ENOMEM;
1279 memset(base, 0, sizeof(*base));
1280 } else {
1281 base = &boot_tvec_bases;
1282 boot_done = 1;
1283 }
1284 per_cpu(tvec_bases, cpu) = base;
1285 }
1265 spin_lock_init(&base->t_base.lock); 1286 spin_lock_init(&base->t_base.lock);
1266 for (j = 0; j < TVN_SIZE; j++) { 1287 for (j = 0; j < TVN_SIZE; j++) {
1267 INIT_LIST_HEAD(base->tv5.vec + j); 1288 INIT_LIST_HEAD(base->tv5.vec + j);
@@ -1273,6 +1294,7 @@ static void __devinit init_timers_cpu(int cpu)
1273 INIT_LIST_HEAD(base->tv1.vec + j); 1294 INIT_LIST_HEAD(base->tv1.vec + j);
1274 1295
1275 base->timer_jiffies = jiffies; 1296 base->timer_jiffies = jiffies;
1297 return 0;
1276} 1298}
1277 1299
1278#ifdef CONFIG_HOTPLUG_CPU 1300#ifdef CONFIG_HOTPLUG_CPU
@@ -1295,8 +1317,8 @@ static void __devinit migrate_timers(int cpu)
1295 int i; 1317 int i;
1296 1318
1297 BUG_ON(cpu_online(cpu)); 1319 BUG_ON(cpu_online(cpu));
1298 old_base = &per_cpu(tvec_bases, cpu); 1320 old_base = per_cpu(tvec_bases, cpu);
1299 new_base = &get_cpu_var(tvec_bases); 1321 new_base = get_cpu_var(tvec_bases);
1300 1322
1301 local_irq_disable(); 1323 local_irq_disable();
1302 spin_lock(&new_base->t_base.lock); 1324 spin_lock(&new_base->t_base.lock);
@@ -1326,7 +1348,8 @@ static int __devinit timer_cpu_notify(struct notifier_block *self,
1326 long cpu = (long)hcpu; 1348 long cpu = (long)hcpu;
1327 switch(action) { 1349 switch(action) {
1328 case CPU_UP_PREPARE: 1350 case CPU_UP_PREPARE:
1329 init_timers_cpu(cpu); 1351 if (init_timers_cpu(cpu) < 0)
1352 return NOTIFY_BAD;
1330 break; 1353 break;
1331#ifdef CONFIG_HOTPLUG_CPU 1354#ifdef CONFIG_HOTPLUG_CPU
1332 case CPU_DEAD: 1355 case CPU_DEAD: