aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Travis <travis@sgi.com>2008-07-24 21:21:29 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-26 10:40:32 -0400
commitb8d317d10cca76cabe6b03ebfeb23cc99118b731 (patch)
treea997d21960099095822ffbfe8be4d3f6176f33a9
parent024e8ac04453b3525448c31ef39848cf675ba6db (diff)
cpumask: make cpumask_of_cpu_map generic
If an arch doesn't define cpumask_of_cpu_map, create a generic statically-initialized one for them. This allows removal of the buggy cpumask_of_cpu() macro (&cpumask_of_cpu() gives address of out-of-scope var). An arch with NR_CPUS of 4096 probably wants to allocate this itself based on the actual number of CPUs, since otherwise they're using 2MB of rodata (1024 cpus means 128k). That's what CONFIG_HAVE_CPUMASK_OF_CPU_MAP is for (only x86/64 does so at the moment). In future as we support more CPUs, we'll need to resort to a get_cpu_map()/put_cpu_map() allocation scheme. Signed-off-by: Mike Travis <travis@sgi.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Jack Steiner <steiner@sgi.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--include/linux/cpumask.h41
-rw-r--r--kernel/cpu.c109
2 files changed, 112 insertions, 38 deletions
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 1b5c98e7fef..8fa3b6d4a32 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -62,15 +62,7 @@
62 * int next_cpu_nr(cpu, mask) Next cpu past 'cpu', or nr_cpu_ids 62 * int next_cpu_nr(cpu, mask) Next cpu past 'cpu', or nr_cpu_ids
63 * 63 *
64 * cpumask_t cpumask_of_cpu(cpu) Return cpumask with bit 'cpu' set 64 * cpumask_t cpumask_of_cpu(cpu) Return cpumask with bit 'cpu' set
65 *ifdef CONFIG_HAS_CPUMASK_OF_CPU 65 * (can be used as an lvalue)
66 * cpumask_of_cpu_ptr_declare(v) Declares cpumask_t *v
67 * cpumask_of_cpu_ptr_next(v, cpu) Sets v = &cpumask_of_cpu_map[cpu]
68 * cpumask_of_cpu_ptr(v, cpu) Combines above two operations
69 *else
70 * cpumask_of_cpu_ptr_declare(v) Declares cpumask_t _v and *v = &_v
71 * cpumask_of_cpu_ptr_next(v, cpu) Sets _v = cpumask_of_cpu(cpu)
72 * cpumask_of_cpu_ptr(v, cpu) Combines above two operations
73 *endif
74 * CPU_MASK_ALL Initializer - all bits set 66 * CPU_MASK_ALL Initializer - all bits set
75 * CPU_MASK_NONE Initializer - no bits set 67 * CPU_MASK_NONE Initializer - no bits set
76 * unsigned long *cpus_addr(mask) Array of unsigned long's in mask 68 * unsigned long *cpus_addr(mask) Array of unsigned long's in mask
@@ -274,36 +266,9 @@ static inline void __cpus_shift_left(cpumask_t *dstp,
274} 266}
275 267
276 268
277#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP 269/* cpumask_of_cpu_map[] is in kernel/cpu.c */
278extern cpumask_t *cpumask_of_cpu_map; 270extern const cpumask_t *cpumask_of_cpu_map;
279#define cpumask_of_cpu(cpu) (cpumask_of_cpu_map[cpu]) 271#define cpumask_of_cpu(cpu) (cpumask_of_cpu_map[cpu])
280#define cpumask_of_cpu_ptr(v, cpu) \
281 const cpumask_t *v = &cpumask_of_cpu(cpu)
282#define cpumask_of_cpu_ptr_declare(v) \
283 const cpumask_t *v
284#define cpumask_of_cpu_ptr_next(v, cpu) \
285 v = &cpumask_of_cpu(cpu)
286#else
287#define cpumask_of_cpu(cpu) \
288({ \
289 typeof(_unused_cpumask_arg_) m; \
290 if (sizeof(m) == sizeof(unsigned long)) { \
291 m.bits[0] = 1UL<<(cpu); \
292 } else { \
293 cpus_clear(m); \
294 cpu_set((cpu), m); \
295 } \
296 m; \
297})
298#define cpumask_of_cpu_ptr(v, cpu) \
299 cpumask_t _##v = cpumask_of_cpu(cpu); \
300 const cpumask_t *v = &_##v
301#define cpumask_of_cpu_ptr_declare(v) \
302 cpumask_t _##v; \
303 const cpumask_t *v = &_##v
304#define cpumask_of_cpu_ptr_next(v, cpu) \
305 _##v = cpumask_of_cpu(cpu)
306#endif
307 272
308#define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS) 273#define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS)
309 274
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 10ba5f1004a..fe31ff3d380 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -461,3 +461,112 @@ out:
461#endif /* CONFIG_PM_SLEEP_SMP */ 461#endif /* CONFIG_PM_SLEEP_SMP */
462 462
463#endif /* CONFIG_SMP */ 463#endif /* CONFIG_SMP */
464
465#ifndef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
466/* 64 bits of zeros, for initializers. */
467#if BITS_PER_LONG == 32
468#define Z64 0, 0
469#else
470#define Z64 0
471#endif
472
473/* Initializer macros. */
474#define CMI0(n) { .bits = { 1UL << (n) } }
475#define CMI(n, ...) { .bits = { __VA_ARGS__, 1UL << ((n) % BITS_PER_LONG) } }
476
477#define CMI8(n, ...) \
478 CMI((n), __VA_ARGS__), CMI((n)+1, __VA_ARGS__), \
479 CMI((n)+2, __VA_ARGS__), CMI((n)+3, __VA_ARGS__), \
480 CMI((n)+4, __VA_ARGS__), CMI((n)+5, __VA_ARGS__), \
481 CMI((n)+6, __VA_ARGS__), CMI((n)+7, __VA_ARGS__)
482
483#if BITS_PER_LONG == 32
484#define CMI64(n, ...) \
485 CMI8((n), __VA_ARGS__), CMI8((n)+8, __VA_ARGS__), \
486 CMI8((n)+16, __VA_ARGS__), CMI8((n)+24, __VA_ARGS__), \
487 CMI8((n)+32, 0, __VA_ARGS__), CMI8((n)+40, 0, __VA_ARGS__), \
488 CMI8((n)+48, 0, __VA_ARGS__), CMI8((n)+56, 0, __VA_ARGS__)
489#else
490#define CMI64(n, ...) \
491 CMI8((n), __VA_ARGS__), CMI8((n)+8, __VA_ARGS__), \
492 CMI8((n)+16, __VA_ARGS__), CMI8((n)+24, __VA_ARGS__), \
493 CMI8((n)+32, __VA_ARGS__), CMI8((n)+40, __VA_ARGS__), \
494 CMI8((n)+48, __VA_ARGS__), CMI8((n)+56, __VA_ARGS__)
495#endif
496
497#define CMI256(n, ...) \
498 CMI64((n), __VA_ARGS__), CMI64((n)+64, Z64, __VA_ARGS__), \
499 CMI64((n)+128, Z64, Z64, __VA_ARGS__), \
500 CMI64((n)+192, Z64, Z64, Z64, __VA_ARGS__)
501#define Z256 Z64, Z64, Z64, Z64
502
503#define CMI1024(n, ...) \
504 CMI256((n), __VA_ARGS__), \
505 CMI256((n)+256, Z256, __VA_ARGS__), \
506 CMI256((n)+512, Z256, Z256, __VA_ARGS__), \
507 CMI256((n)+768, Z256, Z256, Z256, __VA_ARGS__)
508#define Z1024 Z256, Z256, Z256, Z256
509
510/* We want this statically initialized, just to be safe. We try not
511 * to waste too much space, either. */
512static const cpumask_t cpumask_map[] = {
513 CMI0(0), CMI0(1), CMI0(2), CMI0(3),
514#if NR_CPUS > 4
515 CMI0(4), CMI0(5), CMI0(6), CMI0(7),
516#endif
517#if NR_CPUS > 8
518 CMI0(8), CMI0(9), CMI0(10), CMI0(11),
519 CMI0(12), CMI0(13), CMI0(14), CMI0(15),
520#endif
521#if NR_CPUS > 16
522 CMI0(16), CMI0(17), CMI0(18), CMI0(19),
523 CMI0(20), CMI0(21), CMI0(22), CMI0(23),
524 CMI0(24), CMI0(25), CMI0(26), CMI0(27),
525 CMI0(28), CMI0(29), CMI0(30), CMI0(31),
526#endif
527#if NR_CPUS > 32
528#if BITS_PER_LONG == 32
529 CMI(32, 0), CMI(33, 0), CMI(34, 0), CMI(35, 0),
530 CMI(36, 0), CMI(37, 0), CMI(38, 0), CMI(39, 0),
531 CMI(40, 0), CMI(41, 0), CMI(42, 0), CMI(43, 0),
532 CMI(44, 0), CMI(45, 0), CMI(46, 0), CMI(47, 0),
533 CMI(48, 0), CMI(49, 0), CMI(50, 0), CMI(51, 0),
534 CMI(52, 0), CMI(53, 0), CMI(54, 0), CMI(55, 0),
535 CMI(56, 0), CMI(57, 0), CMI(58, 0), CMI(59, 0),
536 CMI(60, 0), CMI(61, 0), CMI(62, 0), CMI(63, 0),
537#else
538 CMI0(32), CMI0(33), CMI0(34), CMI0(35),
539 CMI0(36), CMI0(37), CMI0(38), CMI0(39),
540 CMI0(40), CMI0(41), CMI0(42), CMI0(43),
541 CMI0(44), CMI0(45), CMI0(46), CMI0(47),
542 CMI0(48), CMI0(49), CMI0(50), CMI0(51),
543 CMI0(52), CMI0(53), CMI0(54), CMI0(55),
544 CMI0(56), CMI0(57), CMI0(58), CMI0(59),
545 CMI0(60), CMI0(61), CMI0(62), CMI0(63),
546#endif /* BITS_PER_LONG == 64 */
547#endif
548#if NR_CPUS > 64
549 CMI64(64, Z64),
550#endif
551#if NR_CPUS > 128
552 CMI64(128, Z64, Z64), CMI64(192, Z64, Z64, Z64),
553#endif
554#if NR_CPUS > 256
555 CMI256(256, Z256),
556#endif
557#if NR_CPUS > 512
558 CMI256(512, Z256, Z256), CMI256(768, Z256, Z256, Z256),
559#endif
560#if NR_CPUS > 1024
561 CMI1024(1024, Z1024),
562#endif
563#if NR_CPUS > 2048
564 CMI1024(2048, Z1024, Z1024), CMI1024(3072, Z1024, Z1024, Z1024),
565#endif
566#if NR_CPUS > 4096
567#error NR_CPUS too big. Fix initializers or set CONFIG_HAVE_CPUMASK_OF_CPU_MAP
568#endif
569};
570
571const cpumask_t *cpumask_of_cpu_map = cpumask_map;
572#endif /* !CONFIG_HAVE_CPUMASK_OF_CPU_MAP */