diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-08-19 23:49:44 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-16 10:52:03 -0400 |
commit | 1f3fcd4b1adc972d5c6a34cfed98931c46575b49 (patch) | |
tree | a79b6c656a09a8424863a0025d5b20e7264d6999 /init | |
parent | 3ddfda11861d305b02ed810b522dcf48b74ca808 (diff) |
add per_cpu_dyn_array support
allow dyn-array in per_cpu area, allocated dynamically.
usage:
| /* in .h */
| struct kernel_stat {
| struct cpu_usage_stat cpustat;
| unsigned int *irqs;
| };
|
| /* in .c */
| DEFINE_PER_CPU(struct kernel_stat, kstat);
|
| DEFINE_PER_CPU_DYN_ARRAY_ADDR(per_cpu__kstat_irqs, per_cpu__kstat.irqs, sizeof(unsigned int), nr_irqs, sizeof(unsigned long), NULL);
after setup_percpu()/per_cpu_alloc_dyn_array(), the dyn_array in
per_cpu area is ready to use.
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'init')
-rw-r--r-- | init/main.c | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/init/main.c b/init/main.c index 638d3a786412..416bca4f734f 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -391,17 +391,19 @@ EXPORT_SYMBOL(__per_cpu_offset); | |||
391 | 391 | ||
392 | static void __init setup_per_cpu_areas(void) | 392 | static void __init setup_per_cpu_areas(void) |
393 | { | 393 | { |
394 | unsigned long size, i; | 394 | unsigned long size, i, old_size; |
395 | char *ptr; | 395 | char *ptr; |
396 | unsigned long nr_possible_cpus = num_possible_cpus(); | 396 | unsigned long nr_possible_cpus = num_possible_cpus(); |
397 | 397 | ||
398 | /* Copy section for each CPU (we discard the original) */ | 398 | /* Copy section for each CPU (we discard the original) */ |
399 | size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE); | 399 | old_size = PERCPU_ENOUGH_ROOM; |
400 | size = ALIGN(old_size + per_cpu_dyn_array_size(), PAGE_SIZE); | ||
400 | ptr = alloc_bootmem_pages(size * nr_possible_cpus); | 401 | ptr = alloc_bootmem_pages(size * nr_possible_cpus); |
401 | 402 | ||
402 | for_each_possible_cpu(i) { | 403 | for_each_possible_cpu(i) { |
403 | __per_cpu_offset[i] = ptr - __per_cpu_start; | 404 | __per_cpu_offset[i] = ptr - __per_cpu_start; |
404 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); | 405 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); |
406 | per_cpu_alloc_dyn_array(i, ptr + old_size); | ||
405 | ptr += size; | 407 | ptr += size; |
406 | } | 408 | } |
407 | } | 409 | } |
@@ -559,6 +561,63 @@ void pre_alloc_dyn_array(void) | |||
559 | #endif | 561 | #endif |
560 | } | 562 | } |
561 | 563 | ||
564 | unsigned long per_cpu_dyn_array_size(void) | ||
565 | { | ||
566 | unsigned long total_size = 0; | ||
567 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
568 | unsigned long size; | ||
569 | struct dyn_array **daa; | ||
570 | |||
571 | for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) { | ||
572 | struct dyn_array *da = *daa; | ||
573 | |||
574 | size = da->size * (*da->nr); | ||
575 | print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name); | ||
576 | printk(KERN_CONT "size:%#lx nr:%d align:%#lx\n", | ||
577 | da->size, *da->nr, da->align); | ||
578 | total_size += roundup(size, da->align); | ||
579 | } | ||
580 | if (total_size) | ||
581 | printk(KERN_DEBUG "per_cpu_dyna_array total_size: %#lx\n", | ||
582 | total_size); | ||
583 | #endif | ||
584 | return total_size; | ||
585 | } | ||
586 | |||
587 | void per_cpu_alloc_dyn_array(int cpu, char *ptr) | ||
588 | { | ||
589 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
590 | unsigned long size, phys; | ||
591 | struct dyn_array **daa; | ||
592 | unsigned long addr; | ||
593 | void **array; | ||
594 | |||
595 | phys = virt_to_phys(ptr); | ||
596 | |||
597 | for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) { | ||
598 | struct dyn_array *da = *daa; | ||
599 | |||
600 | size = da->size * (*da->nr); | ||
601 | print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name); | ||
602 | printk(KERN_CONT "size:%#lx nr:%d align:%#lx", | ||
603 | da->size, *da->nr, da->align); | ||
604 | |||
605 | phys = roundup(phys, da->align); | ||
606 | addr = (unsigned long)da->name; | ||
607 | addr += per_cpu_offset(cpu); | ||
608 | array = (void **)addr; | ||
609 | *array = phys_to_virt(phys); | ||
610 | *da->name = *array; /* so init_work could use it directly */ | ||
611 | printk(KERN_CONT " %p ==> [%#lx - %#lx]\n", array, phys, phys + size); | ||
612 | phys += size; | ||
613 | |||
614 | if (da->init_work) { | ||
615 | da->init_work(da); | ||
616 | } | ||
617 | } | ||
618 | #endif | ||
619 | } | ||
620 | |||
562 | asmlinkage void __init start_kernel(void) | 621 | asmlinkage void __init start_kernel(void) |
563 | { | 622 | { |
564 | char * command_line; | 623 | char * command_line; |