x86: convert cpumask_of_cpu macro to allocated array
authorMike Travis <travis@sgi.com>
Sat, 5 Apr 2008 01:11:01 +0000 (18:11 -0700)
committerIngo Molnar <mingo@elte.hu>
Sat, 19 Apr 2008 17:44:59 +0000 (19:44 +0200)
  * Here is a simple patch to use an allocated array of cpumasks to
    represent cpumask_of_cpu() instead of constructing one on the stack.
    It's based on the Kconfig option "HAVE_CPUMASK_OF_CPU_MAP" which is
    currently only set for x86_64 SMP.  Otherwise the the existing
    cpumask_of_cpu() is used but has been changed to produce an lvalue
    so a pointer to it can be used.

Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/Kconfig
arch/x86/kernel/setup.c
include/linux/cpumask.h

index 2a59dbb28248b7da44c9695250e97bf68a05799c..7f30b754bfc3748e6cd07beb5b5d557711fb8d82 100644 (file)
@@ -117,6 +117,9 @@ config ARCH_HAS_CPU_RELAX
 config HAVE_SETUP_PER_CPU_AREA
        def_bool X86_64 || (X86_SMP && !X86_VOYAGER)
 
+config HAVE_CPUMASK_OF_CPU_MAP
+       def_bool X86_64_SMP
+
 config ARCH_HIBERNATION_POSSIBLE
        def_bool y
        depends on !SMP || !X86_VOYAGER
index ed157c90412e25a01076dd268133a8d4d86a9296..0d1f44ae6eea83b3ab32d17fe04a817227dd2acf 100644 (file)
@@ -54,6 +54,24 @@ static void __init setup_per_cpu_maps(void)
 #endif
 }
 
+#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
+cpumask_t *cpumask_of_cpu_map __read_mostly;
+EXPORT_SYMBOL(cpumask_of_cpu_map);
+
+/* requires nr_cpu_ids to be initialized */
+static void __init setup_cpumask_of_cpu(void)
+{
+       int i;
+
+       /* alloc_bootmem zeroes memory */
+       cpumask_of_cpu_map = alloc_bootmem_low(sizeof(cpumask_t) * nr_cpu_ids);
+       for (i = 0; i < nr_cpu_ids; i++)
+               cpu_set(i, cpumask_of_cpu_map[i]);
+}
+#else
+static inline void setup_cpumask_of_cpu(void) { }
+#endif
+
 #ifdef CONFIG_X86_32
 /*
  * Great future not-so-futuristic plan: make i386 and x86_64 do it
@@ -70,7 +88,7 @@ EXPORT_SYMBOL(__per_cpu_offset);
  */
 void __init setup_per_cpu_areas(void)
 {
-       int i;
+       int i, highest_cpu = 0;
        unsigned long size;
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -104,10 +122,18 @@ void __init setup_per_cpu_areas(void)
                __per_cpu_offset[i] = ptr - __per_cpu_start;
 #endif
                memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+
+               highest_cpu = i;
        }
 
+       nr_cpu_ids = highest_cpu + 1;
+       printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d\n", NR_CPUS, nr_cpu_ids);
+
        /* Setup percpu data maps */
        setup_per_cpu_maps();
+
+       /* Setup cpumask_of_cpu map */
+       setup_cpumask_of_cpu();
 }
 
 #endif
index 629102feaa663f05eb4b696682e49a24e8366ef8..259c8051155d9e34c783f9499b606ac780f8dd84 100644 (file)
@@ -222,8 +222,13 @@ int __next_cpu(int n, const cpumask_t *srcp);
 #define next_cpu(n, src)       ({ (void)(src); 1; })
 #endif
 
+#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
+extern cpumask_t *cpumask_of_cpu_map;
+#define cpumask_of_cpu(cpu)    (cpumask_of_cpu_map[cpu])
+
+#else
 #define cpumask_of_cpu(cpu)                                            \
-({                                                                     \
+(*({                                                                   \
        typeof(_unused_cpumask_arg_) m;                                 \
        if (sizeof(m) == sizeof(unsigned long)) {                       \
                m.bits[0] = 1UL<<(cpu);                                 \
@@ -231,8 +236,9 @@ int __next_cpu(int n, const cpumask_t *srcp);
                cpus_clear(m);                                          \
                cpu_set((cpu), m);                                      \
        }                                                               \
-       m;                                                              \
-})
+       &m;                                                             \
+}))
+#endif
 
 #define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS)