mask v2 - Second version of mask, cpumask and nodemask consolidation
Subsystems (12)
cover mask v2 - Second version of mask, cpumask and nodemask consolidation
Paul Jackson [email protected] 1 April 2004 Masks, Cpumasks and Nodemasks
This set of 23 patches, to be sent as followups to this message momentarily, provides a common 'mask' ADT from which both cpumask_t and nodemask_t are defined. This set of patches incorporates Matthew Dobson's [PATCH]_nodemask_t patch series.
This is the second version of this mask patch set. The first version was posted on March 29, 2004. This version builds and boots on arch=ia64 using the sn2_defconfig with NR_CPUS=512. As with the first mask patch set, this one is against 2.6.4.
A primary goal of this patch set was to simplify the support for cpumask_t and nodemask_t, making them easier to use, and reducing code duplication.
Several flavors of mask have been reduced to one, with some local special handling to optimize for normal size systems of less than 32 CPUs.
The other primary goal of this patch set, in particular of Matthew's nodemask_t patches, which are included here, was to provide a standard nodemask_t and operations. This is done to avoid "open" coding of node masks using ad hoc code.
================ Description of Risks ================
This patch set makes changes in mask handling code in several architectures. We could have broken something.
This patch set removes several more optimized variants of mask, which were targeted for optimum performance on various architectures, and replaces that with essentially a single variant. Preliminary analysis on the one architecture I cared most about shows no noticeable difference in the quality of the code generated for mask operations, but other architectures or more demanding uses may require further optimization work.
This patch set might have dependencies on specific gcc or toolchain versions. Portions have worked with both gcc 2.95.3 and 3.3.2 inside a user level scaffolding on i386. Kernels have been built and booted on ia64 using gcc 3.2.3 and built on i386 using gcc 3.3.2. But non-trivial use is made of gcc extensions, so certain archs or toolchains might not build, or might not produce sufficiently optimal code, or might not even work.
This patch set changes the semantics of cpumasks slightly. If all mask operations are performed with correct parameters, and no bits are intentionally set outside the range of bits covered by such a mask (typically this means outside the range [0 ... NR_CPUS-1] for cpumask_t), then there should be no noticable difference. Code that (improperly) sets bits outside that valid range may notice differences in when such bits affect the results of other mask operations.
Patches 19 through 22 (see list of patches, below) in particular attempt to "cleanup" some cpumask manipulation code in various sparc and intel arch's. These patches are not essential - if they get in the way of other work, or are too much distraction, or break something, any of them can be dropped. At a minimum, they require review and approval from the affected arch's.
Similarly, Patches 14 through 18 attempt to "cleanup" some nodemask manipulations in several arch's. Once again, they aren't tested, need review, could break something, or could intrude on other work.
================ Original mask writeup ================
The following writeup describing masks, from the first version posted March 29, is still (with minor edits) useful, so reposted and updated here:
The following sequence of 23 patches replaces cpumask_t and Matthew Dobson's recent nodemask_t with ones based on a new mask ADT.
The following patches apply against a 2.6.4 vanilla kernel, and result in nodemask code that is (with a couple of details) the same as Matthew's.
All the various include/asm-*/*mask.h files are gone. The const macros are gone. The promote and coerce macros are replaced with a single mask_addr() macro, that simply returns the address of the first unsigned long in the mask, to do with as you will.
There are now only 3 mask header files:
include/linux/mask.h - the underlying ADT include/linux/cpumask.h - cpumasks, implemented using mask.h include/linux/nodemask.h - nodemasks, implemented using mask.h
Excluding block comments, the old cpumask code, with Matthew's nodemask patch, consumed (in files matching include/*/*mask*.h):
34 files, 683 lines of code
This new cpumask and nodemask code, and its common mask ADT base, consumes a comparable:
3 files, 418 lines of code
If you want to write code using the cpumask or nodemask API, then everything you need is easily available in the cpumask.h or nodemask.h header file, respectively.
A few more mask macros have been added, to make it easier to code mask manipulations correctly and easily. They provide xor, andnot, intersects and subset operators.
A few places in the kernel that use cpumasks were recoded to make better use of these cpumask macros.
The *_complement macros were recoded to take separate source and dest arguments, following a suggestion of Bill Irwin.
It should be easy to add other mask-based types. One candidate for this conversion would be physid_mask. Just make a copy of cpumask.h (or nodemask.h) and do a few global substitutions in the editor, and you'll be close.
I believe that this version of masks is easier to understand and use, while providing the same performance as before. The fairly rich extensions of gcc for compile time macros and optimizations allow for writing code that produces optimum results on various architectures and system sizes without the complexity of multiple nested include files and ifdefs.
Bug fixes include:
1) *_complement macros don't leave unused high bits set
2) MASK_ALL for sizes > 1 word, but not exact word multiple, doesn't have unused high bits set
3) Explicit, documented semantics for handling these unused high bits.
4) A few missing const attributes in bitmap & bitops added.
5) The (Hamming) cpumask weight macros were using the bitops hweight*() macros, which don't mask high unused bits - fixed to use the bitmap weight macro which does this masking.
Do to the rather limited use so far of these cpumask and nodemask macros, I am not aware of anything that these bugs would actually break in current mm or linus kernels.
Also, the assymetry that nodemasks had with cpumasks, whereby the cpumasks had include/asm-<arch> specific redirecting headers for every arch, but nodemasks didn't, has been fixed. Now neither one has arch-specific redirect headers. They aren't needed in my view. Arch specific code belongs in the underlying bitops.h header files, and the individual mask macros can be elaborated as need be to take advantage of such.
================ Patch Details ================
Here's what each patch does:
Patch_1_of_23 - Document bitmap.c bit model.
Document the bitmap bit model, including handling of unused bits, and operation preconditions and postconditions.
Patch_2_of_23 - Dont generate nonzero unused bits in bitmap
Tighten up bitmap so it does not generate nonzero bits in the unused tail if it is not given any on input.
Patch_3_of_23 - New bitmap operators and two op complement
Add intersects, subset, xor and andnot operators. Change bitmap_complement to take two operands.
Patch_4_of_23 - two missing 'const' qualifiers in bitops/bitmap
Add a couple of missing 'const' qualifiers on bitops test_bit and bitmap_equal args.
Patch_5_of_23 - New mask ADT
Adds new include/linux/mask.h header file ==> See this mask.h header for more extensive mask documentation <==
Patch_6_of_23 - Rework cpumasks to use new mask ADT
Removes many old include/asm-<arch> and asm-generic cpumask files Add intersects, subset, xor and andnot operators. Provides temporary emulators for obsolete const, promote, coerce Presents entire cpumask API clearly in single cpumask.h file
Patch_7_of_23 - Remove/recode obsolete cpumask macros from arch i386
Remove by recoding all uses of the obsolete cpumask const, coerce and promote macros.
Patch_8_of_23 - Remove/recode obsolete cpumask macros from arch ppc64
Remove by recoding all uses of the obsolete cpumask const, coerce and promote macros.
Patch_9_of_23 - Remove/recode obsolete cpumask macros from arch x86_64
Remove by recoding all uses of the obsolete cpumask const, coerce and promote macros.
Patch_10_of_23 - Remove obsolete cpumask emulation from cpumask.h
Now that the emulation of the obsolete cpumask macros is no longer needed, remove it from cpumask.h
Patch_11_of_23 - Add new nodemasks.h file.
Provide a nodemasks_t type, using the mask.h ADT.
Patch_12_of_23 - the mmzone.h changes from Matthew's Patch [1/7]
Just the mmzone.h changes taken from this patch: removing extistant definition of node_online_map and helper functions, added a #include <nodemask.h>.
Patch_13_of_23 - Matthew Dobson's [PATCH] nodemask_t core changes [2/7]
nodemask_t-02-core.patch - Changes to arch-independent code. Surprisingly few references to numnodes, open-coded node loops, etc. in generic code. Most important result of this patch is that no generic code assumes anything about node numbering. This allows individual arches to use sparse numbering if they care to.
Patch_14_of_23 - Matthew Dobson's [PATCH]_nodemask_t_i386_changes_[3_7]
Changes to i386 specific code. As with most arch changes, it involves close-coding loops (ie: for_each_online_node(nid) rather than for(nid=0;nid<numnodes;nid++)) and replacing the use of numnodes with num_online_nodes() and node_set_online(nid).
Patch_15_of_23 - Matthew Dobson's [PATCH]_nodemask_t_pp64_changes_[4_7]
Changes to ppc64 specific code. Untested.
Code review & testing requested.
Patch_16_of_23 - Matthew Dobson's [PATCH]_nodemask_t_x86_64_changes_[5_7]
Changes to x86_64 specific code.
Untested. Code review & testing requested.
Patch_17_of_23 - Matthew Dobson's [PATCH]_nodemask_t_ia64_changes_[6_7]
Changes to ia64 specific code.
Patch_18_of_23 - Matthew Dobson's [PATCH]_nodemask_t_other_arch_changes_[7_7]
Changes to other arch-specific code (alpha, arm, mips, sparc64 & sh). Untested. Code review & testing requested.
Patch_19_of_23 - Simplify some sparc64 cpumask loop code
Make use of for_each_cpu_mask() macro to simplify and optimize a couple of sparc64 per-CPU loops. This code change has _not_ been tested or reviewed. Feedback welcome. There is non-trivial risk that I still don't understand the logic here.
Patch_20_of_23 - Optimize i386 cpumask macro usage.
Optimize a bit of cpumask code for asm-i386/mach-es7000 Code untested, unreviewed. Feedback welcome.
Patch_21_of_23 - Convert physids_complement() to really use both args
Provide for specifying distinct source and dest args to the physids_complement(). No one actually uses this macro yet. The physid_mask type would be a good candidate to convert to using this new mask ADT as a base.
Patch_22_of_23 - Remove cpumask hack from asm-x86_64/topology.h
This file had the cpumask cpu_online_map as type unsigned long, instead of type cpumask_t, for no good reason that I could see. So I changed it. Everywhere else, cpu_online_map is already of type cpumask_t.
Patch_23_of_23 - Cpumask code clarification in kernel/sched.c
Clarify and slightly optimize set_cpus_allowed() cpumask check
================ Changes in 2nd version mask patches ================
I have incorporated the following changes, since posting the first "mask ADT" set of 22 patches, on March 29, thanks primarily to the work of Matthew and Bill Irwin. I have included Matthew's comments for the nodemask changes that he provided, ver batim, without attribution. See his earlier lkml posts for the full detail.
1. The brackets {{ ... }} on MASK ALL and NONE should have been { { ... } }, not ({ ... }). I needed to add a space separator, not change curlies to parens.
2. Renamed cpus_raw to cpus_addr, the name that function has had all along.
3. Dropped patch 8/22 to arch/i386/kernel/smp.c and arch/x86_64/kernel/smp.c, to avoid colliding with parallel work by Hari.
4. Changed mask api for 9 operators:
and or xor andnot equal intersects subset empty clearall
to take a final argument of the number of bits, which it passes through to the corresponding bitmap_* operator. Previously, these operators had used the size in bytes of the mask to compute the number of bits. Less code, more accurate, to just pass through the actual bit count.
5. Incorporated various formatting and related changed from Matthew, including numerous missing parentheses in preprocessor expansions.
6. Matthew removed a few gratuitous differences between the choice of macros available for cpumasks versus nodemasks .
7. Documented the semantics of the bit model supported by bitmap and bitops.
8. Made a distinct patch out of the change, with comment, to lib/bitmap.c to honor the stronger postcondition: there will be no one bits in the unused tail in the results of operations if no such one bits are set in input masks.
9. ppc64 changes from Matthew's nodemask_t Patch 4/7 [13/22]
Here's the updated version of the PPC64 patch. The differences are the complete removal of all references to max_domain in parse_numa_properties() in arch/ppc64/mm/numa.c. Upon closer inspection, this variable and associated code isn't needed. I also removed the
for(i = 0; i <= max_domain; i++) node_set_online(i);
loop because the nodes are onlined as we loop over the CPUs that are in them.
10 x86_64 changes from Matthew's nodemask_t Patch 5/7 [14/22]
This one has been updated as well. I chose a slightly different fix for the nodes_complement() bug I introduced. I just inserted:
for_each_node(i) {
if (node_online(i))
continue;
...}
rather than doing any nodes_complement() at all. Either solution will work
11 ia64 changes from Matthew's nodemask_t Patch 6/7 [15/22]
Yet another updated patch. Changes are very small, but I've attatched the whole patch, rather than an incremental diff. In include/asm-ia64/sn/sn2/sn_private.h, we can safely drop the externs of replicate_kernel_text() & setup_replication_mask() as they are unused on ia64.
12 asm-ia64/sn/sn2
Removed unused replicate_kernel_text(), setup_replication_mask() declarations
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 1/23 mask v2 - Document bitmap.c bit model
Patch_1_of_23 - Document bitmap.c bit model.
Document the bitmap bit model, including handling of unused bits, and operation preconditions and postconditions.
Diffstat Patch_1_of_23:
bitmap.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+)
===================================================================
lib/bitmap.c +38 -0
@@ -12,6 +12,44 @@#include <asm/bitops.h> #include <asm/uaccess.h> +/* +* The bitmap bit model: +* +* The operations in this lib/bitmap.c, and the associated +* files include/linux/bitmap.h, include/linux/bitops.h, + * and include/asm-*/bitops.h, and in the *_BITMAP macros in + * include/linux/types.h, support a model of a set of bits, in + * positions 0 .. nbits-1, for some nbits size between 1 and some + * modest size. There is no specific limit on the size, but the + * internal representation, as an array of unsigned longs, would + * not be efficient for very large or sparse sets. + * + * If the number of valid bits in a particular bitmap is not + * an exact multiple of the number of bits in an unsigned long + * (BITS_PER_LONG), then there will be some unused bits, in a + * so called "tail", that is physically present in the internal + * representation, but will appear as if always zero to callers. + * + * To a first approximation, the "tail" bits are don't care bits. + * That is, regardless of their internal state, zero (0) or one + * (1), any of these functions will behave as if they were zero. + * In particular, all the bitmap functions returning a Boolean + * (e.g. bitmap_empty) or scalar (e.g. bitmap_weight) value are + * implemented so as to filter out or avoid being affected by + * possible one bits in the tail. + * + * Bitmaps are declared using the DECLARE_BITMAP() macro in + * include/linux/types.h. Subsequent operations on a bitmap that + * take a bit position, such as set_bit(), must only be provided + * positions between 0 and the bitmap size, as first provided + * in the DECLARE_BITMAP() invocation. Bitmap operations, such + * as bitmap_empty(), that take an argument specifying how many + * bits are in the bitmap, must be provided the same number as + * first provided to DECLARE_BITMAP(). Bitmap operations such as + *bitmap_or () that take two bitmaps as input must be passed two + * bitmaps of the same size. + */ + #define MAX_BITMAP_BITS 512U /* for ia64 NR_CPUS maximum */ int bitmap_empty(const unsigned long *bitmap, int bits)
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 2/23 mask v2 - Tighten unused bitmap bit handling
In reply to Paul JacksonPatch_2_of_23 - Dont generate nonzero unused bits in bitmap
Tighten up bitmap so it does not generate nonzero bits in the unused tail if it is not given any on input.
Diffstat Patch_2_of_23:
bitmap.c | 18 ++++++++++++++---- 1 files changed, 14 insertions(+), 4 deletions(-)
===================================================================
lib/bitmap.c +14 -4
@@ -38,6 +38,15 @@* implemented so as to filter out or avoid being affected by * possible one bits in the tail. * +* These operations actually provide a slightly stronger guarantee. +* If all input masks to a given operation have only zero bits in +* their tail, then any output masks from such an operation will +* also have only zero bits in the tail. These bitmap operations +* themselves don't require that input bitmap arguments to bitmap +* operations have zero tails; but these operations will not +* generate any ones in tails, if not provided such. This enables +* certain efficiencies in users of bitmaps. +* * Bitmaps are declared using the DECLARE_BITMAP() macro in * include/linux/types.h. Subsequent operations on a bitmap that * take a bit position, such as set_bit(), must only be provided
@@ -101,11 +110,12 @@void bitmap_complement (unsigned long *bitmap,int bits) { -int k; -int nr =BITS_TO_LONGS (bits); - -for (k =0 ; k < nr; ++k) +int k, lim = bits/BITS_PER_LONG ; +for (k =0 ; k < lim; ++k) bitmap[k] = ~bitmap[k]; + +if (bits %BITS_PER_LONG ) + bitmap[k] = ~bitmap[k] & ((1UL << (bits %BITS_PER_LONG )) -1 ); }EXPORT_SYMBOL (bitmap_complement);
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 3/23 mask v2 - New bitmap operators
In reply to Paul JacksonPatch_3_of_23 - New bitmap operators and two op complement
Add intersects, subset, xor and andnot operators. Change bitmap_complement to take two operands.
Diffstat Patch_3_of_23:
include/asm-generic/cpumask_array.h | 2 - include/asm-i386/mpspec.h | 2 - include/asm-x86_64/mpspec.h | 2 - include/linux/bitmap.h | 12 ++++++- lib/bitmap.c | 60 ++++++++++++++++++++++++++++++++++-- 5 files changed, 70 insertions(+), 8 deletions(-)
===================================================================
include/asm-generic/cpumask_array.h +1 -1
@@ -17,7 +17,7 @@#define cpus_and (dst,src1,src2) bitmap_and((dst).mask,(src1).mask, (src2).mask, NR_CPUS)#define cpus_or (dst,src1,src2) bitmap_or((dst).mask, (src1).mask, (src2).mask, NR_CPUS)#define cpus_clear (map) bitmap_clear((map).mask, NR_CPUS) -#define cpus_complement (map) bitmap_complement((map).mask, NR_CPUS) +#define cpus_complement (map) bitmap_complement((map).mask, (map).mask, NR_CPUS)#define cpus_equal (map1, map2) bitmap_equal((map1).mask, (map2).mask, NR_CPUS)#define cpus_empty (map) bitmap_empty(map.mask, NR_CPUS)#define cpus_addr (map) ((map).mask)
===================================================================
include/asm-i386/mpspec.h +1 -1
@@ -60,7 +60,7 @@#define physids_and (dst, src1, src2) bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)#define physids_or (dst, src1, src2) bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)#define physids_clear (map) bitmap_clear((map).mask, MAX_APICS) -#define physids_complement (map) bitmap_complement((map).mask, MAX_APICS) +#define physids_complement (map) bitmap_complement((map).mask, (map).mask, MAX_APICS)#define physids_empty (map) bitmap_empty((map).mask, MAX_APICS)#define physids_equal (map1, map2) bitmap_equal((map1).mask, (map2).mask, MAX_APICS)#define physids_weight (map) bitmap_weight((map).mask, MAX_APICS)
===================================================================
include/asm-x86_64/mpspec.h +1 -1
@@ -214,7 +214,7 @@#define physids_and (dst, src1, src2) bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)#define physids_or (dst, src1, src2) bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)#define physids_clear (map) bitmap_clear((map).mask, MAX_APICS) -#define physids_complement (map) bitmap_complement((map).mask, MAX_APICS) +#define physids_complement (map) bitmap_complement((map).mask, (map).mask, MAX_APICS)#define physids_empty (map) bitmap_empty((map).mask, MAX_APICS)#define physids_equal (map1, map2) bitmap_equal((map1).mask, (map2).mask, MAX_APICS)#define physids_weight (map) bitmap_weight((map).mask, MAX_APICS)
===================================================================
include/linux/bitmap.h +10 -2
@@ -13,8 +13,8 @@int bitmap_empty (const unsigned long *bitmap,int bits);int bitmap_full (const unsigned long *bitmap,int bits);int bitmap_equal (const unsigned long *bitmap1, -unsigned long *bitmap2,int bits); -void bitmap_complement (unsigned long *bitmap,int bits); +const unsigned long *bitmap2,int bits); +void bitmap_complement (unsigned long *dst,const unsigned long *src,int bits);static inline void bitmap_clear (unsigned long *bitmap,int bits) {
@@ -40,6 +40,14 @@ const unsigned long *bitmap2, int bits);void bitmap_or (unsigned long *dst,const unsigned long *bitmap1,const unsigned long *bitmap2,int bits); +void bitmap_xor (unsigned long *dst,const unsigned long *bitmap1, +const unsigned long *bitmap2,int bits); +void bitmap_andnot (unsigned long *dst,const unsigned long *bitmap1, +const unsigned long *bitmap2,int bits); +int bitmap_intersects (const unsigned long *bitmap1, +const unsigned long *bitmap2,int bits); +int bitmap_subset (const unsigned long *bitmap1, +const unsigned long *bitmap2,int bits);int bitmap_weight (const unsigned long *bitmap,int bits);int bitmap_scnprintf (char *buf,unsigned int buflen,const unsigned long *maskp,int bits);
===================================================================
lib/bitmap.c +57 -3
77 lines not on this page · raw message
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 4/23 mask v2 - two missing 'const' qualifiers
In reply to Paul JacksonPatch_4_of_23 - two missing 'const' qualifiers in bitops/bitmap
Add a couple of missing 'const' qualifiers on bitops test_bit and bitmap_equal args.
Diffstat Patch_4_of_23:
include/asm-generic/bitops.h | 2 +- lib/bitmap.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
===================================================================
include/asm-generic/bitops.h +1 -1
@@ -42,7 +42,7 @@return retval; } -extern __inline__int test_bit (int nr,long * addr) +extern __inline__int test_bit (int nr,const unsigned long * addr) {int mask;
===================================================================
lib/bitmap.c +2 -2
@@ -17,7 +17,7 @@* * The operations in this lib/bitmap.c, and the associated * files include/linux/bitmap.h, include/linux/bitops.h, - * and include/asm-*/bitops.h, and in the *_BITMAP macros in +* and include/asm-<arch>/bitops.h, and in the *_BITMAP macros in * include/linux/types.h, support a model of a set of bits, in * positions 0 .. nbits-1, for some nbits size between 1 and some * modest size. There is no specific limit on the size, but the
@@ -92,7 +92,7 @@EXPORT_SYMBOL (bitmap_full);int bitmap_equal (const unsigned long *bitmap1, -unsigned long *bitmap2,int bits) +const unsigned long *bitmap2,int bits) {int k, lim = bits/BITS_PER_LONG ;;for (k =0 ; k < lim; ++k)
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 5/23 mask v2 - Add new mask.h file
In reply to Paul JacksonPatch_5_of_23 - New mask ADT
Adds new include/linux/mask.h header file ==> See this mask.h header for more extensive mask documentation <==
Diffstat Patch_5_of_23:
mask.h | 362 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 362 insertions(+)
===================================================================
include/linux/mask.h +369 -0
@@ -0,0 +1,369 @@ +#ifndef __LINUX_MASK_H +#define __LINUX_MASK_H + +/* +* include/linux/mask.h +* +* Copyright (c) 2004 Silicon Graphics, Inc. All rights reserved. +* +* Paul Jackson <[email protected]> +* +* This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) +* Version 2 (June 1991). See the "COPYING" file distributed with this +* software for more info. +*/ + +/* +* Mask is an abstract data type for multi-word bit masks. Masks +* are bitmaps (arrays of unsigned longs) wrapped in a struct. +* The struct wrapper enables them to be assigned and passed as +* arguments. Masks are useful for representing sets of small +* numbers, such as the CPU numbers on a multi-processor system. +* +* How mask.h fits with bitops.h, bitmap.h, cpumask.h and nodemask.h: +* +* 1) bitmap.h and lib/bitmap.c provide several operations +* for manipulating bitmaps, as arrays of unsigned long. +* There are operations that and, or, set, clear, shift, +* print, parse, and test these bitmaps. The routines +* typically require a pointer to an array of unsigned longs, +* and a count of the number of valid bits therein. +* +* The byte ordering of bitmaps is more natural on little +* endian architectures. See the big-endian headers +* include/asm-ppc64/bitops.h and include/asm-s390/bitops.h +* for the best explanations of this ordering. +* +* 2) bitops.h provides a few specific inline routines for +* finding the first set bit and the Hamming weight of +* these same bitmaps. Several architectures provide +* include/asm-<arch>/bitops.h variants, optimized for +* specific processor instruction sets. +* +* 3) mask.h makes use of bitmap.h, bitops.h and a few other +* kernel utilities to provide a mask abstract data type +* (ADT) as a structure of an array of unsigned longs. +* mask.h attempts to provide a fairly complete set of +* operations, to make it easy for users to write clear +* concise and correct mask manipulation code. +* +* The mask macros use the fairly rich compile time +* optimizations of gcc in order to generate optimum code +* for each architecture. Some of these macros require the +* current mask type or number of bits - the cpumask.h and +* nodemask.h macros serve to hide such details. +* +* 4) cpumask.h and nodemask.h are both based on mask.h. +* They provide cpu and node specific macros that hide +* such details as NR_CPUS that might be needed by the +* lower level mask macros defined below. +* +* Summary: +* Don't use mask.h directly - use cpumask.h and nodemask.h. +* +* The available mask operations and their rough meaning in the +* case that "nbits == BITS_PER_LONG" are: +* +* __mask(nbits) Use to define new *mask types +* mask_setbit(bit, mask) mask |= bit +* mask_clearbit(bit, mask) mask &= ~bit +* mask_setall(mask, nbits) mask = ~0UL +* mask_clearall(mask, nbits) mask = 0UL +* mask_isset(bit, mask) Is bit set in mask? +* mask_test_and_set(bit, mask) mask & bit ? 1 : (mask |= bit, 0) +* mask_and(dst, src1, src2, nbits) dst = src1 & src2 +* mask_or(dst, src1, src2, nbits) dst = src1 | src2 +* mask_xor(dst, src1, src2, nbits) dst = src1 ^ src2 +* mask_andnot(dst, src1, src2, nbits) dst = src1 & ~src2 +* mask_complement(dst, src, nbits) dst = ~src +* mask_equal(mask1, mask2, nbits) Are mask1 and mask2 equal? +* mask_intersects(mask1, mask2, nbits) Do mask1 and mask2 overlap? +* mask_subset(mask1, mask2, nbits) Is mask1 a subset of mask2? +* mask_empty(mask, nbits) Is mask empty? +* mask_full(mask, nbits) Are all bits set in mask? +* mask_weight(mask, nbits) Hamming Weight: number set bits +* mask_shift_right(dst, src, n, nbits) dst = src >> n +* mask_shift_left(dst, src, n, nbits) dst = src << n +* mask_first(mask, nbits) find_first_bit(mask, nbits) +* mask_next(bit, mask, nbits) find_next_bit(mask, size, bit, nbits) +* mask_of_bit(bit, T) returns mask with a single bit set +* MASK_ALL(nbits) returns mask with all bits set +* MASK_NONE(nbits) returns mask with no bits set +* mask_addr(mask) Array of unsigned long's in mask +* mask_scnprintf(buf, len, mask, nbits) scnprintf(buf, len, "%lx", mask, nbits) +* mask_parse(ubuf, ulen, mask, nbits) parse comma sep 32 bit words to mask +* +* Various Implementation Details +* ============================== +* +* The parameter 'T' above must be a variable of the appropriate +* mask type (cpumask_t or nodemask_t, for instance). This +* variable is only used for its typeof() information. +* +* For details of mask_scnprintf() and mask_parse(), see +* bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c +* +* A new *mask type should be defined, such as cpumask_t or +* nodemask_t, for each possibly different sized (number of +* bits) bitmask based on this mask ADT. The definition +* for example of cpumask_t is: +* typedef __mask(NR_CPUS) cpumask_t; +* +* The previous definitions of CPU_MASK_ALL were inconsistent. +* For cpumasks of one word size or less, they set exactly +* NR_CPUS bits, leaving any remaining high order bits zero. +* For cpumasks of multiple words, all bits were set, which +* might result in a cpumask of weight > NR_CPUS, if NR_CPUS is +* not an exact multiple of the number of bits in an unsigned +* long. The MASK_ALL(nbits) macro fixes this inconsistency +* by refining the static initializor to set only valid bits +* in the last word. +* +* These macros presume that all masks passed in a given call +* are the same nbits long, and that only bits in positions +* b where 0 <= b < nbits might be set in input masks. +* They ensure that no additional bits outside this range +* become set (however don't protect against improperly set +* bits that are outside this range but still inside the array +* of unsigned longs representing the mask.) In other words, +* any implementation of these ops may assume as a precondition +* that any unused bits (bits in the array of unsigned +* longs, outside the range 0 to nbits-1) are zero. And any +* implementation of these ops must ensure as a postcondition +* on all output masks that this same precondition (unused +* bits are zero) holds. If you manage to create, by some +* other means, a mask with some unused bits non-zero, and +* then pass that mask to one of these mask operations, that +* operation may malfunction. +* +* The abstract bit model supported by these masks is that of +* an infinite set of bits, in positions numbered 0 and up, +* where all but the first 'nbits' bits are always zero. +* Calls that implicitly attempt to set any bit outside of +* the first 'nbits' bits successfully and quietly leave such +* bits as zero. Calls that query or modify specifically +* numbered bit positions require as a precondition that the +* specified bit position 'n' is the range 0 <= n < nbits, and +* may malfunction if handed a bit position outside this range. +* +* The mask_addr() op enables violating this model. It returns +* the address of the start of the array of unsigned +* longs, enabling the caller to directly manipulate them. +* This can be used to intermix mask ops with classic 'C' bit +* operations, usually only done on systems whose cpumask_t +* fits in a single unsigned long word. +* +* The underlying bitmap.c operations such as bitmap_and() and +* bitmap_or() don't follow this model. They don't assume +* the precondition that unused bits are zero, and they do not +* mask off any unused portion of input masks in most cases. +* The bitmap operations that produce Boolean or scalar results, +* such as for empty, full and weight, _do_ filter out unused bits. +* However the underlying bitop.h operations, such as set_bit() +* and clear_bit(), do no sanitizing of their inputs, depending +* heavily on preconditions. +* +* The declaration of the array _m[] of unsigned longs in the +* definition of __mask() below intentionally does not use +* the DECLARE_BITMAP() macro. It would be gratuitously opaque +* in this case - as the macro implementations below depend on +* the internal details of this declaration. +* +* The MASK_LAST_WORD() macro defines the value of the last (high +* order) word of a bitmask. In particular, for the case of a +* mask of a size that is an exact multiple of the word size, +* with all bits set, it ensures that this value is all one's, +* not all zero's. +* +* The file include/mask.h applies to all architectures. +* Architectures requiring custom details should provide +* them in their include/asm-<arch>/bitops.h file, and +* if necessary modify the common include/linux/mask.h +* file to conditionally generate the necessary code, +* depending on compile time settings. No need to write +* ugly #ifdef's to do this - gcc provides a rich set +* of compile time extensions. See further for example: +* http://gcc.gnu.org/onlinedocs/gcc-3.3.3/gcc/C-Extensions.html +* +* Some architectures (I'm told sparc32) do not pass structures +* efficiently as arguments to subroutine calls, even if the +* structure is just one word long. If you need to pass +* a cpumask or nodemask to a subroutine in a performance +* critical path on such an architecture, then as an +* alternative, pass the first unsigned long of the mask +* directly, using cpus_addr() or nodes_addr(). Of course, +* if your masks are more than one word long, this won't +* be adequate. +*/ + +#include "linux/bitops.h" +#include "linux/string.h" +#include "linux/types.h" +#include "linux/kernel.h" +#include "linux/bitmap.h" + +#define __mask (bits) struct { unsigned long _m[BITS_TO_LONGS(bits)]; } + +#define MASK_LAST_WORD (nbits) \ +( \ + ((nbits) % BITS_PER_LONG) ? \ + (1<<((nbits) % BITS_PER_LONG))-1 : ~0UL \ +) + +#define mask_setbit (bit, mask) \ + set_bit((bit), (mask)._m) + +#define mask_clearbit (bit, mask) \ + clear_bit((bit), (mask)._m) + +#define mask_setall (mask, nbits) \ +do { \ + size_t sz_all_but_last = sizeof(mask) - sizeof(unsigned long); \ + if (sz_all_but_last > 0) \ + memset((mask)._m, 0xff, sz_all_but_last); \ + (mask)._m[BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits); \ +} while(0) + +#define mask_clearall (mask, nbits) \ +do { \ + if (sizeof(mask) == sizeof(unsigned long)) \ + (mask)._m[0] = 0UL; \ + else \ + bitmap_clear((mask)._m, (nbits)); \ +} while(0) + +#define mask_isset (bit, mask) \ + test_bit((bit), (mask)._m) + +#define mask_test_and_set (bit, mask) \ + test_and_set_bit((bit), (mask)._m) + +#define mask_and (dst, src1, src2, nbits) \ +do { \ + if (sizeof(dst) == sizeof(unsigned long)) \ + (dst)._m[0] = (src1)._m[0] & (src2)._m[0]; \ + else \ + bitmap_and((dst)._m, (src1)._m, (src2)._m, (nbits)); \ +} while(0) + +#define mask_or (dst, src1, src2, nbits) \ +do { \ + if (sizeof(dst) == sizeof(unsigned long)) \ + (dst)._m[0] = (src1)._m[0] | (src2)._m[0]; \ + else \ + bitmap_or((dst)._m, (src1)._m, (src2)._m, (nbits)); \ +} while(0) + +#define mask_xor (dst, src1, src2, nbits) \ +do { \ + if (sizeof(dst) == sizeof(unsigned long)) \ + (dst)._m[0] = (src1)._m[0] ^ (src2)._m[0]; \ + else \ + bitmap_xor((dst)._m, (src1)._m, (src2)._m, (nbits)); \ +} while(0) + +#define mask_andnot (dst, src1, src2, nbits) \ +do { \ + if (sizeof(dst) == sizeof(unsigned long)) \ + (dst)._m[0] = (src1)._m[0] & ~(src2)._m[0]; \ + else \ + bitmap_andnot((dst)._m, (src1)._m, (src2)._m, (nbits)); \ +} while(0) + +#define mask_complement (dst, src, nbits) \ + bitmap_complement((dst)._m, (src)._m, (nbits)) + +#define mask_equal (mask1, mask2, nbits) \ +({ \ + int r; \ + if (sizeof(mask1) == sizeof(unsigned long)) \ + r = ((mask1)._m[0] == (mask2)._m[0]); \ + else \ + r = bitmap_equal((mask1)._m, (mask2)._m, (nbits)); \ + r; \ +}) + +#define mask_intersects (mask1, mask2, nbits) \ +({ \ + int r; \ + if (sizeof(mask1) == sizeof(unsigned long)) \ + r = (((mask1)._m[0] & (mask2)._m[0]) != 0); \ + else \ + r = bitmap_intersects((mask1)._m, (mask2)._m, (nbits)); \ + r; \ +}) + +#define mask_subset (mask1, mask2, nbits) \ +({ \ + int r; \ + if (sizeof(mask1) == sizeof(unsigned long)) \ + r = (((mask1)._m[0] & ~(mask2)._m[0]) == 0); \ + else \ + r = bitmap_subset((mask1)._m, (mask2)._m, (nbits)); \ + r; \ +}) + +#define mask_empty (mask, nbits) \ +({ \ + int r; \ + if (sizeof(mask) == sizeof(unsigned long)) \ + r = ((mask)._m[0] == 0UL); \ + else \ + r = bitmap_empty((mask)._m, (nbits)); \ + r; \ +}) + +#define mask_full (mask, nbits) \ + bitmap_full((mask)._m, (nbits)) + +#define mask_weight (mask, nbits) \ + bitmap_weight((mask)._m, (nbits)) + +#define mask_shift_right (dst, src, n, nbits) \ + bitmap_shift_right((dst)._m, (src)._m, (n), (nbits)) + +#define mask_shift_left (dst, src, n, nbits) \ + bitmap_shift_left((dst)._m, (src)._m, (n), (nbits)) + +#define mask_first (mask, nbits) \ + find_first_bit((mask)._m, (nbits)) + +#define mask_next (bit, mask, nbits) \ + find_next_bit((mask)._m, (nbits), (bit)+1) + +#define mask_of_bit (bit,T ) \ +({ \ + typeof(T) m; \ + mask_clearall(m, 8*sizeof(m)); \ + mask_setbit((bit), m); \ + m; \ +}) + +/* Use if nbits <= BITS_PER_LONG */ +#define MASK_ALL1 (nbits) \ +{ { \ + [BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits) \ +} } + +/* Use if nbits > BITS_PER_LONG */ +#define MASK_ALL2 (nbits) \ +{ { \ + [0 ... BITS_TO_LONGS(nbits)-2] = ~0UL, \ + [BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits) \ +} } + +#define MASK_NONE (nbits) \ +{ { \ + [0 ... BITS_TO_LONGS(nbits)-1] = 0UL \ +} } + +#define mask_addr (mask) \ + ((mask)._m) + +#define mask_scnprintf (buf, len, mask, nbits) \ + bitmap_scnprintf((buf), (len), ((mask)._m), (nbits)) + +#define mask_parse (ubuf, ulen, mask, nbits) \ + bitmap_parse((ubuf), (ulen), ((mask)._m), (nbits)) + +#endif /* __LINUX_MASK_H */
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 5/23] mask v2 - Add new mask.h file
Quoted 4 lines · Paul Jackson
Patch_5_of_23- New mask ADTAdds new include/linux/mask.h header file ==> See this mask.h header for more extensive mask documentation <==
<snip>
include/linux/mask.h line 353
Quoted 12 lines
include/linux/mask.h +12
-0+/* Use if nbits <= BITS_PER_LONG */ +#define MASK_ALL1 (nbits) \ +{ { \ + [BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits) \ +} } + +/* Use if nbits > BITS_PER_LONG */ +#define MASK_ALL2 (nbits) \ +{ { \ + [0 ... BITS_TO_LONGS(nbits)-2] = ~0UL, \ + [BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits) \ +} }
Gotta say, I'm not a bit fan of the names of these macros. They're disappointingly short on descriptiveness. ;) Maybe MASK_ALL_SINGLE_LONG and MASK_ALL_MULTIPLE_LONG? Something that more explicitly shows the difference between them. So when we're reading code later on, we're not constantly looking up the definition and saying, "What's the difference between MASK_ALL1 & MASK_ALL2 again?"
-Matt
Re: [Patch 5/23] mask v2 - Add new mask.h file
Quoted 1 line
I'm not a bit fan of the names of these macros ...
MASK_ALL1...
Hmmm ... the way these names were, in this patch a couple of days ago, they spanned files (defined in mask.h, used in cpumask.h). So making the names a little "bigger" might make sense. I use "big" names for stuff that is intended to be visible in larger namespaces.
However:
1) With yesterdays 24/23 patch, these names only span a few lines in mask.h, so short cryptic names are perhaps more appropriate.
2) The key issue here is whether the mask.h type is intended to usable in its own right, only to generate various named mask types.
We _could_ have three levels of coding multiword bit masks:
cpumask, nodemask, ...
mask
bitmap, bitops, plain old C
When I first started thinking about these a few months ago, I intended to make both the mask and cpumask/nodemask level widely usable. Now I don't think that's a good idea. Others only need two levels:
cpumask, nodemask, ...
bitmap, bitops, plain old C
The 'mask.h' stuff now exists only to provide a common implementation basis for the named mask types. Perhaps I should rename 'mask.h' to something such as 'mask_innards.h' ... ;).
Notice the comment in mask.h, after the lengthy explanation of bitmap, bitops, mask and cpumask/nodemask:
Summary:
Don't use mask.h directly - use cpumask.h and nodemask.h.
So, to make a long story short, the "unfriendly" names MASK_ALL1 fit their use. The solution to the problem of remembering what they mean is ... don't use them ;).
What am I missing? What itch is not yet being scratched?
... hmmm ... "mask_innards.h" ... I rather like that.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 6/23 mask v2 - Replace cpumask_t with one using mask
In reply to Paul JacksonPatch_6_of_23 - Rework cpumasks to use new mask ADT
Removes many old include/asm-<arch> and asm-generic cpumask files Add intersects, subset, xor and andnot operators. Provides temporary emulators for obsolete const, promote, coerce Presents entire cpumask API clearly in single cpumask.h file
Diffstat Patch_6_of_23:
asm-alpha/cpumask.h | 6 - asm-arm/cpumask.h | 6 - asm-arm26/cpumask.h | 6 - asm-cris/cpumask.h | 6 - asm-generic/cpumask.h | 40 ------- asm-generic/cpumask_arith.h | 49 --------- asm-generic/cpumask_array.h | 54 --------- asm-generic/cpumask_const_reference.h | 29 ----- asm-generic/cpumask_const_value.h | 21 --- asm-generic/cpumask_up.h | 59 ---------- asm-h8300/cpumask.h | 6 - asm-i386/cpumask.h | 6 - asm-m68k/cpumask.h | 6 - asm-m68knommu/cpumask.h | 6 - asm-mips/cpumask.h | 6 - asm-parisc/cpumask.h | 6 - asm-ppc/cpumask.h | 6 - asm-ppc64/cpumask.h | 6 - asm-s390/cpumask.h | 6 - asm-sh/cpumask.h | 6 - asm-sparc/cpumask.h | 6 - asm-sparc64/cpumask.h | 6 - asm-um/cpumask.h | 6 - asm-v850/cpumask.h | 6 - asm-x86_64/cpumask.h | 6 - linux/cpumask.h | 184 ++++++++++++++++++++++++++++------ 26 files changed, 153 insertions(+), 397 deletions(-)
===================================================================
include/asm-alpha/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_ALPHA_CPUMASK_H -#define _ASM_ALPHA_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_ALPHA_CPUMASK_H */
===================================================================
include/asm-arm/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_ARM_CPUMASK_H -#define _ASM_ARM_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_ARM_CPUMASK_H */
===================================================================
include/asm-arm26/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_ARM26_CPUMASK_H -#define _ASM_ARM26_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_ARM26_CPUMASK_H */
===================================================================
include/asm-cris/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_CRIS_CPUMASK_H -#define _ASM_CRIS_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_CRIS_CPUMASK_H */
===================================================================
include/asm-generic/cpumask.h +0 -40
@@ -1,40 +0,0 @@ -#ifndef __ASM_GENERIC_CPUMASK_H -#define __ASM_GENERIC_CPUMASK_H - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/threads.h> -#include <linux/types.h> -#include <linux/bitmap.h> - -#if NR_CPUS >BITS_PER_LONG &&NR_CPUS !=1 -#define CPU_ARRAY_SIZE BITS_TO_LONGS(NR_CPUS) - -struct cpumask -{ -unsigned long mask[CPU_ARRAY_SIZE ]; -}; - -typedef struct cpumask cpumask_t ; - -#else -typedef unsigned long cpumask_t ; -#endif - -#ifdef CONFIG_SMP -#if NR_CPUS >BITS_PER_LONG -#include <asm-generic/cpumask_array.h> -#else -#include <asm-generic/cpumask_arith.h> -#endif -#else -#include <asm-generic/cpumask_up.h> -#endif - -#if NR_CPUS <=4 *BITS_PER_LONG -#include <asm-generic/cpumask_const_value.h> -#else -#include <asm-generic/cpumask_const_reference.h> -#endif - -#endif /* __ASM_GENERIC_CPUMASK_H */
===================================================================
include/asm-generic/cpumask_arith.h +0 -49
49 lines not on this page · raw message
===================================================================
include/asm-generic/cpumask_array.h +0 -54
54 lines not on this page · raw message
===================================================================
include/asm-generic/cpumask_const_reference.h +0 -29
@@ -1,29 +0,0 @@ -#ifndef __ASM_GENERIC_CPUMASK_CONST_REFERENCE_H -#define __ASM_GENERIC_CPUMASK_CONST_REFERENCE_H - -struct cpumask_ref { -const cpumask_t *val; -}; - -typedef const struct cpumask_ref cpumask_const_t ; - -#define mk_cpumask_const (map) ((cpumask_const_t){ &(map) }) -#define cpu_isset_const (cpu, map) cpu_isset(cpu, *(map).val) - -#define cpus_and_const (dst,src1,src2) cpus_and(dst,*(src1).val,*(src2).val) -#define cpus_or_const (dst,src1,src2) cpus_or(dst,*(src1).val,*(src2).val) - -#define cpus_equal_const (map1, map2) cpus_equal(*(map1).val, *(map2).val) - -#define cpus_copy_const (map1, map2) bitmap_copy((map1).mask, (map2).val->mask, NR_CPUS) - -#define cpus_empty_const (map) cpus_empty(*(map).val) -#define cpus_weight_const (map) cpus_weight(*(map).val) -#define first_cpu_const (map) first_cpu(*(map).val) -#define next_cpu_const (cpu, map) next_cpu(cpu, *(map).val) - -/* only ever use this for things that are _never_ used on large boxen */ -#define cpus_coerce_const (map) cpus_coerce(*(map).val) -#define any_online_cpu_const (map) any_online_cpu(*(map).val) - -#endif /* __ASM_GENERIC_CPUMASK_CONST_REFERENCE_H */
===================================================================
include/asm-generic/cpumask_const_value.h +0 -21
@@ -1,21 +0,0 @@ -#ifndef __ASM_GENERIC_CPUMASK_CONST_VALUE_H -#define __ASM_GENERIC_CPUMASK_CONST_VALUE_H - -typedef const cpumask_t cpumask_const_t ; - -#define mk_cpumask_const (map) (map) -#define cpu_isset_const (cpu, map) cpu_isset(cpu, map) -#define cpus_and_const (dst,src1,src2) cpus_and(dst, src1, src2) -#define cpus_or_const (dst,src1,src2) cpus_or(dst, src1, src2) -#define cpus_equal_const (map1, map2) cpus_equal(map1, map2) -#define cpus_empty_const (map) cpus_empty(map) -#define cpus_copy_const (map1, map2) do { map1 = (cpumask_t)map2; } while (0) -#define cpus_weight_const (map) cpus_weight(map) -#define first_cpu_const (map) first_cpu(map) -#define next_cpu_const (cpu, map) next_cpu(cpu, map) - -/* only ever use this for things that are _never_ used on large boxen */ -#define cpus_coerce_const (map) cpus_coerce(map) -#define any_online_cpu_const (map) any_online_cpu(map) - -#endif /* __ASM_GENERIC_CPUMASK_CONST_VALUE_H */
===================================================================
include/asm-generic/cpumask_up.h +0 -59
59 lines not on this page · raw message
===================================================================
include/asm-h8300/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_H8300_CPUMASK_H -#define _ASM_H8300_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_H8300_CPUMASK_H */
===================================================================
include/asm-i386/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_I386_CPUMASK_H -#define _ASM_I386_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_I386_CPUMASK_H */
===================================================================
include/asm-m68k/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_M68K_CPUMASK_H -#define _ASM_M68K_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_M68K_CPUMASK_H */
===================================================================
include/asm-m68knommu/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_M68KNOMMU_CPUMASK_H -#define _ASM_M68KNOMMU_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_M68KNOMMU_CPUMASK_H */
===================================================================
include/asm-mips/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_MIPS_CPUMASK_H -#define _ASM_MIPS_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_MIPS_CPUMASK_H */
===================================================================
include/asm-parisc/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_PARISC_CPUMASK_H -#define _ASM_PARISC_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_PARISC_CPUMASK_H */
===================================================================
include/asm-ppc/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_PPC_CPUMASK_H -#define _ASM_PPC_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_PPC_CPUMASK_H */
===================================================================
include/asm-ppc64/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_PPC64_CPUMASK_H -#define _ASM_PPC64_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_PPC64_CPUMASK_H */
===================================================================
include/asm-s390/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_S390_CPUMASK_H -#define _ASM_S390_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_S390_CPUMASK_H */
===================================================================
include/asm-sh/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_SH_CPUMASK_H -#define _ASM_SH_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_SH_CPUMASK_H */
===================================================================
include/asm-sparc/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_SPARC_CPUMASK_H -#define _ASM_SPARC_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_SPARC_CPUMASK_H */
===================================================================
include/asm-sparc64/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_SPARC64_CPUMASK_H -#define _ASM_SPARC64_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_SPARC64_CPUMASK_H */
===================================================================
include/asm-um/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_UM_CPUMASK_H -#define _ASM_UM_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_UM_CPUMASK_H */
===================================================================
include/asm-v850/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_V850_CPUMASK_H -#define _ASM_V850_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_V850_CPUMASK_H */
===================================================================
include/asm-x86_64/cpumask.h +0 -6
@@ -1,6 +0,0 @@ -#ifndef _ASM_X86_64_CPUMASK_H -#define _ASM_X86_64_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_X86_64_CPUMASK_H */
===================================================================
include/linux/cpumask.h +157 -31
201 lines not on this page · raw message
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 6/23] mask v2 - Replace cpumask_t with one using mask
Quoted 5 lines · Paul Jackson
Patch_6_of_23- Rework cpumasks to use new mask ADT
Removes many old include/asm-<arch> and asm-generic cpumask files Add intersects, subset, xor and andnot operators. Provides temporary emulators for obsolete const, promote, coerce Presents entire cpumask API clearly in singlecpumask.hfile
<snip>
Review
Quoted 4 lines
(quoted diff) +4
-0+#else /* !CONFIG_SMP */ + +#define cpu_online_map cpumask_of_cpu(0) +#define cpu_possible_map cpumask_of_cpu(0)
I mentioned earlier that there's probably a better way to do this for UP... What do you think about this?
-Matt
include/linux/cpumask.h +6 -2
@@ -134,8 +134,12 @@ extern cpumask_t cpu_possible_map;#else /* !CONFIG_SMP */ -#define cpu_online_map cpumask_of_cpu(0) -#define cpu_possible_map cpumask_of_cpu(0) +#define cpu_online_map \ +({ \ + cpumask_t m = MASK_ALL1(NR_CPUS); \ + m; \ +}) +#define cpu_possible_map cpu_online_map#define num_online_cpus () 1#define num_possible_cpus () 1
Re: [Patch 6/23] mask v2 - Replace cpumask_t with one using mask
Quoted 1 line
What do you think about this?
Check out my patch 24 of 23, sent last night, which should make cpumask_of_cpu() efficient for UP systems.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 6/23] mask v2 - Replace cpumask_t with one using mask
Quoted 4 lines · Paul Jackson
Quoted 1 line
What do you think about this?
Check out my patch 24 of 23, sent last night, which should make
cpumask_of_cpu()efficient for UP systems.
Yep, I was just reading through that patch. It's an interesting solution, but I'm not quite sure how I feel about it. It's definitely not the way I would have solved the problem, but it looks like it will work fine. My only problem with it is that it seems to preclude the possibility of having two different sized masks in a single file. At least without making a .h file for each different mask, and then including each those files in the .c file that needs the multiple masks. This behavior is fine for cpumasks & nodemasks, but makes it difficult for arbitrary masks. I don't foresee this happening a lot (multiple different size masks excluding cpumasks and nodemasks), so it shouldn't be a big deal.
My first impression would be to just define both MASK_ALL1 & MASK_ALL2, and less importantly mask_of_bit1 & mask_of_bit2, in mask.h, and let whatever is using the macros choose the appropriate one to use. For example, moving the cpumask_of_bit() & CPU_MASK_ALL defines into the #ifdef CONFIG_SMP part. This alleviates the (albeit unlikely) problem of multiple masks.
-Matt
Re: [Patch 6/23] mask v2 - Replace cpumask_t with one using mask
Quoted 2 lines
Yep, I was just reading through that patch. It's an interesting solution, but I'm not quite sure how I feel about it.
It [Patch 24/23] might be seriously broken, for files including both cpumask and nodemask. I'm looking at that now.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 6/23] mask v2 - Replace cpumask_t with one using mask
Yes - [Patch 24/23] is seriously fouled up beyond all recall. New replacement [Patch 24a/23] due out momentarilly.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 6/23] mask v2 - Replace cpumask_t with one using mask
In reply to Matthew Dobsoninclude/linux/cpumask.h extern cpumask_t cpu_possible_map; · line 141
Quoted 6 lines · Matthew
a better way to do this for UP.
include/linux/cpumask.h +5
-0+#define cpu_online_map \ +({ \ + cpumask_t m = MASK_ALL1(NR_CPUS); \ + m; \ +})
This only helps cpu_online_map and cpu_possible_map, and only on UP's.
My controversial patch 24/23 helps all MASK_ALL based initializations, and all mask_of_bit based initializations, for all systems up to 32 CPUs (or 64, depending on sizeof(long)).
In particular, grep for 'cpumask_of_cpu(0)' in the kernel. You will find many hits. This should be efficient for all 'normal' sized systems.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 7/23 mask v2 - Remove i386 obsolete cpumask ops
In reply to Paul JacksonPatch_7_of_23 - Remove/recode obsolete cpumask macros from arch i386
Remove by recoding all uses of the obsolete cpumask const, coerce and promote macros.
Diffstat Patch_7_of_23:
arch/i386/kernel/io_apic.c | 2 +- arch/i386/kernel/smp.c | 2 +- arch/i386/mach-voyager/voyager_smp.c | 30 +++++++++++++++--------------- include/asm-i386/genapic.h | 2 +- include/asm-i386/mach-bigsmp/mach_apic.h | 8 ++++---- include/asm-i386/mach-default/mach_apic.h | 10 +++++----- include/asm-i386/mach-es7000/mach_apic.h | 10 +++++----- include/asm-i386/mach-numaq/mach_apic.h | 2 +- include/asm-i386/mach-summit/mach_apic.h | 8 ++++---- include/asm-i386/mach-visws/mach_apic.h | 4 ++-- 10 files changed, 39 insertions(+), 39 deletions(-)
===================================================================
arch/i386/kernel/io_apic.c +1 -1
@@ -264,7 +264,7 @@struct irq_pin_list *entry = irq_2_pin + irq;unsigned int apicid_value; - apicid_value =cpu_mask_to_apicid (mk_cpumask_const (cpumask)); + apicid_value =cpu_mask_to_apicid (cpumask);/* Prepare to do the io_apic_write */ apicid_value = apicid_value <<24 ;spin_lock_irqsave (&ioapic_lock, flags);
arch/i386/kernel/smp.c +1 -1
@@ -160,7 +160,7 @@*/ inline void send_IPI_mask_bitmask (cpumask_t cpumask,int vector) { -unsigned long mask =cpus_coerce (cpumask); +unsigned long mask =cpus_addr (cpumask)[0 ];unsigned long cfg;unsigned long flags;
arch/i386/mach-voyager/voyager_smp.c +15 -15
@@ -154,7 +154,7 @@ send_CPI_allbutself(__u8 cpi) {__u8 cpu =smp_processor_id (); -__u32 mask =cpus_coerce (cpu_online_map) & ~(1 << cpu); +__u32 mask =cpus_addr (cpu_online_map)[0 ] & ~(1 << cpu);send_CPI (mask, cpi); }
@@ -403,11 +403,11 @@/* set up everything for just this CPU, we can alter * this as we start the other CPUs later */ /* now get the CPU disposition from the extended CMOS */ - phys_cpu_present_map =cpus_promote (voyager_extended_cmos_read (VOYAGER_PROCESSOR_PRESENT_MASK )); -cpus_coerce (phys_cpu_present_map) |=voyager_extended_cmos_read (VOYAGER_PROCESSOR_PRESENT_MASK +1 ) <<8 ; -cpus_coerce (phys_cpu_present_map) |=voyager_extended_cmos_read (VOYAGER_PROCESSOR_PRESENT_MASK +2 ) <<16 ; -cpus_coerce (phys_cpu_present_map) |=voyager_extended_cmos_read (VOYAGER_PROCESSOR_PRESENT_MASK +3 ) <<24 ; -printk ("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n" ,cpus_coerce (phys_cpu_present_map)); +cpus_addr (phys_cpu_present_map)[0 ] =voyager_extended_cmos_read (VOYAGER_PROCESSOR_PRESENT_MASK ); +cpus_addr (phys_cpu_present_map)[0 ] |=voyager_extended_cmos_read (VOYAGER_PROCESSOR_PRESENT_MASK +1 ) <<8 ; +cpus_addr (phys_cpu_present_map)[0 ] |=voyager_extended_cmos_read (VOYAGER_PROCESSOR_PRESENT_MASK +2 ) <<16 ; +cpus_addr (phys_cpu_present_map)[0 ] |=voyager_extended_cmos_read (VOYAGER_PROCESSOR_PRESENT_MASK +3 ) <<24 ; +printk ("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n" ,cpus_addr (phys_cpu_present_map)[0 ]);/* Here we set up the VIC to enable SMP */ /* enable the CPIs by writing the base vector to their register */ outb (VIC_DEFAULT_CPI_BASE ,VIC_CPI_BASE_REGISTER );
@@ -707,12 +707,12 @@/* now that the cat has probed the Voyager System Bus, sanity * check the cpu map */ if ( ((voyager_quad_processors | voyager_extended_vic_processors) - &cpus_coerce (phys_cpu_present_map)) !=cpus_coerce (phys_cpu_present_map)) { + &cpus_addr (phys_cpu_present_map)[0 ]) !=cpus_addr (phys_cpu_present_map)[0 ]) {/* should panic */ printk ("\n\n***WARNING*** Sanity check of CPU present map FAILED\n" ); } }else if (voyager_level ==4 ) - voyager_extended_vic_processors =cpus_coerce (phys_cpu_present_map); + voyager_extended_vic_processors =cpus_addr (phys_cpu_present_map)[0 ];/* this sets up the idle task to run on the current cpu */ voyager_extended_cpus =1 ;
@@ -910,7 +910,7 @@if (!cpumask)BUG (); -if ((cpumask &cpus_coerce (cpu_online_map)) != cpumask) +if ((cpumask &cpus_addr (cpu_online_map)[0 ]) != cpumask)BUG ();if (cpumask & (1 <<smp_processor_id ()))BUG ();
@@ -953,7 +953,7 @@preempt_disable (); - cpu_mask =cpus_coerce (mm->cpu_vm_mask) & ~(1 <<smp_processor_id ()); + cpu_mask =cpus_addr (mm->cpu_vm_mask)[0 ] & ~(1 <<smp_processor_id ());local_flush_tlb ();if (cpu_mask)flush_tlb_others (cpu_mask, mm,FLUSH_ALL );
@@ -969,7 +969,7 @@preempt_disable (); - cpu_mask =cpus_coerce (mm->cpu_vm_mask) & ~(1 <<smp_processor_id ()); + cpu_mask =cpus_addr (mm->cpu_vm_mask)[0 ] & ~(1 <<smp_processor_id ());if (current->active_mm == mm) {if (current->mm)
@@ -990,7 +990,7 @@preempt_disable (); - cpu_mask =cpus_coerce (mm->cpu_vm_mask) & ~(1 <<smp_processor_id ()); + cpu_mask =cpus_addr (mm->cpu_vm_mask)[0 ] & ~(1 <<smp_processor_id ());if (current->active_mm == mm) {if (current->mm)__flush_tlb_one (va);
@@ -1099,7 +1099,7 @@ int wait) {struct call_data_struct data; -__u32 mask =cpus_coerce (cpu_online_map); +__u32 mask =cpus_addr (cpu_online_map)[0 ]; mask &= ~(1 <<smp_processor_id ());
@@ -1787,9 +1787,9 @@unsigned long irq_mask =1 << irq;int cpu; - real_mask =cpus_coerce (mask) & voyager_extended_vic_processors; + real_mask =cpus_addr (mask)[0 ] & voyager_extended_vic_processors; -if (cpus_coerce (mask) ==0 ) +if (cpus_addr (mask)[0 ] ==0 )/* can't have no cpu's to accept the interrupt -- extremely * bad things will happen */ return ;
include/asm-i386/genapic.h +1 -1
@@ -62,7 +62,7 @@unsigned (*get_apic_id)(unsigned long x);unsigned long apic_id_mask; -unsigned int (*cpu_mask_to_apicid)(cpumask_const_t cpumask); +unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);/* ipi */ void (*send_IPI_mask)(cpumask_t mask,int vector);
include/asm-i386/mach-bigsmp/mach_apic.h +4 -4
@@ -140,14 +140,14 @@return (1 ); } -static inline unsigned int cpu_mask_to_apicid (cpumask_const_t cpumask) +static inline unsigned int cpu_mask_to_apicid (cpumask_t cpumask) {int num_bits_set;int cpus_found =0 ;int cpu;int apicid; - num_bits_set =cpus_weight_const (cpumask); + num_bits_set =cpus_weight (cpumask);/* Return id to all */ if (num_bits_set ==NR_CPUS )return (int )0xFF ;
@@ -155,10 +155,10 @@* The cpus in the mask must all be on the apic cluster. If are not * on the same apicid cluster return default value of TARGET_CPUS. */ - cpu =first_cpu_const (cpumask); + cpu =first_cpu (cpumask); apicid =cpu_to_logical_apicid (cpu);while (cpus_found < num_bits_set) { -if (cpu_isset_const (cpu, cpumask)) { +if (cpu_isset (cpu, cpumask)) {int new_apicid =cpu_to_logical_apicid (cpu);if (apicid_cluster (apicid) !=apicid_cluster (new_apicid)){
include/asm-i386/mach-default/mach_apic.h +5 -5
@@ -5,12 +5,12 @@#define APIC_DFR_VALUE (APIC_DFR_FLAT) -static inline cpumask_const_t target_cpus (void ) +static inline cpumask_t target_cpus (void ) {#ifdef CONFIG_SMP -return mk_cpumask_const (cpu_online_map); +return cpu_online_map;#else -return mk_cpumask_const (cpumask_of_cpu (0 )); +return cpumask_of_cpu (0 );#endif }#define TARGET_CPUS (target_cpus())
@@ -118,9 +118,9 @@return physid_isset (GET_APIC_ID (apic_read (APIC_ID )), phys_cpu_present_map); } -static inline unsigned int cpu_mask_to_apicid (cpumask_const_t cpumask) +static inline unsigned int cpu_mask_to_apicid (cpumask_t cpumask) { -return cpus_coerce_const (cpumask); +return cpus_addr (cpumask)[0 ]; }static inline void enable_apic_mode (void )
include/asm-i386/mach-es7000/mach_apic.h +5 -5
@@ -89,7 +89,7 @@int apic = bios_cpu_apicid[smp_processor_id ()];printk ("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n" , (apic_version[apic] ==0x14 ) ? -"Physical Cluster" :"Logical Cluster" , nr_ioapics,cpus_coerce (TARGET_CPUS )); +"Physical Cluster" :"Logical Cluster" , nr_ioapics,cpus_addr (TARGET_CPUS )[0 ]); }static inline int multi_timer_check (int apic,int irq)
@@ -159,14 +159,14 @@return (1 ); } -static inline unsigned int cpu_mask_to_apicid (cpumask_const_t cpumask) +static inline unsigned int cpu_mask_to_apicid (cpumask_t cpumask) {int num_bits_set;int cpus_found =0 ;int cpu;int apicid; - num_bits_set =cpus_weight_const (cpumask); + num_bits_set =cpus_weight (cpumask);/* Return id to all */ if (num_bits_set ==NR_CPUS )return 0xFF ;
@@ -174,10 +174,10 @@* The cpus in the mask must all be on the apic cluster. If are not * on the same apicid cluster return default value of TARGET_CPUS. */ - cpu =first_cpu_const (cpumask); + cpu =first_cpu (cpumask); apicid =cpu_to_logical_apicid (cpu);while (cpus_found < num_bits_set) { -if (cpu_isset_const (cpu, cpumask)) { +if (cpu_isset (cpu, cpumask)) {int new_apicid =cpu_to_logical_apicid (cpu);if (apicid_cluster (apicid) !=apicid_cluster (new_apicid)){
include/asm-i386/mach-numaq/mach_apic.h +1 -1
@@ -136,7 +136,7 @@* We use physical apicids here, not logical, so just return the default * physical broadcast to stop people from breaking us */ -static inline unsigned int cpu_mask_to_apicid (cpumask_const_t cpumask) +static inline unsigned int cpu_mask_to_apicid (cpumask_t cpumask) {return (int )0xF ; }
include/asm-i386/mach-summit/mach_apic.h +4 -4
@@ -140,14 +140,14 @@ { } -static inline unsigned int cpu_mask_to_apicid (cpumask_const_t cpumask) +static inline unsigned int cpu_mask_to_apicid (cpumask_t cpumask) {int num_bits_set;int cpus_found =0 ;int cpu;int apicid; - num_bits_set =cpus_weight_const (cpumask); + num_bits_set =cpus_weight (cpumask);/* Return id to all */ if (num_bits_set ==NR_CPUS )return (int )0xFF ;
@@ -155,10 +155,10 @@* The cpus in the mask must all be on the apic cluster. If are not * on the same apicid cluster return default value of TARGET_CPUS. */ - cpu =first_cpu_const (cpumask); + cpu =first_cpu (cpumask); apicid =cpu_to_logical_apicid (cpu);while (cpus_found < num_bits_set) { -if (cpu_isset_const (cpu, cpumask)) { +if (cpu_isset (cpu, cpumask)) {int new_apicid =cpu_to_logical_apicid (cpu);if (apicid_cluster (apicid) !=apicid_cluster (new_apicid)){
include/asm-i386/mach-visws/mach_apic.h +2 -2
@@ -84,9 +84,9 @@return physid_isset (boot_cpu_physical_apicid, phys_cpu_present_map); } -static inline unsigned int cpu_mask_to_apicid (cpumask_const_t cpumask) +static inline unsigned int cpu_mask_to_apicid (cpumask_t cpumask) { -return cpus_coerce_const (cpumask); +return cpus_addr (cpumask)[0 ]; }static inline u32 phys_pkg_id (u32 cpuid_apic,int index_msb)
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 8/23 mask v2 - Remove ppc64 obsolete cpumask ops
In reply to Paul JacksonPatch_8_of_23 - Remove/recode obsolete cpumask macros from arch ppc64
Remove by recoding all uses of the obsolete cpumask const, coerce and promote macros.
Diffstat Patch_8_of_23:
open_pic.c | 8 ++++---- rtasd.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-)
===================================================================
arch/ppc64/kernel/open_pic.c +4 -4
@@ -592,7 +592,7 @@void openpic_init_processor (u_int cpumask) {openpic_write (&OpenPIC->Global.Processor_Initialization, -physmask (cpumask &cpus_coerce (cpu_online_map))); +physmask (cpumask &cpus_addr (cpu_online_map)[0 ])); }#ifdef CONFIG_SMP
@@ -626,7 +626,7 @@CHECK_THIS_CPU ;check_arg_ipi (ipi);openpic_write (&OpenPIC->THIS_CPU.IPI_Dispatch (ipi), -physmask (cpumask &cpus_coerce (cpu_online_map))); +physmask (cpumask &cpus_addr (cpu_online_map)[0 ])); }void openpic_request_IPIs (void )
@@ -712,7 +712,7 @@ {check_arg_timer (timer);openpic_write (&OpenPIC->Global.Timer[timer].Destination, -physmask (cpumask &cpus_coerce (cpu_online_map))); +physmask (cpumask &cpus_addr (cpu_online_map)[0 ])); }
@@ -837,7 +837,7 @@cpumask_t tmp;cpus_and (tmp, cpumask, cpu_online_map); -openpic_mapirq (irq_nr - open_pic_irq_offset,physmask (cpus_coerce (tmp))); +openpic_mapirq (irq_nr - open_pic_irq_offset,physmask (cpus_addr (tmp)[0 ])); }#ifdef CONFIG_SMP
arch/ppc64/kernel/rtasd.c +3 -3
@@ -413,7 +413,7 @@ }lock_cpu_hotplug (); - cpu =first_cpu_const (mk_cpumask_const (cpu_online_map)); + cpu =first_cpu (cpu_online_map);for (;;) {set_cpus_allowed (current,cpumask_of_cpu (cpu));do_event_scan (event_scan);
@@ -427,9 +427,9 @@schedule_timeout ((HZ *60 /rtas_event_scan_rate) /2 );lock_cpu_hotplug (); - cpu =next_cpu_const (cpu,mk_cpumask_const (cpu_online_map)); + cpu =next_cpu (cpu, cpu_online_map);if (cpu ==NR_CPUS ) - cpu =first_cpu_const (mk_cpumask_const (cpu_online_map)); + cpu =first_cpu (cpu_online_map); } error_vfree:
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 9/23 mask v2 - Remove x86_64 obsolete cpumask ops
In reply to Paul JacksonPatch_9_of_23 - Remove/recode obsolete cpumask macros from arch x86_64
Remove by recoding all uses of the obsolete cpumask const, coerce and promote macros.
Diffstat Patch_9_of_23:
arch/x86_64/kernel/io_apic.c | 2 +- arch/x86_64/kernel/pci-gart.c | 4 ++-- arch/x86_64/kernel/smp.c | 2 +- include/asm-x86_64/smp.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-)
===================================================================
arch/x86_64/kernel/io_apic.c +1 -1
@@ -1368,7 +1368,7 @@unsigned long flags;unsigned int dest; - dest =cpu_mask_to_apicid (mk_cpumask_const (mask)); + dest =cpu_mask_to_apicid (mask);/* * Only the first 8 bits are valid.
arch/x86_64/kernel/pci-gart.c +2 -2
@@ -134,7 +134,7 @@ {unsigned long flags;int bus = dev ? dev->bus->number :-1 ; -cpumask_const_t bus_cpumask =pcibus_to_cpumask (bus); +cpumask_t bus_cpumask =pcibus_to_cpumask (bus);int flushed =0 ;int i;
@@ -144,7 +144,7 @@u32 w;if (!northbridges[i])continue ; -if (bus >=0 && !(cpu_isset_const (i, bus_cpumask))) +if (bus >=0 && !(cpu_isset (i, bus_cpumask)))continue ;pci_write_config_dword (northbridges[i],0x9c , northbridge_flush_word[i] |1 );
arch/x86_64/kernel/smp.c +1 -1
@@ -94,7 +94,7 @@static inline void send_IPI_mask (cpumask_t cpumask,int vector) { -unsigned long mask =cpus_coerce (cpumask); +unsigned long mask =cpus_addr (cpumask)[0 ];unsigned long cfg;unsigned long flags;
include/asm-x86_64/smp.h +2 -2
@@ -86,9 +86,9 @@#define TARGET_CPUS 1#ifndef ASSEMBLY -static inline unsigned int cpu_mask_to_apicid (cpumask_const_t cpumask) +static inline unsigned int cpu_mask_to_apicid (cpumask_t cpumask) { -return cpus_coerce_const (cpumask); +return cpus_addr (cpumask)[0 ]; }#endif
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 10/23 mask v2 - Remove obsolete cpumask emulation
In reply to Paul JacksonPatch_10_of_23 - Remove obsolete cpumask emulation from cpumask.h
Now that the emulation of the obsolete cpumask macros is no longer needed, remove it from cpumask.h
Diffstat Patch_10_of_23:
cpumask.h | 12 ------------ 1 files changed, 12 deletions(-)
===================================================================
include/linux/cpumask.h +0 -12
@@ -155,16 +155,4 @@#define for_each_online_cpu (cpu) \ for_each_cpu_mask(cpu, cpu_online_map) -/* Begin obsolete cpumask operator emulation */ -#define cpu_isset_const (a,b) cpu_isset(a,b) -#define cpumask_const_t cpumask_t -#define cpus_coerce (m) (cpus_addr(m)[0]) -#define cpus_coerce_const cpus_coerce -#define cpus_promote (x) ({ cpumask_t m; m._m[0] = x; m; }) -#define cpus_weight_const cpus_weight -#define first_cpu_const first_cpu -#define mk_cpumask_const (x) x -#define next_cpu_const next_cpu -/* End of obsolete cpumask operator emulation */ -#endif /* __LINUX_CPUMASK_H */
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 11/23 mask v2 - Add new nodemasks.h file
In reply to Paul JacksonPatch_11_of_23 - Add new nodemasks.h file.
Provide a nodemasks_t type, using the mask.h ADT.
Diffstat Patch_11_of_23:
nodemask.h | 152 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 152 insertions(+)
===================================================================
include/linux/nodemask.h +156 -0
@@ -0,0 +1,156 @@ +#ifndef __LINUX_NODEMASK_H +#define __LINUX_NODEMASK_H + +/* +* Nodemasks provide a bit mask suitable for representing the +* set of Node's in a system, one bit position per Node number. +* +* See detailed comments in the file linux/mask.h describing the +* data type on which these nodemasks are based. +* +* For details of nodemask_scnprintf() and nodemask_parse(), +* see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c. +* +* The available nodemask operations are: +* +* void node_set(node, mask) turn on bit 'node' in mask +* void node_clear(node, mask) turn off bit 'node' in mask +* void nodes_setall(mask) set all bits +* void nodes_clear(mask) clear all bits +* int node_isset(node, mask) true iff bit 'node' set in mask +* int node_test_and_set(node, mask) test and set bit 'node' in mask +* +* void nodes_and(dst, src1, src2) dst = src1 & src2 [intersection] +* void nodes_or(dst, src1, src2) dst = src1 | src2 [union] +* void nodes_xor(dst, src1, src2) dst = src1 ^ src2 +* void nodes_andnot(dst, src1, src2) dst = src1 & ~src2 +* void nodes_complement(dst, src) dst = ~src +* +* int nodes_equal(mask1, mask2) Does mask1 == mask2? +* int nodes_intersects(mask1, mask2) Do mask1 and mask2 intersect? +* int nodes_subset(mask1, mask2) Is mask1 a subset of mask2? +* int nodes_empty(mask) Is mask empty (no bits sets)? +* int nodes_full(mask) Is mask full (all bits sets)? +* int nodes_weight(mask) Hamming weigh - number of set bits +* +* void nodes_shift_right(dst, src, n) Shift right +* void nodes_shift_left(dst, src, n) Shift left +* +* int first_node(mask) Number lowest set bit, or MAX_NUMNODES +* int next_node(node, mask) Next node past 'node', or MAX_NUMNODES +* +* nodemask_t nodemask_of_node(node) Return nodemask with bit 'node' set +* NODE_MASK_ALL Initializer - all bits set +* NODE_MASK_NONE Initializer - no bits set +* unsigned long *nodes_addr(mask) Array of unsigned long's in mask +* +* int nodemask_scnprintf(buf, len, mask) Format nodemask for printing +* int nodemask_parse(ubuf, ulen, mask) Parse ascii string as nodemask +* +* int num_online_nodes() Number of online nodes +* int num_possible_nodes() Number of all possible nodes +* int node_online(node) Is some node < MAX_NUMNODES online? +* int node_possible(node) Is some node < MAX_NUMNODES possible? +* void node_set_online(node) set node in node_online_map +* void node_set_offline(node) clear node in node_online_map +* int any_online_node(mask) First online node in mask +* +* for_each_node_mask(node, mask) for-loop node over mask +* for_each_node(node) for-loop node over node_possible_map +* for_each_online_node(node) for-loop node over node_online_map +*/ + +#include <linux/numa.h> +#include <linux/mask.h> +#include <asm/bug.h> + +typedef __mask (MAX_NUMNODES)nodemask_t ; +extern nodemask_t _unused_nodemask_arg_; + +#define node_set (node, mask) mask_setbit((node), (mask)) +#define node_clear (node, mask) mask_clearbit((node), (mask)) +#define nodes_setall (mask) mask_setall((mask), MAX_NUMNODES) +#define nodes_clear (mask) mask_clearall((mask), MAX_NUMNODES) +#define node_isset (node, mask) mask_isset((node), (mask)) +#define node_test_and_set (node, mask) mask_test_and_set((node), (mask)) +#define nodes_and (dst, src1, src2) mask_and((dst), (src1), (src2), MAX_NUMNODES) +#define nodes_or (dst, src1, src2) mask_or((dst), (src1), (src2), MAX_NUMNODES) +#define nodes_xor (dst, src1, src2) mask_xor((dst), (src1), (src2), MAX_NUMNODES) +#define nodes_andnot (dst, src1, src2) mask_andnot((dst), (src1), (src2), MAX_NUMNODES) +#define nodes_complement (dst, src) mask_complement((dst), (src), MAX_NUMNODES) +#define nodes_equal (mask1, mask2) mask_equal((mask1), (mask2), MAX_NUMNODES) +#define nodes_intersects (mask1, mask2) mask_intersects((mask1), (mask2), MAX_NUMNODES) +#define nodes_subset (mask1, mask2) mask_subset((mask1), (mask2), MAX_NUMNODES) +#define nodes_empty (mask) mask_empty((mask), MAX_NUMNODES) +#define nodes_full (mask) mask_full((mask), MAX_NUMNODES) +#define nodes_weight (mask) mask_weight((mask), MAX_NUMNODES) +#define nodes_shift_right (dst, src, n) \ + mask_shift_right((dst), (src), (n), MAX_NUMNODES) +#define nodes_shift_left (dst, src, n) \ + mask_shift_left((dst), (src), (n), MAX_NUMNODES) +#define first_node (mask) mask_first((mask), MAX_NUMNODES) +#define next_node (node, mask) mask_next((node), (mask), MAX_NUMNODES) +#define nodemask_of_node (node) \ + mask_of_bit((node), _unused_nodemask_arg_) +#if MAX_NUMNODES <=BITS_PER_LONG +#define NODE_MASK_ALL MASK_ALL1(MAX_NUMNODES) +#else +#define NODE_MASK_ALL MASK_ALL2(MAX_NUMNODES) +#endif +#define NODE_MASK_NONE MASK_NONE(MAX_NUMNODES) +#define nodes_addr (mask) mask_addr(mask) +#define nodemask_scnprintf (buf, len, mask) \ + mask_scnprintf((buf), (len), (mask), MAX_NUMNODES) +#define nodemask_parse (ubuf, ulen, mask) \ + mask_parse((ubuf), (ulen), (mask), MAX_NUMNODES) + +/* +* The following particular system nodemasks and operations +* on them manage all (possible) and online nodes. +*/ + +extern nodemask_t node_online_map; +extern nodemask_t node_possible_map; + +#ifdef CONFIG_NUMA + +#define num_online_nodes () nodes_weight(node_online_map) +#define num_possible_nodes () nodes_weight(node_possible_map) +#define node_online (node) node_isset((node), node_online_map) +#define node_possible (node) node_isset((node), node_possible_map) +#define node_set_online (node) node_set((node), node_online_map) +#define node_set_offline (node) node_clear((node), node_online_map) + +#define any_online_node (mask) \ +({ \ + nodemask_t n; \ + nodes_and(n, mask, node_online_map); \ + first_node(n); \ +}) + +#define for_each_node_mask (node, mask) \ + for (node = first_node(mask); \ + node < MAX_NUMNODES; \ + node = next_node(node, mask)) + +#else /* !CONFIG_NUMA */ + +#define num_online_nodes () 1 +#define num_possible_nodes () 1 +#define node_online (node) ({ BUG_ON((node) != 0); 1; }) +#define node_possible (node) ({ BUG_ON((node) != 0); 1; }) +#define node_set_online (node) ({ BUG_ON((node) != 0); }) +#define node_set_offline (node) ({ BUG(); }) + +#define any_online_node (mask) 0 + +#define for_each_node_mask (node, mask) for (node = 0; node < 1; node++) + +#endif /* CONFIG_NUMA */ + +#define for_each_node (node) \ + for_each_node_mask(node, node_possible_map) +#define for_each_online_node (node) \ + for_each_node_mask(node, node_online_map) + +#endif /* __LINUX_NODEMASK_H */
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 12/23 mask v2 - [1/7] mmzone.h changes for nodemask
In reply to Paul JacksonPatch_12_of_23 - the mmzone.h changes from Matthew's Patch [1/7]
Just the mmzone.h changes taken from this patch: removing extistant definition of node_online_map and helper functions, added a #include <nodemask.h>.
Diffstat Patch_12_of_23:
mmzone.h | 31 +------------------------------ 1 files changed, 1 insertion(+), 30 deletions(-)
===================================================================
include/linux/mmzone.h +1 -30
@@ -11,6 +11,7 @@#include <linux/cache.h> #include <linux/threads.h> #include <linux/numa.h> +#include <linux/nodemask.h> #include <asm/atomic.h> /* Free memory management - zoned buddy allocator. */
@@ -218,7 +219,6 @@#define node_present_pages (nid) (NODE_DATA(nid)->node_present_pages)#define node_spanned_pages (nid) (NODE_DATA(nid)->node_spanned_pages) -extern int numnodes;extern struct pglist_data *pgdat_list; void get_zone_counts(unsigned long *active, unsigned long *inactive,
@@ -336,35 +336,6 @@#error ZONES_SHIFT > MAX_ZONES_SHIFT#endif -extern DECLARE_BITMAP(node_online_map, MAX_NUMNODES); - -#if defined(CONFIG_DISCONTIGMEM ) || defined(CONFIG_NUMA ) - -#define node_online (node) test_bit(node, node_online_map) -#define node_set_online (node) set_bit(node, node_online_map) -#define node_set_offline (node) clear_bit(node, node_online_map) -static inline unsigned int num_online_nodes (void ) -{ -int i, num =0 ; - -for (i =0 ; i <MAX_NUMNODES ; i++){ -if (node_online (i)) - num++; - } -return num; -} - -#else /* !CONFIG_DISCONTIGMEM && !CONFIG_NUMA */ - -#define node_online (node) \ - ({ BUG_ON((node) != 0); test_bit(node, node_online_map); }) -#define node_set_online (node) \ - ({ BUG_ON((node) != 0); set_bit(node, node_online_map); }) -#define node_set_offline (node) \ - ({ BUG_ON((node) != 0); clear_bit(node, node_online_map); }) -#define num_online_nodes () 1 - -#endif /* CONFIG_DISCONTIGMEM || CONFIG_NUMA */ #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _LINUX_MMZONE_H */
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 13/23 mask v2 - [2/7] nodemask_t core changes
In reply to Paul JacksonPatch_13_of_23 - Matthew Dobson's [PATCH] nodemask_t core changes [2/7]
nodemask_t-02-core.patch - Changes to arch-independent code. Surprisingly few references to numnodes, open-coded node loops, etc. in generic code. Most important result of this patch is that no generic code assumes anything about node numbering. This allows individual arches to use sparse numbering if they care to.
Diffstat Patch_13_of_23:
Documentation/vm/numa | 2 +- include/linux/gfp.h | 2 +- include/linux/topology.h | 19 ++++++++++++------- kernel/sched.c | 2 +- mm/page_alloc.c | 16 ++++++++++------ 5 files changed, 25 insertions(+), 16 deletions(-)
Documentation/vm/numa +1 -1
@@ -29,7 +29,7 @@ into a pg_data_t. The bootmem_data_t is just one part of this. To make the code look uniform between NUMA and regular UMA platforms, UMA platforms have a statically allocated pg_data_t too (contig_page_data). -For the sake of uniformity, the variable "numnodes" is also defined +For the sake of uniformity, the variable "node_online_map" is also defined for all platforms. As we run benchmarks, we might decide to NUMAize more variables like low_on_memory, nr_free_pages etc into the pg_data_t.
include/linux/gfp.h +1 -1
@@ -58,7 +58,7 @@/* * We get the zone list from the current node and the gfp_mask. -* This zone list contains a maximum of MAXNODES*MAX_NR_ZONES zones. +* This zone list contains a maximum of MAX_NUMNODES*MAX_NR_ZONES zones. * * For the normal case of non-DISCONTIGMEM systems the NODE_DATA() gets * optimized to &contig_page_data at compile-time.
include/linux/topology.h +12 -7
@@ -43,15 +43,20 @@ })#endif -static inline int __next_node_with_cpus (int node) +static inline int __next_node_with_cpus (int last_node) { -do - ++node; -while (node < numnodes && !nr_cpus_node (node)); -return node; +int nid; +for_each_online_node (nid) +if (nr_cpus_node (nid) && nid > last_node) +return nid; + +return MAX_NUMNODES ; } -#define for_each_node_with_cpus (node) \ - for (node = 0; node < numnodes; node = __next_node_with_cpus(node)) +/* Assumes first_node(node_online_map) will have CPUs */ +#define for_each_node_with_cpus (node) \ + for(node = first_node(node_online_map); \ + node < MAX_NUMNODES; \ + node = __next_node_with_cpus(node))#endif /* _LINUX_TOPOLOGY_H */
kernel/sched.c +1 -1
@@ -1088,7 +1088,7 @@ {int new_cpu; -if (numnodes >1 ) { +if (num_online_nodes () >1 ) { new_cpu =sched_best_cpu (current);if (new_cpu !=smp_processor_id ())sched_migrate_task (current, new_cpu);
mm/page_alloc.c +10 -6
@@ -34,12 +34,12 @@#include <asm/tlbflush.h> -DECLARE_BITMAP (node_online_map,MAX_NUMNODES ); +nodemask_t node_online_map =NODE_MASK_NONE ; +nodemask_t node_possible_map =NODE_MASK_ALL ;struct pglist_data *pgdat_list;unsigned long totalram_pages;unsigned long totalhigh_pages;int nr_swap_pages; -int numnodes =1 ;int sysctl_lower_zone_protection =0 ;EXPORT_SYMBOL (totalram_pages);
@@ -1115,9 +1115,13 @@* zones coming right after the local ones are those from * node N+1 (modulo N) */ -for (node = local_node +1 ; node < numnodes; node++) +for (node =next_node (local_node, node_online_map); + node <MAX_NUMNODES ; + node =next_node (node, node_online_map)) j =build_zonelists_node (NODE_DATA (node), zonelist, j, k); -for (node =0 ; node < local_node; node++) +for (node =first_node (node_online_map); + node < local_node; + node =next_node (node, node_online_map)) j =build_zonelists_node (NODE_DATA (node), zonelist, j, k); zonelist->zones[j++] =NULL ;
@@ -1128,9 +1132,9 @@ {int i; -for (i =0 ; i < numnodes ; i++) +for_each_online_node (i)build_zonelists (NODE_DATA (i)); -printk ("Built %i zonelists\n" , numnodes); +printk ("Built %i zonelists\n" ,num_online_nodes ()); }/*
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 14/23 mask v2 - [3/7] nodemask_t_i386_changes
In reply to Paul JacksonPatch_14_of_23 - Matthew Dobson's [PATCH]_nodemask_t_i386_changes_[3_7]
Changes to i386 specific code. As with most arch changes, it involves close-coding loops (ie: for_each_online_node(nid) rather than for(nid=0;nid<numnodes;nid++)) and replacing the use of numnodes with num_online_nodes() and node_set_online(nid).
Diffstat Patch_14_of_23:
arch/i386/kernel/mpparse.c | 4 ++-- arch/i386/kernel/numaq.c | 10 ++++------ arch/i386/kernel/smpboot.c | 2 +- arch/i386/kernel/srat.c | 23 +++++++++++------------ arch/i386/mm/discontig.c | 17 ++++++++--------- arch/i386/mm/hugetlbpage.c | 8 ++++---- arch/i386/pci/numa.c | 11 ++++------- include/asm-i386/mach-numaq/mach_apic.h | 10 ++++++---- 8 files changed, 40 insertions(+), 45 deletions(-)
arch/i386/kernel/mpparse.c +2 -2
@@ -287,8 +287,8 @@printk (KERN_ERR "MAX_MPC_ENTRY exceeded!\n" ); else translation_table[mpc_record] = m;/* stash this for later */ -if (m->trans_quad+1 > numnodes) - numnodes = m->trans_quad+1 ; +if (m->trans_quad+1 >num_online_nodes ()) +node_set_online (m->trans_quad); }/*
arch/i386/kernel/numaq.c +4 -6
@@ -39,8 +39,7 @@* Function: smp_dump_qct() * * Description: gets memory layout from the quad config table. This -* function also increments numnodes with the number of nodes (quads) -* present. +* function also updates node_online_map with the nodes (quads) present. */ static void __init smp_dump_qct (void ) {
@@ -49,11 +48,10 @@struct sys_cfg_data *scd = (struct sys_cfg_data *)__va (SYS_CFG_DATA_PRIV_ADDR ); - numnodes =0 ; -for (node =0 ; node <MAX_NUMNODES ; node++) { +nodes_clear (node_online_map); +for_each_node (node) {if (scd->quads_present31_0 & (1 << node)) {node_set_online (node); - numnodes++; eq = &scd->eq[node];/* Convert to pages */ node_start_pfn[node] = MB_TO_PAGES(
@@ -86,7 +84,7 @@ (struct sys_cfg_data *)__va (SYS_CFG_DATA_PRIV_ADDR ); -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {if (scd->quads_present31_0 & (1 << nid)) { eq = &scd->eq[nid]; cur = eq->hi_shrd_mem_start;
arch/i386/kernel/smpboot.c +1 -1
@@ -520,7 +520,7 @@int node;printk ("Unmapping cpu %d from all nodes\n" , cpu); -for (node =0 ; node <MAX_NUMNODES ; node ++) +for_each_node (node)cpu_clear (cpu, node_2_cpu_mask[node]); cpu_2_node[cpu] =-1 ; }
arch/i386/kernel/srat.c +11 -12
@@ -248,17 +248,16 @@* a set of sequential node IDs starting at zero. (ACPI doesn't seem * to specify the range of _PXM values.) */ - numnodes =0 ;/* init total nodes in system */ +nodes_clear (node_online_map);/* init total nodes in system */ for (i =0 ; i <MAX_PXM_DOMAINS ; i++) {if (BMAP_TEST (pxm_bitmap, i)) { - pxm_to_nid_map[i] = numnodes; - nid_to_pxm_map[numnodes] = i; -node_set_online (numnodes); - ++numnodes; + pxm_to_nid_map[i] =num_online_nodes (); + nid_to_pxm_map[num_online_nodes ()] = i; +node_set_online (num_online_nodes ()); } } -if (numnodes ==0 ) +if (num_online_nodes () ==0 )BUG ();/* set cnode id in memory chunk structure */
@@ -272,7 +271,7 @@printk ("%02X " , pxm_bitmap[i]); }printk ("\n" ); -printk ("Number of logical nodes in system = %d\n" , numnodes); +printk ("Number of logical nodes in system = %d\n" ,num_online_nodes ());printk ("Number of memory chunks in system = %d\n" , num_memory_chunks);for (j =0 ; j < num_memory_chunks; j++){
@@ -283,7 +282,7 @@ }/*calculate node_start_pfn/node_end_pfn arrays*/ -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {int been_here_before =0 ;for (j =0 ; j < num_memory_chunks; j++){
@@ -415,7 +414,7 @@int first;unsigned long end =0 ; -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) { first =1 ;for (c =0 ; c < num_memory_chunks; c++){if (node_memory_chunk[c].nid == nid) {
@@ -443,8 +442,8 @@ zholes_size_init++;get_zholes_init (); } -if ((nid >= numnodes) | (nid >=MAX_NUMNODES )) -printk ("%s: nid = %d is invalid. numnodes = %d" , - __FUNCTION__, nid, numnodes); +if (!node_online (nid)) +printk ("%s: nid = %d is invalid. num_online_nodes() = %d" , + __FUNCTION__, nid,num_online_nodes ());return &zholes_size[nid *MAX_NR_ZONES ]; }
arch/i386/mm/discontig.c +8 -9
@@ -39,7 +39,7 @@* numa interface - we expect the numa architecture specfic code to have * populated the following initialisation. * -* 1) numnodes - the total number of nodes configured in the system +* 1) node_online_map - the bitmap of nodes configured in the system * 2) physnode_map - the mapping between a pfn and owning node * 3) node_start_pfn - the starting page frame number for a node * 3) node_end_pfn - the ending page fram number for a node
@@ -107,7 +107,6 @@/* Indicate there is one node available. */ node_set_online (0 ); - numnodes =1 ;return 1 ; }
@@ -189,7 +188,7 @@unsigned long pfn;int node; -for (node =1 ; node < numnodes; ++node) { +for (node =1 ; node <num_online_nodes (); node++) {for (pfn=0 ; pfn < node_remap_size[node]; pfn +=PTRS_PER_PTE ) { vaddr = node_remap_start_vaddr[node]+(pfn<<PAGE_SHIFT ); set_pmd_pfn((ulong) vaddr,
@@ -204,7 +203,7 @@int nid;unsigned long size, reserve_pages =0 ; -for (nid =1 ; nid < numnodes; nid++) { +for (nid =1 ; nid <num_online_nodes (); nid++) {/* calculate the size of the mem_map needed in bytes */ size = (node_end_pfn[nid] - node_start_pfn[nid] +1 ) *sizeof (struct page ) +sizeof (pg_data_t);
@@ -256,7 +255,7 @@printk ("Low memory ends at vaddr %08lx\n" , (ulong )pfn_to_kaddr (max_low_pfn)); -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) { node_remap_start_vaddr[nid] =pfn_to_kaddr ( highstart_pfn - node_remap_offset[nid]);allocate_pgdat (nid);
@@ -267,7 +266,7 @@ }printk ("High memory starts at vaddr %08lx\n" , (ulong )pfn_to_kaddr (highstart_pfn)); -for (nid =0 ; nid < numnodes; nid++) +for_each_online_node (nid)find_max_pfn_node (nid);NODE_DATA (0 )->bdata = &node0_bdata;
@@ -342,14 +341,14 @@* Clobber node 0's links and NULL out pgdat_list before starting. */ pgdat_list =NULL ; -for (nid = numnodes -1 ; nid >=0 ; nid--) { +for (nid =num_online_nodes () -1 ; nid >=0 ; nid--) {if (nid)memset (NODE_DATA (nid),0 ,sizeof (pg_data_t));NODE_DATA (nid)->pgdat_next = pgdat_list; pgdat_list =NODE_DATA (nid); } -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {unsigned long zones_size[MAX_NR_ZONES ] = {0 ,0 ,0 };unsigned long *zholes_size;unsigned int max_dma;
@@ -405,7 +404,7 @@#ifdef CONFIG_HIGHMEM int nid; -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {unsigned long node_pfn, node_high_size, zone_start_pfn;struct page * zone_mem_map;
arch/i386/mm/hugetlbpage.c +4 -4
@@ -39,11 +39,11 @@struct page *page =NULL ;if (list_empty (&hugepage_freelists[nid])) { -for (nid =0 ; nid <MAX_NUMNODES ; ++nid) +for_each_node (nid)if (!list_empty (&hugepage_freelists[nid]))break ; } -if (nid >=0 && nid <MAX_NUMNODES && !list_empty (&hugepage_freelists[nid])) { +if (node_possible (nid) && !list_empty (&hugepage_freelists[nid])) { page = list_entry(hugepage_freelists[nid].next, struct page, list);list_del (&page->list); }
@@ -55,7 +55,7 @@static int nid =0 ;struct page *page; page =alloc_pages_node (nid,GFP_HIGHUSER ,HUGETLB_PAGE_ORDER ); - nid = (nid +1 ) % numnodes; + nid = (nid +1 ) %num_online_nodes ();return page; }
@@ -494,7 +494,7 @@if (!cpu_has_pse)return -ENODEV ; -for (i =0 ; i <MAX_NUMNODES ; ++i) +for_each_node (i)INIT_LIST_HEAD (&hugepage_freelists[i]);for (i =0 ; i < htlbpage_max; ++i) {
arch/i386/pci/numa.c +4 -7
@@ -115,13 +115,10 @@return 0 ; pci_root_bus =pcibios_scan_root (0 ); -if (numnodes >1 ) { -for (quad =1 ; quad < numnodes; ++quad) { -printk ("Scanning PCI bus %d for quad %d\n" , -QUADLOCAL2BUS (quad,0 ), quad); -pci_scan_bus (QUADLOCAL2BUS (quad,0 ), - &pci_root_ops,NULL ); - } +for (quad =1 ; quad <num_online_nodes (); quad++) { +printk ("Scanning PCI bus %d for quad %d\n" , +QUADLOCAL2BUS (quad,0 ), quad); +pci_scan_bus (QUADLOCAL2BUS (quad,0 ), &pci_root_ops,NULL ); }return 0 ; }
include/asm-i386/mach-numaq/mach_apic.h +6 -4
@@ -114,13 +114,15 @@static inline void setup_portio_remap (void ) { -if (numnodes <=1 ) +int num_nodes =num_online_nodes (); + +if (num_nodes <=1 )return ; -printk ("Remapping cross-quad port I/O for %d quads\n" , numnodes); - xquad_portio =ioremap (XQUAD_PORTIO_BASE , numnodes*XQUAD_PORTIO_QUAD ); +printk ("Remapping cross-quad port I/O for %d quads\n" , num_nodes); + xquad_portio =ioremap (XQUAD_PORTIO_BASE , num_nodes*XQUAD_PORTIO_QUAD );printk ("xquad_portio vaddr 0x%08lx, len %08lx\n" , - (u_long ) xquad_portio, (u_long ) numnodes*XQUAD_PORTIO_QUAD ); + (u_long ) xquad_portio, (u_long ) num_nodes*XQUAD_PORTIO_QUAD ); }static inline int check_phys_apicid_present (int boot_cpu_physical_apicid)
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 15/23 mask v2 - [4/7] nodemask_t_pp64_changes
In reply to Paul JacksonPatch_15_of_23 - Matthew Dobson's [PATCH]_nodemask_t_pp64_changes_[4_7]
Changes to ppc64 specific code. Untested.
Code review & testing requested.
Diffstat Patch_15_of_23:
kernel/smp.c | 20 +++++++++----------- mm/hugetlbpage.c | 10 +++++----- mm/init.c | 2 +- mm/numa.c | 17 +++++------------ 4 files changed, 20 insertions(+), 29 deletions(-)
arch/ppc64/kernel/smp.c +9 -11
@@ -737,19 +737,17 @@ static void register_nodes(void)int i;int ret; -for (i =0 ; i <MAX_NUMNODES ; i++) { -if (node_online (i)) { -int p_node =parent_node (i); -struct node *parent =NULL ; +for_each_online_node (i) { +int p_node =parent_node (i); +struct node *parent =NULL ; -if (p_node != i) - parent = &node_devices[p_node]; +if (p_node != i) + parent = &node_devices[p_node]; - ret =register_node (&node_devices[i], i, parent); -if (ret) -printk (KERN_WARNING "register_nodes: " -"register_node %d failed (%d)" , i, ret); - } + ret =register_node (&node_devices[i], i, parent); +if (ret) +printk (KERN_WARNING "register_nodes: " +"register_node %d failed (%d)" , i, ret); } }#else
arch/ppc64/mm/hugetlbpage.c +5 -5
@@ -56,10 +56,10 @@ static struct page *dequeue_huge_page(voif (!largepage_roundrobin) nid =numa_node_id (); -for (i =0 ; i < numnodes; i++) { +for_each_online_node (i) {if (!list_empty (&hugepage_freelists[nid]))break ; - nid = (nid +1 ) % numnodes; + nid = (nid +1 ) %num_online_nodes (); }if (!list_empty (&hugepage_freelists[nid])) {
@@ -68,7 +68,7 @@ static struct page *dequeue_huge_page(vo }if (largepage_roundrobin) - nid = (nid +1 ) % numnodes; + nid = (nid +1 ) %num_online_nodes ();return page; }
@@ -83,7 +83,7 @@ static struct page *alloc_fresh_huge_pagreturn NULL ; nid =page_zone (page)->zone_pgdat->node_id; - nid = (nid +1 ) % numnodes; + nid = (nid +1 ) %num_online_nodes ();return page; }
@@ -871,7 +871,7 @@ static int __init hugetlb_init(void)struct page *page;if (cur_cpu_spec->cpu_features &CPU_FTR_16M_PAGE ) { -for (i =0 ; i <MAX_NUMNODES ; ++i) +for_each_node (i)INIT_LIST_HEAD (&hugepage_freelists[i]);for (i =0 ; i < htlbpage_max; ++i) {
arch/ppc64/mm/init.c +1 -1
@@ -639,7 +639,7 @@ void __init mem_init(void) {int nid; -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {if (node_data[nid].node_spanned_pages !=0 ) {printk ("freeing bootmem node %x\n" , nid); totalram_pages +=
arch/ppc64/mm/numa.c +5 -12
@@ -55,7 +55,6 @@ static int __init parse_numa_properties(int *cpu_associativity;int *memory_associativity;int depth; -int max_domain =0 ; cpu =of_find_node_by_type (NULL ,"cpu" );if (!cpu)
@@ -101,14 +100,11 @@ static int __init parse_numa_properties( numa_domain =0 ; } -if (numa_domain >=MAX_NUMNODES ) +if (!node_possible (numa_domain))BUG ();node_set_online (numa_domain); -if (max_domain < numa_domain) - max_domain = numa_domain; -map_cpu_to_node (cpu_nr, numa_domain); }
@@ -157,11 +153,10 @@ new_range: numa_domain =0 ; } -if (numa_domain >=MAX_NUMNODES ) +if (!node_possible (numa_domain))BUG (); -if (max_domain < numa_domain) - max_domain = numa_domain; +node_set_online (numa_domain);/* * For backwards compatibility, OF splits the first node
@@ -198,8 +193,6 @@ new_range: goto new_range; } - numnodes = max_domain +1 ; -return 0 ; err:of_node_put (cpu);
@@ -242,7 +235,7 @@ void __init do_init_bootmem(void)if (parse_numa_properties ())setup_nonnuma (); -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {unsigned long start_paddr, end_paddr;int i;unsigned long bootmem_paddr;
@@ -329,7 +322,7 @@ void __init paging_init(void)memset (zones_size,0 ,sizeof (zones_size));memset (zholes_size,0 ,sizeof (zholes_size)); -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {unsigned long start_pfn;unsigned long end_pfn;
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 16/23 mask v2 - [5/7] nodemask_t_x86_64_changes
In reply to Paul JacksonPatch_16_of_23 - Matthew Dobson's [PATCH]_nodemask_t_x86_64_changes_[5_7]
Changes to x86_64 specific code.
Untested. Code review & testing requested.
Diffstat Patch_16_of_23:
arch/x86_64/kernel/setup64.c | 6 +++--- arch/x86_64/mm/k8topology.c | 32 +++++++++++++++++--------------- arch/x86_64/mm/numa.c | 16 ++++++---------- include/asm-x86_64/mmzone.h | 1 - include/asm-x86_64/numa.h | 6 ------ 5 files changed, 26 insertions(+), 35 deletions(-)
arch/x86_64/kernel/setup64.c +3 -3
@@ -135,11 +135,11 @@ void __init setup_per_cpu_areas(void)unsigned char *ptr;/* If possible allocate on the node of the CPU. In case it doesn't exist round-robin nodes. */ -if (!NODE_DATA (i % numnodes)) { -printk ("cpu with no node %d, numnodes %d\n" , i, numnodes); +if (!NODE_DATA (i %num_online_nodes ())) { +printk ("cpu with no node %d, num_online_nodes() %d\n" , i,num_online_nodes ()); ptr =alloc_bootmem (size); }else { - ptr =alloc_bootmem_node (NODE_DATA (i % numnodes), size); + ptr =alloc_bootmem_node (NODE_DATA (i %num_online_nodes ()), size); }if (!ptr)panic ("Cannot allocate cpu data for CPU %d\n" , i);
arch/x86_64/mm/k8topology.c +17 -15
@@ -44,7 +44,7 @@ static __init int find_northbridge(void)int __init k8_scan_nodes (unsigned long start,unsigned long end) {unsigned long prevbase; -struct node nodes[MAXNODE ]; +struct node nodes[MAX_NUMNODES ];int nodeid, i, nb;int found =0 ;u32 reg;
@@ -57,9 +57,10 @@ int __init k8_scan_nodes(unsigned long sprintk (KERN_INFO "Scanning NUMA topology in Northbridge %d\n" , nb); reg =read_pci_config (0 , nb,0 ,0x60 ); - numnodes = ((reg >>4 ) &7 ) +1 ; +for (i =0 ; i <= ((reg >>4 ) &7 ); i++) +node_set_online (i); -printk (KERN_INFO "Number of nodes %d (%x)\n" , numnodes, reg); +printk (KERN_INFO "Number of nodes %d (%x)\n" ,num_online_nodes (), reg);memset (&nodes,0 ,sizeof (nodes)); prevbase =0 ;
@@ -71,11 +72,11 @@ int __init k8_scan_nodes(unsigned long s nodeid = limit &7 ;if ((base &3 ) ==0 ) { -if (i < numnodes) +if (i <num_online_nodes ())printk ("Skipping disabled node %d\n" , i);continue ; } -if (nodeid >= numnodes) { +if (nodeid >=num_online_nodes ()) {printk ("Ignoring excess node %d (%lx:%lx)\n" , nodeid, base, limit);continue ;
@@ -91,7 +92,7 @@ int __init k8_scan_nodes(unsigned long s nodeid, (base>>8)&3, (limit>>8) & 3);return -1 ; } -if ((1UL << nodeid) & nodes_present) { +if (node_online (nodeid)) {printk (KERN_INFO "Node %d already present. Skipping\n" , nodeid);continue ;
@@ -151,7 +152,7 @@ int __init k8_scan_nodes(unsigned long s }printk (KERN_INFO "Using node hash shift of %d\n" , memnode_shift); -for (i =0 ; i <MAXNODE ; i++) { +for_each_node (i) {if (nodes[i].start != nodes[i].end)setup_node_bootmem (i, nodes[i].start, nodes[i].end); }
@@ -161,15 +162,16 @@ int __init k8_scan_nodes(unsigned long smapping. To avoid this fill in the mapping for all possible CPUs, as the number of CPUs is not known yet. We round robin the existing nodes. */ - rr =0 ; -for (i =0 ; i <MAXNODE ; i++) { -if (nodes_present & (1UL <<i)) -continue ; -if ((nodes_present >> rr) ==0 ) - rr =0 ; - rr =ffz (~nodes_present >> rr); + rr =first_node (node_online_map); +for_each_node (i) { +if (node_online (i)) +continue ; + node_data[i] = node_data[rr]; - rr++; + + rr =next_node (rr, node_online_map); +if (rr >=MAX_NUMNODES ) + rr =first_node (node_online_map); }if (found ==1 )
arch/x86_64/mm/numa.c +6 -10
@@ -16,7 +16,7 @@ #define Dprintk(x...) -struct pglist_data *node_data[MAXNODE ]; +struct pglist_data *node_data[MAX_NUMNODES ];bootmem_data_t plat_node_bdata[MAX_NUMNODES ];int memnode_shift;
@@ -24,8 +24,6 @@ u8 memnodemap[NODEMAPSIZE];static int numa_off__initdata ; -unsigned long nodes_present; -int __init compute_hash_shift (struct node *nodes) {int i;
@@ -35,7 +33,7 @@ int __init compute_hash_shift(struct nod/* When in doubt use brute force. */ while (shift <48 ) {memset (memnodemap,0xff ,sizeof (*memnodemap) *NODEMAPSIZE ); -for (i =0 ; i < numnodes; i++) { +for_each_online_node (i) {if (nodes[i].start == nodes[i].end)continue ; for (addr = nodes[i].start;
@@ -101,9 +99,6 @@ void __init setup_node_bootmem(int nodeireserve_bootmem_node (NODE_DATA (nodeid), nodedata_phys, pgdat_size);reserve_bootmem_node (NODE_DATA (nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT ); -if (nodeid +1 > numnodes) - numnodes = nodeid +1 ; - nodes_present |= (1UL << nodeid);node_set_online (nodeid); }
@@ -152,7 +147,8 @@ int __init numa_initmem_init(unsigned lo fake_node =1 ; memnode_shift =63 ; memnodemap[0 ] =0 ; - numnodes =1 ; +nodes_clear (node_online_map); +node_set_online (0 );setup_node_bootmem (0 , start_pfn<<PAGE_SHIFT , end_pfn<<PAGE_SHIFT );return -1 ; }
@@ -161,7 +157,7 @@ unsigned long __init numa_free_all_bootm {int i;unsigned long pages =0 ; -for_all_nodes (i) { +for_each_online_node (i) { pages +=free_all_bootmem_node (NODE_DATA (i)); }return pages;
@@ -170,7 +166,7 @@ unsigned long __init numa_free_all_bootmvoid __init paging_init (void ) {int i; -for_all_nodes (i) { +for_each_online_node (i) {setup_node_zones (i); } }
include/asm-x86_64/mmzone.h +0 -1
@@ -12,7 +12,6 @@#include <asm/smp.h> -#define MAXNODE 8#define NODEMAPSIZE 0xff/* Simple perfect hash to map physical addresses to node numbers */
include/asm-x86_64/numa.h +0 -6
@@ -1,19 +1,13 @@#ifndef _ASM_X8664_NUMA_H#define _ASM_X8664_NUMA_H 1 -#define MAXNODE 8#define NODEMASK 0xffstruct node {u64 start,end; }; -#define for_all_nodes (x) for ((x) = 0; (x) < numnodes; (x)++) \ - if ((1UL << (x)) & nodes_present) - -extern int compute_hash_shift (struct node *nodes); -extern unsigned long nodes_present;#define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 17/23 mask v2 = [6/7] nodemask_t_ia64_changes
In reply to Paul JacksonPatch_17_of_23 - Matthew Dobson's [PATCH]_nodemask_t_ia64_changes_[6_7]
Changes to ia64 specific code.
Diffstat Patch_17_of_23:
arch/ia64/kernel/acpi.c | 15 +++++---- arch/ia64/kernel/smpboot.c | 2 - arch/ia64/mm/discontig.c | 48 ++++++++++++++++--------------- arch/ia64/mm/hugetlbpage.c | 9 ++--- arch/ia64/mm/numa.c | 6 +-- arch/ia64/sn/fakeprom/fpmem.c | 8 ++--- arch/ia64/sn/io/machvec/pci_bus_cvlink.c | 3 - arch/ia64/sn/io/sn2/klconflib.c | 4 +- arch/ia64/sn/io/sn2/klgraph.c | 4 +- arch/ia64/sn/io/sn2/ml_SN_init.c | 2 - arch/ia64/sn/io/sn2/ml_SN_intr.c | 4 +- arch/ia64/sn/io/sn2/ml_iograph.c | 2 - arch/ia64/sn/io/sn2/module.c | 4 +- arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c | 4 +- arch/ia64/sn/io/sn2/shub.c | 18 +++++++---- arch/ia64/sn/kernel/setup.c | 12 +++---- arch/ia64/sn/kernel/sn2/prominfo_proc.c | 16 +++++----- arch/ia64/sn/kernel/sn2/sn2_smp.c | 2 - include/asm-ia64/numa.h | 2 - include/asm-ia64/sn/sn2/sn_private.h | 2 - 20 files changed, 86 insertions(+), 81 deletions(-)
arch/ia64/kernel/acpi.c +8 -7
@@ -450,14 +450,15 @@ acpi_numa_arch_fixup (void) }/* calculate total number of nodes in system from PXM bitmap */ - numnodes =0 ;/* init total nodes in system */ +nodes_clear (node_online_map);/* init total nodes in system */ memset (pxm_to_nid_map,-1 ,sizeof (pxm_to_nid_map));memset (nid_to_pxm_map,-1 ,sizeof (nid_to_pxm_map));for (i =0 ; i <MAX_PXM_DOMAINS ; i++) {if (pxm_bit_test (i)) { - pxm_to_nid_map[i] = numnodes; - nid_to_pxm_map[numnodes++] = i; + pxm_to_nid_map[i] =num_online_nodes (); + nid_to_pxm_map[num_online_nodes ()] = i; +node_set_online (num_online_nodes ()); } }
@@ -466,7 +467,7 @@ acpi_numa_arch_fixup (void) node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid];/* assign memory bank numbers for each chunk on each node */ -for (i =0 ; i < numnodes; i++) { +for_each_online_node (i) {int bank; bank =0 ;
@@ -479,7 +480,7 @@ acpi_numa_arch_fixup (void)for (i =0 ; i < srat_num_cpus; i++) node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid]; -printk (KERN_INFO "Number of logical nodes in system = %d\n" , numnodes); +printk (KERN_INFO "Number of logical nodes in system = %d\n" ,num_online_nodes ());printk (KERN_INFO "Number of memory chunks in system = %d\n" , num_node_memblks);if (!slit_table)return ;
@@ -499,8 +500,8 @@ acpi_numa_arch_fixup (void)#ifdef SLIT_DEBUG printk ("ACPI 2.0 SLIT locality table:\n" ); -for (i =0 ; i < numnodes; i++) { -for (j =0 ; j < numnodes; j++) +for_each_online_node (i) { +for_each_online_node (j)printk ("%03d " ,node_distance (i,j));printk ("\n" ); }
arch/ia64/kernel/smpboot.c +1 -1
@@ -474,7 +474,7 @@ build_cpu_to_node_map (void) {int cpu, i, node; -for (node=0 ; node<MAX_NUMNODES ; node++) +for_each_node (node)cpus_clear (node_to_cpu_mask[node]);for (cpu =0 ; cpu <NR_CPUS ; ++cpu) {/*
arch/ia64/mm/discontig.c +26 -22
144 lines not on this page · raw message
arch/ia64/mm/hugetlbpage.c +4 -5
@@ -42,12 +42,11 @@ static struct page *dequeue_huge_page(vostruct page *page =NULL ;if (list_empty (&hugepage_freelists[nid])) { -for (nid =0 ; nid <MAX_NUMNODES ; ++nid) +for_each_node (nid)if (!list_empty (&hugepage_freelists[nid]))break ; } -if (nid >=0 && nid <MAX_NUMNODES && - !list_empty (&hugepage_freelists[nid])) { +if (node_possible (nid) && !list_empty (&hugepage_freelists[nid])) { page = list_entry(hugepage_freelists[nid].next, struct page, list);list_del (&page->list); }
@@ -59,7 +58,7 @@ static struct page *alloc_fresh_huge_pagstatic int nid =0 ;struct page *page; page =alloc_pages_node (nid,GFP_HIGHUSER ,HUGETLB_PAGE_ORDER ); - nid = (nid +1 ) % numnodes; + nid = (nid +1 ) %num_online_nodes ();return page; }
@@ -557,7 +556,7 @@ static int __init hugetlb_init(void)int i;struct page *page; -for (i =0 ; i <MAX_NUMNODES ; ++i) +for_each_node (i)INIT_LIST_HEAD (&hugepage_freelists[i]);for (i =0 ; i < htlbpage_max; ++i) {
arch/ia64/mm/numa.c +3 -3
@@ -54,12 +54,12 @@ static int __init topology_init(void) {int i, err =0 ; - sysfs_nodes =kmalloc (sizeof (struct node ) * numnodes,GFP_KERNEL ); + sysfs_nodes =kmalloc (sizeof (struct node ) *num_online_nodes (),GFP_KERNEL );if (!sysfs_nodes) { err = -ENOMEM ; goto out; } -memset (sysfs_nodes,0 ,sizeof (struct node ) * numnodes); +memset (sysfs_nodes,0 ,sizeof (struct node ) *num_online_nodes ()); sysfs_cpus =kmalloc (sizeof (struct cpu ) *NR_CPUS ,GFP_KERNEL );if (!sysfs_cpus) {
@@ -69,7 +69,7 @@ static int __init topology_init(void) }memset (sysfs_cpus,0 ,sizeof (struct cpu ) *NR_CPUS ); -for (i =0 ; i < numnodes; i++) +for_each_online_node (i)if ((err =register_node (&sysfs_nodes[i], i,0 ))) goto out;
arch/ia64/sn/fakeprom/fpmem.c +4 -4
@@ -26,7 +26,7 @@* * 32 bit 32 bit * -* numnodes numcpus +* num_nodes numcpus * * 16 bit 16 bit 32 bit * nasid0 cpuconf membankdesc0
@@ -59,7 +59,7 @@ sn_config_t *sn_config ;#endif /* -* For SN, this may not take an arg and gets the numnodes from +* For SN, this may not take an arg and gets the num_nodes from * the prom variable or by traversing klcfg or promcfg */ int
@@ -144,7 +144,7 @@ build_mem_desc(efi_memory_desc_t *md, inint build_efi_memmap (void *md,int mdsize) { -int numnodes =GetNumNodes () ; +int num_nodes =GetNumNodes () ;int cnode,bank ;int nasid ;node_memmap_t membank_info ;
@@ -153,7 +153,7 @@ build_efi_memmap(void *md, int mdsize)long paddr, hole, numbytes; -for (cnode=0 ;cnode<numnodes;cnode++) { +for (cnode=0 ; cnode<num_nodes; cnode++) { nasid =GetNasid (cnode) ; membank_info =GetMemBankInfo (cnode) ;for (bank=0 ;bank<MD_BANKS_PER_NODE ;bank++) {
arch/ia64/sn/io/machvec/pci_bus_cvlink.c +1 -2
@@ -791,7 +791,6 @@ sn_pci_init (void)struct list_head *ln;struct pci_bus *pci_bus =NULL ;struct pci_dev *pci_dev =NULL ; -extern int numnodes;int cnode, ret;#ifdef CONFIG_PROC_FS extern void register_sn_procfs (void );
@@ -814,7 +813,7 @@ sn_pci_init (void)sgi_master_io_infr_init (); -for (cnode =0 ; cnode < numnodes; cnode++) { +for_each_online_node (cnode) {extern void intr_init_vecblk (cnodeid_t );intr_init_vecblk (cnode); }
arch/ia64/sn/io/sn2/klconflib.c +2 -2
@@ -62,7 +62,7 @@ find_lboard_nasid(lboard_t *start, nasid (start->brd_nasid == nasid))return start; -if (numionodes == numnodes) +if (numionodes ==num_online_nodes ()) start =KLCF_NEXT_ANY (start);else start =KLCF_NEXT (start);
@@ -95,7 +95,7 @@ find_lboard_class_nasid(lboard_t *start, (start->brd_nasid == nasid))return start; -if (numionodes == numnodes) +if (numionodes ==num_online_nodes ()) start =KLCF_NEXT_ANY (start);else start =KLCF_NEXT (start);
arch/ia64/sn/io/sn2/klgraph.c +2 -2
@@ -279,7 +279,7 @@ klhwg_add_all_routers(vertex_hdl_t hwgrachar path_buffer[100 ];int rv; -for (cnode =0 ; cnode < numnodes; cnode++) { +for_each_online_node (cnode) { nasid =COMPACT_TO_NASID_NODEID (cnode); brd =find_lboard_class_any ((lboard_t *)KL_CONFIG_INFO (nasid),KLTYPE_ROUTER );
@@ -413,7 +413,7 @@ klhwg_connect_routers(vertex_hdl_t hwgracnodeid_t cnode;lboard_t *brd; -for (cnode =0 ; cnode < numnodes; cnode++) { +for_each_online_node (cnode) { nasid =COMPACT_TO_NASID_NODEID (cnode); brd =find_lboard_class_any ((lboard_t *)KL_CONFIG_INFO (nasid),KLTYPE_ROUTER );
arch/ia64/sn/io/sn2/ml_SN_init.c +1 -1
@@ -38,7 +38,7 @@ void init_platform_nodepda(nodepda_t *np/* Allocate per-node platform-dependent data */ nasid =COMPACT_TO_NASID_NODEID (node); -if (node >= numnodes)/* Headless/memless IO nodes */ +if (node >=num_online_nodes ())/* Headless/memless IO nodes */ hubinfo = (hubinfo_t )alloc_bootmem_node (NODE_DATA (0 ),sizeof (struct hubinfo_s ));else hubinfo = (hubinfo_t )alloc_bootmem_node (NODE_DATA (node),sizeof (struct hubinfo_s ));
arch/ia64/sn/io/sn2/ml_SN_intr.c +2 -2
@@ -256,12 +256,12 @@ static cpuid_t intr_cpu_choose_node(voidcnodeid_t candidate_node;cpuid_t cpuid; -if (last_node >= numnodes) +if (last_node >=num_online_nodes ()) last_node =0 ;for (candidate_node = last_node +1 ; candidate_node != last_node; candidate_node++) { -if (candidate_node == numnodes) +if (candidate_node ==num_online_nodes ()) candidate_node =0 ; cpuid =intr_cpu_choose_from_node (candidate_node);if (cpuid !=CPU_NONE )
arch/ia64/sn/io/sn2/ml_iograph.c +1 -1
@@ -680,7 +680,7 @@ init_all_devices(void)DBG ("init_all_devices: Done io_init_node() for cnode %d\n" , cnodeid); } -for (cnodeid =0 ; cnodeid < numnodes; cnodeid++) { +for_each_online_node (cnodeid) {/* * Update information generated by IO init. */
arch/ia64/sn/io/sn2/module.c +2 -2
@@ -195,7 +195,7 @@ io_module_init(void)* First pass just scan for compute node boards KLTYPE_SNIA. * We do not support memoryless compute nodes. */ -for (node =0 ; node < numnodes; node++) { +for_each_online_node (node) { nasid =COMPACT_TO_NASID_NODEID (node); board =find_lboard_nasid ((lboard_t *)KL_CONFIG_INFO (nasid), nasid,KLTYPE_SNIA );ASSERT (board);
@@ -210,7 +210,7 @@ io_module_init(void)/* * Second scan, look for headless/memless board hosted by compute nodes. */ -for (node = numnodes; node < numionodes; node++) { +for (node =num_online_nodes (); node < numionodes; node++) {nasid_t nasid;char serial_number[16 ];
arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c +2 -2
@@ -2639,7 +2639,7 @@ isIO9(nasid_t nasid)if (brd->brd_flags &LOCAL_MASTER_IO6 ) {return 1 ; } -if (numionodes == numnodes) +if (numionodes ==num_online_nodes ()) brd =KLCF_NEXT_ANY (brd);else brd =KLCF_NEXT (brd);
@@ -2652,7 +2652,7 @@ isIO9(nasid_t nasid)if (brd->brd_flags &LOCAL_MASTER_IO6 ) {return 1 ; } -if (numionodes == numnodes) +if (numionodes ==num_online_nodes ()) brd =KLCF_NEXT_ANY (brd);else brd =KLCF_NEXT (brd);
arch/ia64/sn/io/sn2/shub.c +11 -7
@@ -165,7 +165,7 @@ shubstats_ioctl(struct inode *inode, strint nasid; cnode = (cnodeid_t )file->f_dentry->d_fsdata; -if (cnode <0 || cnode >= numnodes) +if (cnode <0 || cnode >=num_online_nodes ())return -ENODEV ;switch (cmd) {
@@ -239,8 +239,8 @@ sn_linkstats_reset(unsigned long msecs)uint64_t llp_csr_reg;spin_lock (&sn_linkstats_lock); -memset (sn_linkstats,0 , numnodes *sizeof (struct s_linkstats )); -for (cnode=0 ; cnode < numnodes; cnode++) { +memset (sn_linkstats,0 ,num_online_nodes () *sizeof (struct s_linkstats )); +for_each_online_node (cnode) {shub_mmr_write (cnode,SH_NI0_LLP_ERR ,0L );shub_mmr_write (cnode,SH_NI1_LLP_ERR ,0L );shub_mmr_write_iospace (cnode,IIO_LLP_LOG ,0L );
@@ -286,7 +286,8 @@ linkstatd_thread(void *unused)spin_lock (&sn_linkstats_lock); overflows =0 ; -for (lsp=sn_linkstats, cnode=0 ; cnode < numnodes; cnode++, lsp++) { + lsp = sn_linkstats; +for_each_online_node (cnode) { reg[0 ] =shub_mmr_read (cnode,SH_NI0_LLP_ERR ); reg[1 ] =shub_mmr_read (cnode,SH_NI1_LLP_ERR );if (lsp->hs_ii_up) {
@@ -349,6 +350,7 @@ linkstatd_thread(void *unused) iio_wstat &=0xffffffffff00ffff ;/* bits 23:16 */ shub_mmr_write_iospace (cnode,IIO_WSTAT , iio_wstat); } + lsp++; } sn_linkstats_samples++;
@@ -401,7 +403,8 @@ sn_linkstats_get(char *page) n +=sprintf (page+n,"%-37s %8s %8s %8s %8s\n" ,"# Numalink" ,"sn errs" ,"cb errs" ,"cb/min" ,"retries" ); -for (lsp=sn_linkstats, cnode=0 ; cnode < numnodes; cnode++, lsp++) { + lsp = sn_linkstats; +for_each_online_node (cnode) { npda =NODEPDA (cnode);/* two NL links on each SHub */
@@ -411,7 +414,7 @@ sn_linkstats_get(char *page) retrysum += lsp->hs_ni_retry_errors[nlport];/* avoid buffer overrun (should be using seq_read API) */ -if (numnodes >64 ) +if (num_online_nodes () >64 )continue ; n += sprintf(page + n, "/%s/link/%d %8lu %8lu %8s %8lu\n",
@@ -432,6 +435,7 @@ sn_linkstats_get(char *page) cbsum_ii += lsp->hs_ii_cb_errors; retrysum_ii += lsp->hs_ii_retry_errors; } + lsp++; } n += sprintf(page + n, "%-37s %8lu %8lu %8s %8lu\n",
@@ -454,7 +458,7 @@ linkstatd_init(void)return -ENODEV ;spin_lock_init (&sn_linkstats_lock); - sn_linkstats =kmalloc (numnodes *sizeof (struct s_linkstats ),GFP_KERNEL ); + sn_linkstats =kmalloc (num_online_nodes () *sizeof (struct s_linkstats ),GFP_KERNEL );sn_linkstats_reset (60000UL );/* default 60 second update interval */ kernel_thread (linkstatd_thread,NULL ,CLONE_KERNEL );
arch/ia64/sn/kernel/setup.c +6 -6
@@ -224,7 +224,7 @@ sn_check_for_wars(void) {int cnode; -for (cnode=0 ; cnode< numnodes; cnode++) +for_each_online_node (cnode)if (is_shub_1_1 (cnodeid_to_nasid (cnode))) shub_1_1_found =1 ; }
@@ -372,16 +372,16 @@ sn_init_pdas(char **cmdline_p)panic ("overflow of cpu_data page" );memset (pda->cnodeid_to_nasid_table,-1 ,sizeof (pda->cnodeid_to_nasid_table)); -for (cnode=0 ; cnode<numnodes; cnode++) +for_each_online_node (cnode) pda->cnodeid_to_nasid_table[cnode] =pxm_to_nasid (nid_to_pxm_map[cnode]); - numionodes = numnodes; + numionodes =num_online_nodes ();scan_for_ionodes ();/* * Allocate & initalize the nodepda for each node. */ -for (cnode=0 ; cnode < numnodes; cnode++) { +for_each_online_node (cnode) { nodepdaindr[cnode] =alloc_bootmem_node (NODE_DATA (cnode),sizeof (nodepda_t));memset (nodepdaindr[cnode],0 ,sizeof (nodepda_t)); }
@@ -398,7 +398,7 @@ sn_init_pdas(char **cmdline_p)* The following routine actually sets up the hubinfo struct * in nodepda. */ -for (cnode =0 ; cnode < numnodes; cnode++) { +for_each_online_node (cnode) {init_platform_nodepda (nodepdaindr[cnode], cnode);bte_init_node (nodepdaindr[cnode], cnode); }
@@ -486,7 +486,7 @@ sn_cpu_init(void)if (nodepda->node_first_cpu == cpuid) {int buddy_nasid; - buddy_nasid =cnodeid_to_nasid (numa_node_id () == numnodes-1 ?0 :numa_node_id ()+1 ); + buddy_nasid =cnodeid_to_nasid (numa_node_id () ==num_online_nodes ()-1 ?0 :numa_node_id ()+1 ); pda->pio_shub_war_cam_addr = (volatile unsigned long *)GLOBAL_MMR_ADDR (nasid,SH_PI_CAM_CONTROL ); }
arch/ia64/sn/kernel/sn2/prominfo_proc.c +8 -8
@@ -320,16 +320,15 @@ prominfo_init(void)TRACE ();DPRINTK ("running on cpu %d\n" ,smp_processor_id ()); -DPRINTK ("numnodes %d\n" , numnodes); +DPRINTK ("num_online_nodes() %d\n" ,num_online_nodes ()); - proc_entries =kmalloc (numnodes *sizeof (struct proc_dir_entry *), + proc_entries =kmalloc (num_online_nodes () *sizeof (struct proc_dir_entry *),GFP_KERNEL ); sgi_prominfo_entry =proc_mkdir ("sgi_prominfo" ,NULL ); -for (cnodeid =0 , entp = proc_entries; - cnodeid < numnodes; - cnodeid++, entp++) { + entp = proc_entries; +for_each_online_node (cnodeid) {sprintf (name,"node%d" , cnodeid); *entp =proc_mkdir (name, sgi_prominfo_entry); nasid =cnodeid_to_nasid (cnodeid);
@@ -339,6 +338,7 @@ prominfo_init(void)create_proc_read_entry ("version" ,0 , *entp, read_version_entry,lookup_fit (nasid)); + entp++; }return 0 ;
@@ -353,13 +353,13 @@ prominfo_exit(void)TRACE (); -for (cnodeid =0 , entp = proc_entries; - cnodeid < numnodes; - cnodeid++, entp++) { + entp = proc_entries; +for_each_online_node (cnodeid) {remove_proc_entry ("fit" , *entp);remove_proc_entry ("version" , *entp);sprintf (name,"node%d" , cnodeid);remove_proc_entry (name, sgi_prominfo_entry); + entp++; }remove_proc_entry ("sgi_prominfo" ,NULL );kfree (proc_entries);
arch/ia64/sn/kernel/sn2/sn2_smp.c +1 -1
@@ -183,7 +183,7 @@ sn2_ptc_deadlock_recovery(unsigned long mycnode =numa_node_id (); -for (cnode =0 ; cnode < numnodes; cnode++) { +for_each_online_node (cnode) {if (is_headless_node (cnode) || cnode == mycnode)continue ; nasid =cnodeid_to_nasid (cnode);
include/asm-ia64/numa.h +1 -1
@@ -59,7 +59,7 @@ extern struct node_cpuid_s node_cpuid[NR*/ extern u8 numa_slit[MAX_NUMNODES *MAX_NUMNODES ]; -#define node_distance (from,to) (numa_slit[from * numnodes + to]) +#define node_distance (from,to) (numa_slit[from * num_online_nodes() + to])extern int paddr_to_nid (unsigned long paddr);
include/asm-ia64/sn/sn2/sn_private.h +0 -2
@@ -87,9 +87,7 @@ void klhwg_add_all_modules(vertex_hdl_t)void install_klidbg_functions (void );/* klnuma.c */ -extern void replicate_kernel_text (int numnodes);extern unsigned long get_freemem_start (cnodeid_t cnode); -extern void setup_replication_mask (int maxnodes);/* init.c */ extern cnodeid_t get_compact_nodeid (void );/* get compact node id */
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Matthew,
A couple of these nodemask changes are increasing kernel text size quite a bit on big numa configurations.
I've got one test case I ran where the text size of vmlinux increased from 8789097 to 8810513 bytes (2.6.5 kernel for ia64 SN2 NR_CPUS=512 sn2_defconfig, gcc 3.2.3).
Quoted 1 line
From a cursory comparson of 'nm --print-size --size-sort' output,
I think the increased space is caused by the numerous numnodes changes, such as:
- pxm_to_nid_map[i] = numnodes;
- nid_to_pxm_map[numnodes++] = i;
+ pxm_to_nid_map[i] = num_online_nodes();
+ nid_to_pxm_map[num_online_nodes()] = i;
+ node_set_online(num_online_nodes());
And by the for loop replacements:
- for (nid = 0, i = 0; i < numnodes; i++) {
+ nid = 0;
+ for_each_online_node(i) {
In particular, the machine code generated by the following silly little routine:
int foo() { int i = 0, n; for_each_online_node(n) i++; return i; }
is ... hold onto your hat ...
a000000100116f40 <foo>:
a000000100116f40: 00 10 20 02 29 26 [MII] addl r2=-2091896,r1 a000000100116f46: 80 00 00 00 42 20 mov r8=r0 a000000100116f4c: 02 00 08 90 mov r17=256 a000000100116f50: 0b 90 00 00 00 21 [MMI] mov r18=r0;; a000000100116f56: 50 01 08 30 20 00 ld8 r21=[r2] a000000100116f5c: 00 00 04 00 nop.i 0x0;; a000000100116f60: 01 78 00 2a 00 21 [MII] mov r15=r21 a000000100116f66: 00 00 00 02 00 00 nop.i 0x0 a000000100116f6c: 00 00 04 00 nop.i 0x0;; a000000100116f70: 03 80 20 1e 18 14 [MII] ld8 r16=[r15],8 a000000100116f76: 10 01 46 7e 46 40 adds r17=-64,r17;; a000000100116f7c: 00 8c b0 88 and r2=-64,r17;; a000000100116f80: 10 48 00 04 08 39 [MIB] cmp.eq p9,p8=0,r2 a000000100116f86: a0 00 40 16 f2 05 cmp.eq p10,p11=0,r16
a000000100116f8c: 90 00 00 43 (p11) br.cond.dpnt.few a000000100117010 <foo+0xd0>a000000100116f90: 11 90 00 25 00 21 [MIB] adds r18=64,r18a000000100116f96: 00 00 00 02 00 04 nop.i 0x0a000000100116f9c: e0 ff ff 4a (p08) br.cond.dptk.few a000000100116f70 <foo+0x30>;;
a000000100116fa0: 01 50 fc f9 ff 27 [MII] mov r10=-1 a000000100116fa6: 00 01 46 4a 40 20 sub r16=64,r17 a000000100116fac: 01 88 20 e4 cmp.eq p9,p8=0,r17;; a000000100116fb0: 30 71 00 24 00 21 [MIB] (p09) mov r14=r18 a000000100116fb6: b0 00 40 24 80 04 zxt4 r11=r16 a000000100116fbc: 90 00 00 42 (p09) br.cond.dptk.few a000000100117040 <foo+0x100> a000000100116fc0: 0b 18 00 1e 18 10 [MMI] ld8 r3=[r15];; a000000100116fc6: 00 00 00 02 00 20 nop.m 0x0 a000000100116fcc: b1 50 00 79 shr.u r9=r10,r11;; a000000100116fd0: 03 00 00 00 01 00 [MII] nop.m 0x0 a000000100116fd6: 00 00 00 02 00 00 nop.i 0x0;; a000000100116fdc: 00 00 04 00 nop.i 0x0;; a000000100116fe0: 01 00 00 00 01 00 [MII] nop.m 0x0 a000000100116fe6: 00 00 00 02 00 00 nop.i 0x0 a000000100116fec: 00 00 04 00 nop.i 0x0;; a000000100116ff0: 0b 80 24 06 0c 20 [MMI] and r16=r9,r3;; a000000100116ff6: d0 00 40 18 72 00 cmp.eq p13,p12=0,r16 a000000100116ffc: 00 00 04 00 nop.i 0x0;; a000000100117000: b0 71 48 22 00 20 [MIB] (p13) add r14=r18,r17 a000000100117006: 00 00 00 02 80 06 nop.i 0x0 a00000010011700c: 40 00 00 42 (p13) br.cond.dptk.few a000000100117040 <foo+0x100> a000000100117010: 0b 98 fc 21 3f 23 [MMI] adds r19=-1,r16;; a000000100117016: 10 99 40 1a 40 00 andcm r17=r19,r16 a00000010011701c: 00 00 04 00 nop.i 0x0;; a000000100117020: 02 00 00 00 01 00 [MII] nop.m 0x0 a000000100117026: f0 00 44 a4 39 c0 popcnt r15=r17;; a00000010011702c: 21 79 00 80 add r14=r18,r15 a000000100117030: 01 00 00 00 01 00 [MII] nop.m 0x0 a000000100117036: 00 00 00 02 00 00 nop.i 0x0 a00000010011703c: 00 00 04 00 nop.i 0x0;; a000000100117040: 00 90 fc 01 01 24 [MII] mov r18=255 a000000100117046: f0 00 38 00 42 c0 mov r15=r14 a00000010011704c: f2 e7 ff 9f mov r22=-1 a000000100117050: 1d a0 fc 01 01 24 [MFB] mov r20=255 a000000100117056: 00 00 00 02 00 00 nop.f 0x0 a00000010011705c: 00 00 00 20 nop.b 0x0;; a000000100117060: 10 78 48 1c 8e 30 [MIB] cmp4.lt p15,p14=r18,r14 a000000100117066: 00 00 00 02 80 87 nop.i 0x0 a00000010011706c: 08 00 84 03 (p15) br.ret.dpnt.many b0 a000000100117070: 01 c0 04 1e 00 21 [MII] adds r24=1,r15 a000000100117076: 30 01 00 04 48 00 mov r19=256 a00000010011707c: 11 40 00 84 adds r8=1,r8;; a000000100117080: 02 00 00 00 01 00 [MII] nop.m 0x0 a000000100117086: f0 00 60 2c 00 e0 sxt4 r15=r24;; a00000010011708c: c2 78 e4 52 shr.u r23=r15,6 a000000100117090: 09 90 00 1f 2c 22 [MMI] and r18=-64,r15 a000000100117096: a0 78 4c 16 68 e0 cmp.ltu p10,p11=r15,r19 a00000010011709c: f1 7b b0 80 and r15=63,r15;; a0000001001170a0: 10 98 4c 24 05 e0 [MIB] sub r19=r19,r18 a0000001001170a6: e2 00 00 04 c8 05 (p11) mov r14=256 a0000001001170ac: a0 01 00 42 (p11) br.cond.dptk.few a000000100117240 <foo+0x300> a0000001001170b0: 0a 40 00 1e 09 39 [MMI] cmp.eq p8,p9=0,r15;; a0000001001170b6: c0 f8 4d 1a 6a 40 cmp.ltu p12,p13=63,r19 a0000001001170bc: 63 79 20 79 shl r26=r22,r15 a0000001001170c0: 11 88 5c 2a 12 20 [MIB] shladd r17=r23,3,r21 a0000001001170c6: 00 00 00 02 00 04 nop.i 0x0 a0000001001170cc: 70 00 00 42 (p08) br.cond.dptk.few a000000100117130 <foo+0x1f0>;; a0000001001170d0: 01 c8 20 22 18 14 [MII] ld8 r25=[r17],8 a0000001001170d6: 00 00 00 02 00 00 nop.i 0x0 a0000001001170dc: 00 00 04 00 nop.i 0x0;; a0000001001170e0: 01 00 00 00 01 00 [MII] nop.m 0x0 a0000001001170e6: 00 00 00 02 00 00 nop.i 0x0 a0000001001170ec: 00 00 04 00 nop.i 0x0;; a0000001001170f0: 10 80 68 32 0c 20 [MIB] and r16=r26,r25 a0000001001170f6: 00 00 00 02 80 06 nop.i 0x0 a0000001001170fc: c0 00 00 43 (p13) br.cond.dpnt.few a0000001001171b0 <foo+0x270> a000000100117100: 1d 98 00 27 3f 23 [MFB] adds r19=-64,r19 a000000100117106: 00 00 00 02 00 00 nop.f 0x0 a00000010011710c: 00 00 00 20 nop.b 0x0;; a000000100117110: 10 70 00 20 0f 39 [MIB] cmp.eq p14,p15=0,r16 a000000100117116: 00 00 00 02 80 07 nop.i 0x0 a00000010011711c: 00 01 00 43 (p15) br.cond.dpnt.few a000000100117210 <foo+0x2d0> a000000100117120: 00 90 00 25 00 21 [MII] adds r18=64,r18 a000000100117126: 00 00 00 02 00 00 nop.i 0x0 a00000010011712c: 00 00 04 00 nop.i 0x0 a000000100117130: 1d d8 00 27 2c 22 [MFB] and r27=-64,r19 a000000100117136: 00 00 00 02 00 00 nop.f 0x0 a00000010011713c: 00 00 00 20 nop.b 0x0;; a000000100117140: 10 58 00 36 0a 39 [MIB] cmp.eq p11,p10=0,r27 a000000100117146: 00 00 00 02 80 05 nop.i 0x0 a00000010011714c: 40 00 00 43 (p11) br.cond.dpnt.few a000000100117180 <foo+0x240> a000000100117150: 03 80 20 22 18 14 [MII] ld8 r16=[r17],8 a000000100117156: 30 01 4e 7e 46 80 adds r19=-64,r19;; a00000010011715c: 03 9c b0 88 and r28=-64,r19;; a000000100117160: 10 48 00 38 08 39 [MIB] cmp.eq p9,p8=0,r28 a000000100117166: c0 00 40 1a f2 06 cmp.eq p12,p13=0,r16
a00000010011716c: b0 00 00 43 (p13) br.cond.dpnt.few a000000100117210 <foo+0x2d0>a000000100117170: 11 90 00 25 00 21 [MIB] adds r18=64,r18a000000100117176: 00 00 00 02 00 04 nop.i 0x0a00000010011717c: e0 ff ff 4a (p08) br.cond.dptk.few a000000100117150 <foo+0x210>;;
a000000100117180: 1d 48 00 26 08 39 [MFB] cmp.eq p9,p8=0,r19 a000000100117186: 00 00 00 02 00 00 nop.f 0x0 a00000010011718c: 00 00 00 20 nop.b 0x0;; a000000100117190: 30 71 00 24 00 21 [MIB] (p09) mov r14=r18 a000000100117196: 00 00 00 02 80 04 nop.i 0x0 a00000010011719c: b0 00 00 42 (p09) br.cond.dptk.few a000000100117240 <foo+0x300> a0000001001171a0: 00 80 00 22 18 10 [MII] ld8 r16=[r17] a0000001001171a6: 00 00 00 02 00 00 nop.i 0x0 a0000001001171ac: 00 00 04 00 nop.i 0x0 a0000001001171b0: 0b f8 00 27 25 20 [MMI] sub r31=64,r19;; a0000001001171b6: 00 00 00 02 00 c0 nop.m 0x0 a0000001001171bc: 03 f8 48 00 zxt4 r30=r31;; a0000001001171c0: 01 00 00 00 01 00 [MII] nop.m 0x0 a0000001001171c6: d0 f1 58 80 3c 00 shr.u r29=r22,r30 a0000001001171cc: 00 00 04 00 nop.i 0x0;; a0000001001171d0: 03 00 00 00 01 00 [MII] nop.m 0x0 a0000001001171d6: 00 00 00 02 00 00 nop.i 0x0;; a0000001001171dc: 00 00 04 00 nop.i 0x0;; a0000001001171e0: 01 00 00 00 01 00 [MII] nop.m 0x0 a0000001001171e6: 00 00 00 02 00 00 nop.i 0x0 a0000001001171ec: 00 00 04 00 nop.i 0x0;; a0000001001171f0: 0b 80 74 20 0c 20 [MMI] and r16=r29,r16;; a0000001001171f6: f0 00 40 1c 72 00 cmp.eq p15,p14=0,r16 a0000001001171fc: 00 00 04 00 nop.i 0x0;; a000000100117200: f0 71 48 26 00 20 [MIB] (p15) add r14=r18,r19 a000000100117206: 00 00 00 02 80 07 nop.i 0x0 a00000010011720c: 40 00 00 42 (p15) br.cond.dptk.few a000000100117240 <foo+0x300> a000000100117210: 0b 48 fc 21 3f 23 [MMI] adds r9=-1,r16;; a000000100117216: 30 48 40 1a 40 00 andcm r3=r9,r16 a00000010011721c: 00 00 04 00 nop.i 0x0;; a000000100117220: 02 00 00 00 01 00 [MII] nop.m 0x0 a000000100117226: 20 00 0c a4 39 c0 popcnt r2=r3;; a00000010011722c: 21 11 00 80 add r14=r18,r2 a000000100117230: 01 00 00 00 01 00 [MII] nop.m 0x0 a000000100117236: 00 00 00 02 00 00 nop.i 0x0 a00000010011723c: 00 00 04 00 nop.i 0x0;; a000000100117240: 10 78 00 1c 00 21 [MIB] mov r15=r14 a000000100117246: b0 a0 38 14 61 05 cmp4.lt p11,p10=r20,r14 a00000010011724c: 30 fe ff 4a (p10) br.cond.dptk.few a000000100117070 <foo+0x130> a000000100117250: 11 00 00 00 01 00 [MIB] nop.m 0x0 a000000100117256: 00 00 00 02 00 80 nop.i 0x0 a00000010011725c: 08 00 84 00 br.ret.sptk.many b0;;
Possible changes to consider:
1) Instead of replacing each numnodes with num_online_nodes(), rather add a local function variable:
int numnodes = num_online_nodes();
This would reduce the size of the source code patch as well.
2) Perhaps some of the mechanism laying beneath num_online_nodes(), such as in the bitmap/bitop area, should not be inlined.
3) Are not the following two codes essentially equivalent:
int n;
for_each_online_node(n) {
blah blah ...
}
and:
int n;
for (n = 0; n < MAX_NUMNODES; n++) {
if (! node_online(n))
continue;
blah blah ...
}
I'll wager the second form generates better code. And since
the second form is closer to what was there before, generates
a smaller patch.
In other words, I am not yet understanding the value of changing
each loop over nodes to use these macros.Just possible avenues for investigation - there are likely others.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Quoted 28 lines · Paul Jackson
Matthew,
A couple of these nodemask changes are increasing kernel text size quite a bit on big numa configurations.
I've got one test case I ran where the text size of vmlinux increased from 8789097 to 8810513 bytes (2.6.5 kernel for ia64 SN2 NR_CPUS=512
sn2_defconfig, gcc 3.2.3).From a cursory comparson of 'nm --print-size --size-sort' output, I think the increased space is caused by the numerous numnodes changes, such as:
arch/ia64/kernel/acpi.c +3
-2- pxm_to_nid_map[i] = numnodes; - nid_to_pxm_map[numnodes++] = i; + pxm_to_nid_map[i] =num_online_nodes (); + nid_to_pxm_map[num_online_nodes ()] = i; +node_set_online (num_online_nodes ());And by the for loop replacements:
arch/ia64/mm/discontig.c +2
-1-for (nid =0 , i =0 ; i < numnodes; i++) { + nid =0 ; +for_each_online_node (i) {In particular, the machine code generated by the following silly little routine:
Quoted 8 lines
int
foo(){ int i = 0, n;for_each_online_node(n)i++; return i; }is ... hold onto your hat ...
a000000100116f40<foo>:a000000100116f40: 00 10 20 02 29 26 [MII] addl r2=-2091896,r1 a000000100116f46: 80 00 00 00 42 20 mov r8=r0 a000000100116f4c: 02 00 08 90 mov r17=256
<~700 bytes of code snipped away>
Quoted 2 lines
a000000100117256: 00 00 00 02 00 80 nop.i0x0a00000010011725c: 08 00 84 00 br.ret.sptk.many b0;;
Deinlining will help, but why such a simple thing require 700 bytes of code in the first place? (assuming it's not a gcc drain bamage and non-inlined for_each_online_node(n) will be of comparable size)
Signature · 1 line
vda
Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Denis asked:
Quoted 1 line
why such a simple thing require 700 bytes of code in the first place?
Well ... it doesn't "require" 700 bytes of code. But it is currently consuming that much in this patch set, each time a for node loop is invoked.
This is because "for_each_online_node" boils down to two copies of "find_next_bit" (to get the first bit and then to get the next bit), and in the file include/asm-ia64/bitops.h, find_next_bit() is the following hefty chunk of inline code:
/*
* Find next bit in a bitmap reasonably efficiently..
*/
static inline intfind_next_bit(const void *addr, unsigned long size, unsigned long offset)
{
unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
unsigned long result = offset & ~63UL;
unsigned long tmp;
if (offset >= size)
return size;
size -= result;
offset &= 63UL;
if (offset) {
tmp = *(p++);
tmp &= ~0UL << offset;
if (size < 64)
goto found_first;
if (tmp)
goto found_middle;
size -= 64;
result += 64;
}
while (size & ~63UL) {
if ((tmp = *(p++)))
goto found_middle;
result += 64;
size -= 64;
}
if (!size)
return result;
tmp = *p;
found_first:
tmp &= ~0UL >> (64-size);
if (tmp == 0UL) /* Are any bits set? */
return result + size; /* Nope. */
found_middle:
return result + __ffs(tmp);
}===
Some things that Matthew might want to try:
1) Don't inline ia64 find_next_bit
2) Hunt down and minimize uses find_next_bit (benefits more than just numamask)
3) Instead of having the loop macro evaluate to:
for (i = first_node(mask); i < MAX_NUMNODES; i = next_node(i, mask))
rather have it evaluate something like this (node_set is more efficient):
for (
({ i = 0; while(!node_set(i, mask) && i < MAX_NUMNODES) i++; i; });
i < MAX_NUMNODES;
({ i++; while(!node_set(i, mask) && i < MAX_NUMNODES) i++; i; })
)Hmmm ... (3) looks rather nice (in an ugly sort of way ...). It might be worth moving lower, perhaps into bitmap, for use by both cpumask and nodemask.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Several architectures have this large version of find_next_bit() code.
It may well make sense for the O(1) scheduler to be inlining this.
Perhaps these large versions should be renamed sched_find_next_bit(), as is done for sched_find_first_bit(), and another, more space efficient version provided under the name find_next_bit(), for use by others who should prefer smaller code size. The asm-generic version of this smaller one might be something like [pseudo C]:
int find_next_bit(addr, size, pos)
{
int i;
for (i = pos; i < size; i++) {
if (test_bit(i, addr))
break;
}
return i;}
Arch's that have a reasonably tight version of find_next_bit() already could use it for both sched_find_next_bit() and find_next_bit().
Just speculating ...
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Quoted 4 lines · Paul Jackson
Several architectures have this large version of
find_next_bit()code.It may well make sense for the O(1) scheduler to be inlining this.
No, the schedule() fastpath doesn't use find_next_bit. That is only used to traverse the runqueues when moving tasks from one to another. No problem uninlining it there.
If the function is more than a cacheline or two big, you'll probably get better performance through better cache utilisation anyway, and you'll be able to use a slightly larger, faster version if you have one, which is probably a good thing.
Unless there is something specific that I'm not aware of?
Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Quoted 1 line · Nick
No, the
schedule()fastpath doesn't usefind_next_bit.
Ok - makes sense - thanks.
Uninlining it is perhaps the easiest way out.
That or replacing it with the trivial version that is several times smaller (loops one bit at a time, checking 'test_bit()').
Right now, I don't see any excuse for that fat version of find_next_bit() to exist.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Quoted 7 lines · Paul Jackson
Quoted 1 line · Nick
No, the
schedule()fastpath doesn't usefind_next_bit.Ok - makes sense - thanks.
Quoted 8 lines
Uninlining it is perhaps the easiest way out.
That or replacing it with the trivial version that is several times smaller (loops one bit at a time, checking '
test_bit()').Right now, I don't see any excuse for that fat version of
find_next_bit()to exist.
Well it would be nice to keep it fast though, especially for big masks like those 64 byte cpumasks of yours. In the scheduler for example, a lot of balancing operations are done with very sparse cpumasks, which your bit at a time version doesn't handle very well.
For example, a global CPU balancing operation on a 512 CPU system with 2 CPUs per node currently does 256 for_each_cpu loops over cpumasks with two entries in them. 130 thousand test_bit loop iteratinos.
The uninlined larger version would have to be smaller and faster than your small version inlined, wouldn't it?
Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Quoted 2 lines
The uninlined larger version would have to be smaller and faster than your small version inlined, wouldn't it?
Yes - a normal function call with 3 args will be smaller than an inline for-loop with a test_bit().
Faster depends - small or dense would favor the inline, large and sparse the larger version via a call.
You raise good points. Thanks.
Looks like uninlining it is the sensible choice.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
In reply to Paul JacksonQuoted 3 lines · Paul Jackson
Several architectures have this large version of
find_next_bit()code.It may well make sense for the O(1) scheduler to be inlining this.
Why?
Signature · 1 line
vda
Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Quoted 3 lines
Quoted 1 line
It may well make sense for the O(1) scheduler to be inlining this.
Why?
I was thinking that perhaps this call was in a certain critical performance path of the O(1) scheduler.
Turned out it wasn't - see further Nick Piggin's followups to this same thread.
My latest bitmap/cpumask patch moves this out of line, for ia64. The other arch's that use this large find_next_bit() code might want to move it out too.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Quoted 6 lines · Paul Jackson
Quoted 3 lines
Quoted 1 line
It may well make sense for the O(1) scheduler to be inlining this.
Why?
I was thinking that perhaps this call was in a certain critical performance path of the O(1) scheduler.
Even if it is used in some time critical place, adding call overhead ~350 byte function will barely be noticeable on speed, but *will* be noticeable on size.
Quoted 6 lines
Turned out it wasn't - see further Nick Piggin's followups to this same thread.
My latest bitmap/cpumask patch moves this out of line, for ia64. The other arch's that use this large
find_next_bit()code might want to move it out too.
We have far too many large inlines to kill them one by one. Nedd to automate that.
--
vda
Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Quoted 1 line
Even if it is used in some time critical place, adding call overhead
I'm not disagreeing with anything you note. I was just stating that I didn't claim the expertise for such decisions.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
In reply to Paul JacksonA few hours ago, I sketched the following code:
Quoted 5 lines
for (
({ i = 0; while(!node_set(i, mask) && i < MAX_NUMNODES) i++; i; });
i < MAX_NUMNODES;
({ i++; while(!node_set(i, mask) && i < MAX_NUMNODES) i++; i; })
)I've reduced this to a pair of bitmap.h operators:
Quoted 5 lines
#define find_next_bit_in_bitmap(src, nbits, n) \ ({ int i = (n); while(i < (nbits) && !test_bit(i, (src))) i++; i; })#define find_first_bit_in_bitmap(src, nbits) \ find_next_bit_in_bitmap((src), (nbits), 0)
which are plug compatible with bitops find_first_bit() and find_next_bit(), but smaller. These alternatives can then be used in the for-loop defines.
The above is not yet compiled or tested ... Use at own risk.
My next mask patchset will have these. Following the excellent recommendations of Rusty however, my next mask patchset won't have masks ;). Just cpumasks bolted directly on top of souped up bitmaps.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes
Quoted 11 lines
I've reduced this to a pair of
bitmap.hoperators:Quoted 5 lines
#define find_next_bit_in_bitmap(src, nbits, n) \ ({ int i = (n); while(i < (nbits) && !test_bit(i, (src))) i++; i; })#define find_first_bit_in_bitmap(src, nbits) \ find_next_bit_in_bitmap((src), (nbits), 0)...
My next mask patchset will have these.
Wrong. My next patch set, released 8 April, did not have these.
A subsequent discussion with Nick Piggin convinced me that the better path was to take find_next_bit() out of line, which I did for ia64 (other arch's might also want to do this).
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 18/23 mask v2 - [7/7] nodemask_t_other_arch_changes
In reply to Paul JacksonPatch_18_of_23 - Matthew Dobson's [PATCH]_nodemask_t_other_arch_changes_[7_7]
Changes to other arch-specific code (alpha, arm, mips, sparc64 & sh). Untested. Code review & testing requested.
Diffstat Patch_18_of_23:
arch/alpha/mm/numa.c | 12 ++++++------ arch/arm/mm/init.c | 33 ++++++++++++++------------------- arch/arm/mm/mm-armv.c | 2 +- arch/arm26/mm/init.c | 3 ++- arch/mips/sgi-ip27/ip27-init.c | 27 +++++++++++++-------------- arch/mips/sgi-ip27/ip27-klnuma.c | 8 ++++---- arch/mips/sgi-ip27/ip27-memory.c | 8 ++++---- arch/mips/sgi-ip27/ip27-nmi.c | 8 ++++---- arch/mips/sgi-ip27/ip27-reset.c | 4 ++-- arch/mips/sgi-ip27/ip27-smp.c | 10 +++++----- arch/sparc64/mm/hugetlbpage.c | 9 ++++----- include/asm-mips/sn/sn_private.h | 4 ++-- include/asm-sh/mmzone.h | 2 +- 13 files changed, 62 insertions(+), 68 deletions(-)
===================================================================
arch/alpha/mm/numa.c +6 -6
@@ -244,7 +244,7 @@reserve_bootmem_node (NODE_DATA (nid),PFN_PHYS (bootmap_start), bootmap_size);printk (" reserving pages %ld:%ld\n" , bootmap_start, bootmap_start+PFN_UP (bootmap_size)); - numnodes++; +node_set_online (nid); }void __init
@@ -254,11 +254,11 @@show_mem_layout (); - numnodes =0 ; +nodes_clear (node_online_map); min_low_pfn = ~0UL ; max_low_pfn =0UL ; -for (nid =0 ; nid <MAX_NUMNODES ; nid++) +for_each_node (nid)setup_memory_node (nid, kernel_end);#ifdef CONFIG_BLK_DEV_INITRD
@@ -301,7 +301,7 @@*/ dma_local_pfn =virt_to_phys ((char *)MAX_DMA_ADDRESS ) >>PAGE_SHIFT ; -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {unsigned long start_pfn = node_bdata[nid].node_boot_start >>PAGE_SHIFT ;unsigned long end_pfn = node_bdata[nid].node_low_pfn;
@@ -330,7 +330,7 @@ high_memory = (void *)__va (max_low_pfn <<PAGE_SHIFT ); reservedpages =0 ; -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {/* * This will free up the bootmem, ie, slot 0 memory */
@@ -370,7 +370,7 @@printk ("\nMem-info:\n" );show_free_areas ();printk ("Free swap: %6dkB\n" ,nr_swap_pages<<(PAGE_SHIFT -10 )); -for (nid =0 ; nid < numnodes; nid++) { +for_each_online_node (nid) {struct page * lmem_map =node_mem_map (nid); i =node_spanned_pages (nid);while (i-- >0 ) {
===================================================================
arch/arm/mm/init.c +14 -19
@@ -69,7 +69,7 @@show_free_areas ();printk ("Free swap: %6dkB\n" ,nr_swap_pages<<(PAGE_SHIFT -10 )); -for (node =0 ; node < numnodes; node++) { +for_each_online_node (node) {struct page *page, *end; page =NODE_MEM_MAP (node);
@@ -172,7 +172,7 @@ {unsigned int i, bootmem_pages =0 , memend_pfn =0 ; -for (i =0 ; i <MAX_NUMNODES ; i++) { +for_each_node (i) { np[i].start =-1U ; np[i].end =0 ; np[i].bootmap_pages =0 ;
@@ -192,18 +192,13 @@ node = mi->bank[i].node; -if (node >= numnodes) { - numnodes = node +1 ; - -/* -* Make sure we haven't exceeded the maximum number -* of nodes that we have in this configuration. If -* we have, we're in trouble. (maybe we ought to -* limit, instead of bugging?) -*/ -if (numnodes >MAX_NUMNODES ) -BUG (); - } +/* +* Make sure we haven't exceeded the maximum number of nodes +* that we have in this configuration. If we have, we're in +* trouble. +*/ +if (!node_online (node) &&node_possible (node)) +node_set_online (node);/* * Get the start and end pfns for this bank
@@ -225,7 +220,7 @@* Calculate the number of pages we require to * store the bootmem bitmaps. */ -for (i =0 ; i < numnodes; i++) { +for_each_online_node (i) {if (np[i].end ==0 )continue ;
@@ -388,8 +383,8 @@* (we could also do with rolling bootmem_init and paging_init * into one generic "memory_init" type function). */ - np += numnodes -1 ; -for (node = numnodes -1 ; node >=0 ; node--, np--) { + np +=num_online_nodes () -1 ; +for (node =num_online_nodes () -1 ; node >=0 ; node--, np--) {/* * If there are no pages in this node, ignore it. * Note that node 0 must always have some pages.
@@ -457,7 +452,7 @@/* * initialise the zones within each node */ -for (node =0 ; node < numnodes; node++) { +for_each_online_node (node) {unsigned long zone_size[MAX_NR_ZONES ];unsigned long zhole_size[MAX_NR_ZONES ];struct bootmem_data *bdata;
@@ -567,7 +562,7 @@create_memmap_holes (&meminfo);/* this will put all unused low memory onto the freelists */ -for (node =0 ; node < numnodes; node++) { +for_each_online_node (node) {pg_data_t *pgdat =NODE_DATA (node);if (pgdat->node_spanned_pages !=0 )
===================================================================
arch/arm/mm/mm-armv.c +1 -1
@@ -653,6 +653,6 @@ {int node; -for (node =0 ; node < numnodes; node++) +for_each_online_node (node)free_unused_memmap_node (node, mi); }
===================================================================
arch/arm26/mm/init.c +2 -1
@@ -156,7 +156,8 @@ {unsigned int memend_pfn =0 ; - numnodes =1 ; +nodes_clear (node_online_map); +node_set_online (0 ); np->bootmap_pages =0 ;
===================================================================
arch/mips/sgi-ip27/ip27-init.c +13 -14
@@ -10,7 +10,7 @@#include <linux/kernel.h> #include <linux/init.h> #include <linux/sched.h> -#include <linux/mmzone.h> /* for numnodes */ +#include <linux/nodemask.h> /* for node_online_map */ #include <linux/mm.h> #include <linux/cpumask.h> #include <asm/cpu.h>
@@ -56,14 +56,13 @@return COMPACT_TO_NASID_NODEID (cnode) >>NASID_TO_COARSEREG_SHFT ; } -static void gen_region_mask (hubreg_t *region_mask,int maxnodes) +static void gen_region_mask (hubreg_t *region_mask) {cnodeid_t cnode; (*region_mask) =0 ; -for (cnode =0 ; cnode < maxnodes; cnode++) { +for_each_online_node (cnode) (*region_mask) |=1ULL <<get_region (cnode); - } }static int is_fine_dirmode (void )
@@ -168,7 +167,7 @@int port;/* Figure out which routers nodes in question are connected to */ -for (cnode =0 ; cnode < numnodes; cnode++) { +for_each_online_node (cnode) { nasid =COMPACT_TO_NASID_NODEID (cnode);if (nasid ==-1 )continue ;
@@ -235,9 +234,9 @@for (col =0 ; col <MAX_COMPACT_NODES ; col++) node_distances[row][col] =-1 ; -for (row =0 ; row < numnodes; row++) { +for_each_online_node (row) { nasid =COMPACT_TO_NASID_NODEID (row); -for (col =0 ; col < numnodes; col++) { +for_each_online_node (col) { nasid2 =COMPACT_TO_NASID_NODEID (col); node_distances[row][col] =node_distance (nasid, nasid2); }
@@ -257,17 +256,17 @@printk ("************** Topology ********************\n" );printk (" " ); -for (col =0 ; col < numnodes; col++) +for_each_online_node (col)printk ("%02d " , col);printk ("\n" ); -for (row =0 ; row < numnodes; row++) { +for_each_online_node (row) {printk ("%02d " , row); -for (col =0 ; col < numnodes; col++) +for_each_online_node (col)printk ("%2d " , node_distances[row][col]);printk ("\n" ); } -for (cnode =0 ; cnode < numnodes; cnode++) { +for_each_online_node (cnode) { nasid =COMPACT_TO_NASID_NODEID (cnode);if (nasid ==-1 )continue ;
@@ -323,14 +322,14 @@init_topology_matrix ();dump_topology (); -gen_region_mask (®ion_mask, numnodes); +gen_region_mask (®ion_mask); -setup_replication_mask (numnodes); +setup_replication_mask ();/* * Set all nodes' calias sizes to 8k */ -for (i =0 ; i < numnodes; i++) { +for_each_online_node (i) {nasid_t nasid; nasid =COMPACT_TO_NASID_NODEID (i);
===================================================================
arch/mips/sgi-ip27/ip27-klnuma.c +4 -4
@@ -27,7 +27,7 @@* kernel. For example, we should never put a copy on a headless node, * and we should respect the topology of the machine. */ -void __init setup_replication_mask (int maxnodes) +void __init setup_replication_mask (void ) {static int numa_kernel_replication_ratio;cnodeid_t cnode;
@@ -44,7 +44,7 @@ numa_kernel_replication_ratio =1 ;#endif -for (cnode =1 ; cnode < numnodes; cnode++) { +for (cnode =1 ; cnode <num_online_nodes (); cnode++) {/* See if this node should get a copy of the kernel */ if (numa_kernel_replication_ratio && !(cnode % numa_kernel_replication_ratio)) {
@@ -92,7 +92,7 @@memcpy ((void *)dest_kern_start, (void *)source_start, kern_size); } -void __init replicate_kernel_text (int maxnodes) +void __init replicate_kernel_text (void ) {cnodeid_t cnode;nasid_t client_nasid;
@@ -103,7 +103,7 @@/* Record where the master node should get its kernel text */ set_ktext_source (master_nasid, master_nasid); -for (cnode =1 ; cnode < maxnodes; cnode++) { +for (cnode =1 ; cnode <num_online_nodes (); cnode++) { client_nasid =COMPACT_TO_NASID_NODEID (cnode);/* Check if this node should get a copy of the kernel */
===================================================================
arch/mips/sgi-ip27/ip27-memory.c +4 -4
@@ -137,7 +137,7 @@pfn_t slot0sz =0 , nodebytes;/* Hack to detect problem configs */ int ignore; -for (node =0 ; node < numnodes; node++) { +for_each_online_node (node) { numslots =node_getnumslots (node); ignore = nodebytes =0 ;for (slot =0 ; slot < numslots; slot++) {
@@ -183,7 +183,7 @@ num_physpages =szmem (); -for (node =0 ; node < numnodes; node++) { +for_each_online_node (node) {pfn_t slot_firstpfn =slot_getbasepfn (node,0 );pfn_t slot_lastpfn = slot_firstpfn +slot_getsize (node,0 );pfn_t slot_freepfn =node_getfirstfree (node);
@@ -225,7 +225,7 @@pagetable_init (); -for (node =0 ; node < numnodes; node++) { +for_each_online_node (node) {pfn_t start_pfn =slot_getbasepfn (node,0 );pfn_t end_pfn =node_getmaxclick (node) +1 ;
@@ -245,7 +245,7 @@ high_memory = (void *)__va (num_physpages <<PAGE_SHIFT ); -for (node =0 ; node < numnodes; node++) { +for_each_online_node (node) {unsigned slot, numslots;struct page *end, *p;
===================================================================
arch/mips/sgi-ip27/ip27-nmi.c +4 -4
@@ -183,7 +183,7 @@ {cnodeid_t cnode; -for (cnode =0 ; cnode < numnodes; cnode++) +for_each_online_node (cnode)nmi_node_eframe_save (cnode); }
@@ -214,13 +214,13 @@* send NMIs to all cpus on a 256p system. */ for (i=0 ; i <1500 ; i++) { -for (node=0 ; node < numnodes; node++) +for_each_online_node (node)if (NODEPDA (node)->dump_count ==0 )break ; -if (node == numnodes) +if (node ==num_online_nodes ())break ;if (i ==1000 ) { -for (node=0 ; node < numnodes; node++) +for_each_online_node (node)if (NODEPDA (node)->dump_count ==0 ) { cpu =CNODE_TO_CPU_BASE (node);for (n=0 ; n <CNODE_NUM_CPUS (node); cpu++, n++) {
===================================================================
arch/mips/sgi-ip27/ip27-reset.c +2 -2
@@ -43,7 +43,7 @@smp_send_stop ();#endif #if 0 -for (i =0 ; i < numnodes; i++) +for_each_online_node (i)REMOTE_HUB_S (COMPACT_TO_NASID_NODEID (i),PROMOP_REG ,PROMOP_REBOOT );#else
@@ -59,7 +59,7 @@#ifdef CONFIG_SMP smp_send_stop ();#endif -for (i =0 ; i < numnodes; i++) +for_each_online_node (i)REMOTE_HUB_S (COMPACT_TO_NASID_NODEID (i),PROMOP_REG ,PROMOP_RESTART );LOCAL_HUB_S (NI_PORT_RESET ,NPR_PORTRESET |NPR_LOCALRESET );
===================================================================
arch/mips/sgi-ip27/ip27-smp.c +5 -5
@@ -108,18 +108,18 @@for (i =0 ; i <MAXCPUS ; i++) cpuid_to_compact_node[i] =INVALID_CNODEID ; - numnodes =0 ; +nodes_clear (node_online_map);for (i =0 ; i <MAX_COMPACT_NODES ; i++) {nasid_t nasid = gdap->g_nasidtable[i];if (nasid ==INVALID_NASID )break ; compact_to_nasid_node[i] = nasid; nasid_to_compact_node[nasid] = i; - numnodes++; +node_set_online (i); highest =do_cpumask (i, nasid, highest); } -printk ("Discovered %d cpus on %d nodes\n" , highest +1 , numnodes); +printk ("Discovered %d cpus on %d nodes\n" , highest +1 ,num_online_nodes ()); }void __init prom_build_cpu_map (void )
@@ -155,13 +155,13 @@ {cnodeid_t cnode; -for (cnode =0 ; cnode < numnodes; cnode++) +for_each_online_node (cnode)intr_clear_all (COMPACT_TO_NASID_NODEID (cnode));/* Master has already done per_cpu_init() */ install_ipi (); -replicate_kernel_text (numnodes); +replicate_kernel_text ();/* * Assumption to be fixed: we're always booted on logical / physical
===================================================================
arch/sparc64/mm/hugetlbpage.c +4 -5
@@ -39,12 +39,11 @@struct page *page =NULL ;if (list_empty (&hugepage_freelists[nid])) { -for (nid =0 ; nid <MAX_NUMNODES ; ++nid) +for_each_node (nid)if (!list_empty (&hugepage_freelists[nid]))break ; } -if (nid >=0 && nid <MAX_NUMNODES && - !list_empty (&hugepage_freelists[nid])) { +if (node_possible (nid) && !list_empty (&hugepage_freelists[nid])) { page =list_entry (hugepage_freelists[nid].next, struct page, list);list_del (&page->list);
@@ -57,7 +56,7 @@static int nid =0 ;struct page *page; page =alloc_pages_node (nid,GFP_HIGHUSER ,HUGETLB_PAGE_ORDER ); - nid = (nid +1 ) % numnodes; + nid = (nid +1 ) %num_online_nodes ();return page; }
@@ -464,7 +463,7 @@int i;struct page *page; -for (i =0 ; i <MAX_NUMNODES ; ++i) +for_each_node (i)INIT_LIST_HEAD (&hugepage_freelists[i]);for (i =0 ; i < htlbpage_max; ++i) {
===================================================================
include/asm-mips/sn/sn_private.h +2 -2
@@ -13,8 +13,8 @@extern void per_hub_init (cnodeid_t cnode);extern void install_cpu_nmi_handler (int slice);extern void install_ipi (void ); -extern void setup_replication_mask (int ); -extern void replicate_kernel_text (int ); +extern void setup_replication_mask (void ); +extern void replicate_kernel_text (void );extern pfn_t node_getfirstfree (cnodeid_t );#endif /* __ASM_SN_SN_PRIVATE_H */
===================================================================
include/asm-sh/mmzone.h +1 -1
@@ -46,7 +46,7 @@ {unsigned int i; -for (i =0 ; i <MAX_NUMNODES ; i++) { +for_each_node (i) {if (page >=NODE_MEM_MAP (i) && page <NODE_MEM_MAP (i) +NODE_DATA (i)->node_size)return 1 ;
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 19/23 mask v2 - Simplify sparc64 cpumask loop code
In reply to Paul JacksonPatch_19_of_23 - Simplify some sparc64 cpumask loop code
Make use of for_each_cpu_mask() macro to simplify and optimize a couple of sparc64 per-CPU loops. This code change has _not_ been tested or reviewed. Feedback welcome. There is non-trivial risk that I still don't understand the logic here.
Diffstat Patch_19_of_23:
smp.c | 66 ++++++++++++++--------------------------- 1 files changed, 24 insertions(+), 42 deletions(-)
arch/sparc64/kernel/smp.c +24 -42
@@ -409,14 +409,8 @@int i; __asm__ __volatile__("rdpr %%pstate, %0" :"=r" (pstate)); -for (i =0 ; i <NR_CPUS ; i++) { -if (cpu_isset (i, mask)) { -spitfire_xcall_helper (data0, data1, data2, pstate, i); -cpu_clear (i, mask); -if (cpus_empty (mask)) -break ; - } - } +for_each_cpu_mask (i, mask) +spitfire_xcall_helper (data0, data1, data2, pstate, i); }/* Cheetah now allows to send the whole 64-bytes of data in the interrupt
@@ -459,25 +453,19 @@ nack_busy_id =0 ; { -cpumask_t work_mask = mask;int i; -for (i =0 ; i <NR_CPUS ; i++) { -if (cpu_isset (i, work_mask)) { -u64 target = (i <<14 ) |0x70 ; - -if (!is_jalapeno) - target |= (nack_busy_id <<24 ); - __asm__ __volatile__( -"stxa %%g0, [%0] %1\n\t" -"membar #Sync\n\t" - :/* no outputs */ - :"r" (target),"i" (ASI_INTR_W )); - nack_busy_id++; -cpu_clear (i, work_mask); -if (cpus_empty (work_mask)) -break ; - } +for_each_cpu_mask (i, mask) { +u64 target = (i <<14 ) |0x70 ; + +if (!is_jalapeno) + target |= (nack_busy_id <<24 ); + __asm__ __volatile__( +"stxa %%g0, [%0] %1\n\t" +"membar #Sync\n\t" + :/* no outputs */ + :"r" (target),"i" (ASI_INTR_W )); + nack_busy_id++; } }
@@ -510,7 +498,6 @@printk ("CPU[%d]: mondo stuckage result[%016lx]\n" ,smp_processor_id (), dispatch_stat); }else { -cpumask_t work_mask = mask;int i, this_busy_nack =0 ;/* Delay some random time with interrupts enabled
@@ -521,22 +508,17 @@/* Clear out the mask bits for cpus which did not * NACK us. */ -for (i =0 ; i <NR_CPUS ; i++) { -if (cpu_isset (i, work_mask)) { -u64 check_mask; - -if (is_jalapeno) - check_mask = (0x2UL << (2 *i)); -else - check_mask = (0x2UL << - this_busy_nack); -if ((dispatch_stat & check_mask) ==0 ) -cpu_clear (i, mask); - this_busy_nack +=2 ; -cpu_clear (i, work_mask); -if (cpus_empty (work_mask)) -break ; - } +for_each_cpu_mask (i, mask) { +u64 check_mask; + +if (is_jalapeno) + check_mask = (0x2UL << (2 *i)); +else + check_mask = (0x2UL << + this_busy_nack); +if ((dispatch_stat & check_mask) ==0 ) +cpu_clear (i, mask); + this_busy_nack +=2 ; } goto retry;
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 20/23 mask v2 - Optimize i386 cpumask macro usage
In reply to Paul JacksonPatch_20_of_23 - Optimize i386 cpumask macro usage.
Optimize a bit of cpumask code for asm-i386/mach-es7000 Code untested, unreviewed. Feedback welcome.
Diffstat Patch_20_of_23:
mach_ipi.h | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
include/asm-i386/mach-es7000/mach_ipi.h +2 -3
@@ -10,9 +10,8 @@static inline void send_IPI_allbutself (int vector) { -cpumask_t mask =cpumask_of_cpu (smp_processor_id ()); -cpus_complement (mask); -cpus_and (mask, mask, cpu_online_map); +cpumask_t mask = cpu_online_map; +cpu_clear (smp_processor_id (), mask);if (!cpus_empty (mask))send_IPI_mask (mask, vector); }
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 21/23 mask v2 - Dyadic physids_complement()
In reply to Paul JacksonPatch_21_of_23 - Convert physids_complement() to really use both args
Provide for specifying distinct source and dest args to the physids_complement(). No one actually uses this macro yet. The physid_mask type would be a good candidate to convert to using this new mask ADT as a base.
Diffstat Patch_21_of_23:
asm-i386/mpspec.h | 2 +- asm-x86_64/mpspec.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/asm-i386/mpspec.h +1 -1
@@ -60,7 +60,7 @@#define physids_and (dst, src1, src2) bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)#define physids_or (dst, src1, src2) bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)#define physids_clear (map) bitmap_clear((map).mask, MAX_APICS) -#define physids_complement (map) bitmap_complement((map).mask, (map).mask, MAX_APICS) +#define physids_complement (dst, src) bitmap_complement((dst).mask, (src).mask, MAX_APICS)#define physids_empty (map) bitmap_empty((map).mask, MAX_APICS)#define physids_equal (map1, map2) bitmap_equal((map1).mask, (map2).mask, MAX_APICS)#define physids_weight (map) bitmap_weight((map).mask, MAX_APICS)
include/asm-x86_64/mpspec.h +1 -1
@@ -214,7 +214,7 @@#define physids_and (dst, src1, src2) bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)#define physids_or (dst, src1, src2) bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)#define physids_clear (map) bitmap_clear((map).mask, MAX_APICS) -#define physids_complement (map) bitmap_complement((map).mask, (map).mask, MAX_APICS) +#define physids_complement (dst, src) bitmap_complement((dst).mask, (src).mask, MAX_APICS)#define physids_empty (map) bitmap_empty((map).mask, MAX_APICS)#define physids_equal (map1, map2) bitmap_equal((map1).mask, (map2).mask, MAX_APICS)#define physids_weight (map) bitmap_weight((map).mask, MAX_APICS)
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 22/23 mask v2 - Fix cpumask in asm-x86_64/topology.h
In reply to Paul JacksonPatch_22_of_23 - Remove cpumask hack from asm-x86_64/topology.h
This file had the cpumask cpu_online_map as type unsigned long, instead of type cpumask_t, for no good reason that I could see. So I changed it. Everywhere else, cpu_online_map is already of type cpumask_t.
Diffstat Patch_22_of_23:
topology.h | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
include/asm-x86_64/topology.h +5 -5
@@ -10,18 +10,18 @@/* Map the K8 CPU local memory controllers to a simple 1:1 CPU:NODE topology */ extern int fake_node; -/* This is actually a cpumask_t, but doesn't matter because we don't have ->BITS_PER_LONG CPUs */ -extern unsigned long cpu_online_map; +extern cpumask_t cpu_online_map;#define cpu_to_node (cpu) (fake_node ? 0 : (cpu))#define parent_node (node) (node)#define node_to_first_cpu (node) (fake_node ? 0 : (node))#define node_to_cpumask (node) (fake_node ? cpu_online_map : (1UL << (node))) -static inline unsigned long pcibus_to_cpumask (int bus) +static inline cpumask_t pcibus_to_cpumask (int bus) { -return mp_bus_to_cpumask[bus] & cpu_online_map; +cpumask_t tmp; +cpus_and (tmp, mp_bus_to_cpumask[bus], cpu_online_map); +return tmp; }#define NODE_BALANCE_RATE 30/* CHECKME */
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 23/23 mask v2 - Cpumask tweak in kernel/sched.c
In reply to Paul JacksonPatch_23_of_23 - Cpumask code clarification in kernel/sched.c
Clarify and slightly optimize set_cpus_allowed() cpumask check
Diffstat Patch_23_of_23:
sched.c | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-)
kernel/sched.c +1 -1
@@ -2708,7 +2708,7 @@runqueue_t *rq; rq =task_rq_lock (p, &flags); -if (any_online_cpu (new_mask) ==NR_CPUS ) { +if (!cpus_intersects (new_mask, cpu_online_map)) { ret = -EINVAL ; goto out; }
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 24/23] mask v2 - Small system optimizations
In reply to Paul JacksonThis Patch 24 of 23 ;-) improves the small system code, where small is anything under 32 or 64 CPUs. I am now getting vmlinux kernel text sizes that are about 600 bytes of text _smaller_ with these mask patches applied (which include the addition of Matthew's nodemask_t), then a stock 2.6.4. This is with i386 arch defconfig, NR_CPUS = 8, 16 or 32, gcc 3.3.2.
The patch uses some preprocessor logic in the mask.h file, in order to provide alternative macros that are custom tuned for the small system. So far, only a couple of macros, for cpumask_of_cpu() and CPU_MASK_ALL, look to be worth special casing this way.
The cpumask.h and nodemask.h files that users of these macros will work with are practically free of any of this logic - just one #define telling mask.h what size masks are needed, before the #include of mask.h. There is less such overhead in these files than in yesterdays version.
The focus continues to be on keeping these masks convenient to understand and use.
Thanks to Matthew for provoking me into these latest improvements.
And special thanks to Andrew for his patch tools (ancestor of 'quilt'), without which even the few patches I have here would be a royal pain.
Diffstat:
cpumask.h | 13 ++++++------- mask.h | 53 ++++++++++++++++++++++++++++++++++++++++++----------- nodemask.h | 14 ++++++-------- 3 files changed, 54 insertions(+), 26 deletions(-)
==================================================================
include/linux/cpumask.h +6 -7
@@ -61,9 +61,10 @@*/ #include <linux/threads.h> -#include <linux/mask.h> #include <asm/bug.h> +#define _NBITS_IN_THIS_MASK NR_CPUS +#include <linux/mask.h> typedef __mask (NR_CPUS)cpumask_t ;extern cpumask_t _unused_cpumask_arg_;
@@ -90,13 +91,11 @@ mask_shift_left((dst), (src), (n), NR_CPUS)#define first_cpu (mask) mask_first((mask), NR_CPUS)#define next_cpu (cpu, mask) mask_next((cpu), (mask), NR_CPUS) -#define cpumask_of_cpu (cpu) mask_of_bit((cpu), _unused_cpumask_arg_) -#if NR_CPUS <=BITS_PER_LONG -#define CPU_MASK_ALL MASK_ALL1(NR_CPUS) -#else -#define CPU_MASK_ALL MASK_ALL2(NR_CPUS) -#endif +#define CPU_MASK_NONE MASK_NONE(NR_CPUS) +#define cpumask_of_cpu (cpu) mask_of_bit((cpu), _unused_cpumask_arg_) +#define CPU_MASK_ALL MASK_ALL(NR_CPUS) +#define cpus_addr (mask) mask_addr(mask)#define cpumask_scnprintf (buf, len, mask) \ mask_scnprintf((buf), (len), (mask), NR_CPUS)
include/linux/mask.h +42 -11
88 lines not on this page · raw message
include/linux/nodemask.h +6 -8
@@ -61,9 +61,10 @@*/ #include <linux/numa.h> -#include <linux/mask.h> #include <asm/bug.h> +#define _NBITS_IN_THIS_MASK MAX_NUMNODES +#include <linux/mask.h> typedef __mask (MAX_NUMNODES)nodemask_t ;extern nodemask_t _unused_nodemask_arg_;
@@ -90,14 +91,11 @@ mask_shift_left((dst), (src), (n), MAX_NUMNODES)#define first_node (mask) mask_first((mask), MAX_NUMNODES)#define next_node (node, mask) mask_next((node), (mask), MAX_NUMNODES) -#define nodemask_of_node (node) \ - mask_of_bit((node), _unused_nodemask_arg_) -#if MAX_NUMNODES <=BITS_PER_LONG -#define NODE_MASK_ALL MASK_ALL1(MAX_NUMNODES) -#else -#define NODE_MASK_ALL MASK_ALL2(MAX_NUMNODES) -#endif +#define NODE_MASK_NONE MASK_NONE(MAX_NUMNODES) +#define nodemask_of_node (node) mask_of_bit((node), _unused_nodemask_arg_) +#define NODE_MASK_ALL MASK_ALL(MAX_NUMNODES) +#define nodes_addr (mask) mask_addr(mask)#define nodemask_scnprintf (buf, len, mask) \ mask_scnprintf((buf), (len), (mask), MAX_NUMNODES)
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373Re: [Patch 24/23] mask v2 - Small system optimizations
Forget [Patch 24/23]. This patch is bad.
The C preprocessor does not bind symbols the way this patch requires. With this patch, including both cpumask.h and nodemask.h in the same header would end up with a broken mixture of implementations if cpumasks were bigger than one word, but nodemasks not.
[Patch 24a/23] will be out shortly, replacing this patch.
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373PATCH 1/1 mask v2 - UP fix, faster mask_of_bit, MASK_ALL* names
In reply to Paul JacksonThis patch replaces 24/23. Patch 24/23 was fouled up beyond all recall.
This patch 24a/23 applies after the 23 mask v2 patches 1/23 - 23/23, based on the 2.6.4 Linux kernel.
It closely follows some excellent suggestions from Matthew.
1) It corrects a build error for UP (1 CPU, no SMP). Real cpu_online_map and cpu_possible_map data words are needed, so that cpumask_of_cpu() will evalutate correctly when in used in contexts requiring a real lvalue, as in sys_sched_getaffinity().
2) Since the MASK_ALL* implementation alternatives (for the single long and multiple long cases) are split across the base mask.h file and the derived cpumask.h/nodemask.h files, rename them to MASK_ALL_SINGLE_LONG/MASK_ALL_MULTIPLE_LONG, as suggested by Matthew, for code clarity.
3) Optimize the single word flavor of mask_of_bit (resulting in better code on small systems for cpumask_of_cpu).
The mask.h header is once again (still, if you don't count 24/23) usable in its own right.
Diffstat:
include/linux/cpumask.h | 11 ++++------- include/linux/mask.h | 12 ++++++++---- include/linux/nodemask.h | 4 ++-- kernel/sched.c | 5 +++++ 4 files changed, 19 insertions(+), 13 deletions(-)
include/linux/cpumask.h +4 -7
@@ -92,9 +92,9 @@#define next_cpu (cpu, mask) mask_next((cpu), (mask), NR_CPUS)#define cpumask_of_cpu (cpu) mask_of_bit((cpu), _unused_cpumask_arg_)#if NR_CPUS <=BITS_PER_LONG -#define CPU_MASK_ALL MASK_ALL1(NR_CPUS) +#define CPU_MASK_ALL MASK_ALL_SINGLE_LONG(NR_CPUS)#else -#define CPU_MASK_ALL MASK_ALL2(NR_CPUS) +#define CPU_MASK_ALL MASK_ALL_MULTIPLE_LONG(NR_CPUS)#endif #define CPU_MASK_NONE MASK_NONE(NR_CPUS)#define cpus_addr (mask) mask_addr(mask)
@@ -108,11 +108,11 @@* on them manage all (possible) and online cpus. */ -#ifdef CONFIG_SMP -extern cpumask_t cpu_online_map;extern cpumask_t cpu_possible_map; +#ifdef CONFIG_SMP +#define num_online_cpus () cpus_weight(cpu_online_map)#define num_possible_cpus () cpus_weight(cpu_possible_map)#define cpu_online (cpu) cpu_isset((cpu), cpu_online_map)
@@ -134,9 +134,6 @@#else /* !CONFIG_SMP */ -#define cpu_online_map cpumask_of_cpu(0) -#define cpu_possible_map cpumask_of_cpu(0) -#define num_online_cpus () 1#define num_possible_cpus () 1#define cpu_online (cpu) ({ BUG_ON((cpu) != 0); 1; })
include/linux/mask.h +8 -4
@@ -334,19 +334,23 @@#define mask_of_bit (bit,T ) \ ({ \ typeof(T) m; \ - mask_clearall(m, 8*sizeof(m)); \ - mask_setbit((bit), m); \ + if (sizeof(m) == sizeof(unsigned long)) \ + m._m[0] = 1UL<<(bit); \ + else { \ + mask_clearall(m, 8*sizeof(m)); \ + mask_setbit((bit), m); \ + } \ m; \ })/* Use if nbits <= BITS_PER_LONG */ -#define MASK_ALL1 (nbits) \ +#define MASK_ALL_SINGLE_LONG (nbits) \ { { \ [BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits) \ } }/* Use if nbits > BITS_PER_LONG */ -#define MASK_ALL2 (nbits) \ +#define MASK_ALL_MULTIPLE_LONG (nbits) \ { { \ [0 ... BITS_TO_LONGS(nbits)-2] = ~0UL, \ [BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits) \
include/linux/nodemask.h +2 -2
@@ -93,9 +93,9 @@#define nodemask_of_node (node) \ mask_of_bit((node), _unused_nodemask_arg_)#if MAX_NUMNODES <=BITS_PER_LONG -#define NODE_MASK_ALL MASK_ALL1(MAX_NUMNODES) +#define NODE_MASK_ALL MASK_ALL_SINGLE_LONG(MAX_NUMNODES)#else -#define NODE_MASK_ALL MASK_ALL2(MAX_NUMNODES) +#define NODE_MASK_ALL MASK_ALL_MULTIPLE_LONG(MAX_NUMNODES)#endif #define NODE_MASK_NONE MASK_NONE(MAX_NUMNODES)#define nodes_addr (mask) mask_addr(mask)
kernel/sched.c +5 -0
@@ -2340,6 +2340,11 @@return retval; } +#ifndef CONFIG_SMP +cpumask_t cpu_online_map =CPU_MASK_ALL ; +cpumask_t cpu_possible_map =CPU_MASK_ALL ; +#endif +/** * sys_sched_getaffinity - get the cpu affinity of a process * @pid: pid of the process
Signature · 3 lines
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373