Only allocate per-cpu copies for possible CPUs

Only allocate per-cpu copies for possible CPUs

Post by Rusty Russel » Fri, 13 Sep 2002 16:30:06

Not quite as neat as I would like, but it means that per-cpu vars are
still usable on the boot CPU early, and usable on the other cpus by
the time they are called online.

The problem is that some people want to use per-cpu vars before we
have probed for cpus, so we don't know what CPUs are possible, hence
this "alloc the boot cpu using bootmem and the other cpus using
kmalloc" approach.

This is a precursor to pushing "change all [NR_CPUS] arrays to per-cpu
vars" (which then implies that the per-cpu area pointer, not the cpu
number, becomes the primary object from which the other is derived.


Name: per-cpu only for possible CPUs
Author: Rusty Russell
Status: Tested on 2.5.34 2-way i386

D: This allocates per-cpu areas only for those CPUs which may actually
D: exist, before each one comes online.

diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.34/init/main.c working-2.5.34-percpu_possible/init/main.c
--- linux-2.5.34/init/main.c    Tue Sep 10 09:11:21 2002

 #define smp_init()     do { } while (0)

-static inline void setup_per_cpu_areas(void) { }
+static inline void setup_per_cpu_area(unsigned int cpu) { }
 static inline void smp_prepare_cpus(unsigned int maxcpus) { }


+/* Created by linker magic */
+extern char __per_cpu_start[], __per_cpu_end[];
 unsigned long __per_cpu_offset[NR_CPUS];

-static void __init setup_per_cpu_areas(void)
+/* Sets up per-cpu area for boot CPU. */
+static void __init setup_per_cpu_area(unsigned int cpu)
-       unsigned long size, i;
+       unsigned long size;
        char *ptr;
-       /* Created by linker magic */
-       extern char __per_cpu_start[], __per_cpu_end[];

        /* Copy section for each CPU (we discard the original) */
        size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
        if (!size)

-       ptr = alloc_bootmem(size * NR_CPUS);
+       /* First CPU happens really early... */
+       if (cpu == smp_processor_id())
+               ptr = alloc_bootmem(size);
+       else
+               ptr = kmalloc(size, GFP_ATOMIC);

-       for (i = 0; i < NR_CPUS; i++, ptr += size) {
-               __per_cpu_offset[i] = ptr - __per_cpu_start;
-               memcpy(ptr, __per_cpu_start, size);
-       }
+       __per_cpu_offset[cpu] = ptr - __per_cpu_start;
+       memcpy(ptr, __per_cpu_start, size);
 #endif /* !__GENERIC_PER_CPU */

        unsigned int i;

-       /* FIXME: This should be done in userspace --RR */
+       for (i = 0; i < NR_CPUS; i++) {
+               if (cpu_possible(i)) {
+                       if (i != smp_processor_id())
+                               setup_per_cpu_area(i);
+               } else {
+                       /* Force a NULL deref on use */
+                       __per_cpu_offset[i] = (char *)0 - __per_cpu_start;
+               }
+       }
        for (i = 0; i < NR_CPUS; i++) {
                if (num_online_cpus() >= max_cpus)

-       setup_per_cpu_areas();
+       setup_per_cpu_area(smp_processor_id());
        printk("Kernel command line: %s\n", saved_command_line);

  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at
Please read the FAQ at


1. Sun license manager...1%cpu...1%cpu...50%cpu50%cpu50%cpu....

    Is there a patch to fix this problem: Once and a while, the license manager
lmgrd.ste will peg a CPU (2 in this box) with activity.  It still manages the licenses
and can still receive lm messages (reread, shutdown).  This seems to happen, I have
noticed, if I ^C a compiler which is starting up.  When it goes down and I invoke it
again, it gives those annoying "socket in use" messages.  It eventually comes
completely up, but is not services licenses for those 5 minutes it complains
about sockets.  Any workarounds?


    Real Time Enterprises                               | Scott MacKay

    Pittsford,NY 14534                                  | Real Time Enterprises
- Electronic Document Imaging - System Integration -    | (716) 383-1290
        - Software Development-                         | Postmaster

2. Fvwm95 Hosts

3. New per-cpu patch v2.5.1

4. Zip Disk

5. Make diskstats per-cpu using kmalloc_percpu

6. Two IP addresses

7. per-cpu areas

8. Samba and dial on demand ... again

9. User per-cpu data in softirq.c

10. (2/3) per-cpu interrupt stacks for x86

11. Per-cpu variable in mm/slab.c

12. __crc_page_states__per_cpu not in per-cpu section

13. cpufreq: per-CPU initialization