Commit fb5eeeee44edb248b4837416966f19731f497f79

Authored by Paul Jackson
Committed by Linus Torvalds
1 parent 28a42b9ea7

[PATCH] cpusets: bitmap and mask remap operators

In the forthcoming task migration support, a key calculation will be
mapping cpu and node numbers from the old set to the new set while
preserving cpuset-relative offset.

For example, if a task and its pages on nodes 8-11 are being migrated to
nodes 24-27, then pages on node 9 (the 2nd node in the old set) should be
moved to node 25 (the 2nd node in the new set.)

As with other bitmap operations, the proper way to code this is to provide
the underlying calculation in lib/bitmap.c, and then to provide the usual
cpumask and nodemask wrappers.

This patch provides that.  These operations are termed 'remap' operations.
Both remapping a single bit and a set of bits is supported.

Signed-off-by: Paul Jackson <pj@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 4 changed files with 212 additions and 0 deletions Side-by-side Diff

include/linux/bitmap.h
... ... @@ -40,6 +40,8 @@
40 40 * bitmap_weight(src, nbits) Hamming Weight: number set bits
41 41 * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
42 42 * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
  43 + * bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src)
  44 + * bitmap_bitremap(oldbit, old, new, nbits) newbit = map(old, new)(oldbit)
43 45 * bitmap_scnprintf(buf, len, src, nbits) Print bitmap src to buf
44 46 * bitmap_parse(ubuf, ulen, dst, nbits) Parse bitmap dst from user buf
45 47 * bitmap_scnlistprintf(buf, len, src, nbits) Print bitmap src as list to buf
... ... @@ -104,6 +106,10 @@
104 106 const unsigned long *src, int nbits);
105 107 extern int bitmap_parselist(const char *buf, unsigned long *maskp,
106 108 int nmaskbits);
  109 +extern void bitmap_remap(unsigned long *dst, const unsigned long *src,
  110 + const unsigned long *old, const unsigned long *new, int bits);
  111 +extern int bitmap_bitremap(int oldbit,
  112 + const unsigned long *old, const unsigned long *new, int bits);
107 113 extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
108 114 extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
109 115 extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
include/linux/cpumask.h
... ... @@ -12,6 +12,8 @@
12 12 * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
13 13 * For details of cpulist_scnprintf() and cpulist_parse(), see
14 14 * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
  15 + * For details of cpu_remap(), see bitmap_bitremap in lib/bitmap.c
  16 + * For details of cpus_remap(), see bitmap_remap in lib/bitmap.c.
15 17 *
16 18 * The available cpumask operations are:
17 19 *
... ... @@ -50,6 +52,8 @@
50 52 * int cpumask_parse(ubuf, ulen, mask) Parse ascii string as cpumask
51 53 * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing
52 54 * int cpulist_parse(buf, map) Parse ascii string as cpulist
  55 + * int cpu_remap(oldbit, old, new) newbit = map(old, new)(oldbit)
  56 + * int cpus_remap(dst, src, old, new) *dst = map(old, new)(src)
53 57 *
54 58 * for_each_cpu_mask(cpu, mask) for-loop cpu over mask
55 59 *
... ... @@ -292,6 +296,22 @@
292 296 static inline int __cpulist_parse(const char *buf, cpumask_t *dstp, int nbits)
293 297 {
294 298 return bitmap_parselist(buf, dstp->bits, nbits);
  299 +}
  300 +
  301 +#define cpu_remap(oldbit, old, new) \
  302 + __cpu_remap((oldbit), &(old), &(new), NR_CPUS)
  303 +static inline int __cpu_remap(int oldbit,
  304 + const cpumask_t *oldp, const cpumask_t *newp, int nbits)
  305 +{
  306 + return bitmap_bitremap(oldbit, oldp->bits, newp->bits, nbits);
  307 +}
  308 +
  309 +#define cpus_remap(dst, src, old, new) \
  310 + __cpus_remap(&(dst), &(src), &(old), &(new), NR_CPUS)
  311 +static inline void __cpus_remap(cpumask_t *dstp, const cpumask_t *srcp,
  312 + const cpumask_t *oldp, const cpumask_t *newp, int nbits)
  313 +{
  314 + bitmap_remap(dstp->bits, srcp->bits, oldp->bits, newp->bits, nbits);
295 315 }
296 316  
297 317 #if NR_CPUS > 1
include/linux/nodemask.h
... ... @@ -12,6 +12,8 @@
12 12 * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
13 13 * For details of nodelist_scnprintf() and nodelist_parse(), see
14 14 * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
  15 + * For details of node_remap(), see bitmap_bitremap in lib/bitmap.c.
  16 + * For details of nodes_remap(), see bitmap_remap in lib/bitmap.c.
15 17 *
16 18 * The available nodemask operations are:
17 19 *
... ... @@ -52,6 +54,8 @@
52 54 * int nodemask_parse(ubuf, ulen, mask) Parse ascii string as nodemask
53 55 * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
54 56 * int nodelist_parse(buf, map) Parse ascii string as nodelist
  57 + * int node_remap(oldbit, old, new) newbit = map(old, new)(oldbit)
  58 + * int nodes_remap(dst, src, old, new) *dst = map(old, new)(dst)
55 59 *
56 60 * for_each_node_mask(node, mask) for-loop node over mask
57 61 *
... ... @@ -305,6 +309,22 @@
305 309 static inline int __nodelist_parse(const char *buf, nodemask_t *dstp, int nbits)
306 310 {
307 311 return bitmap_parselist(buf, dstp->bits, nbits);
  312 +}
  313 +
  314 +#define node_remap(oldbit, old, new) \
  315 + __node_remap((oldbit), &(old), &(new), MAX_NUMNODES)
  316 +static inline int __node_remap(int oldbit,
  317 + const nodemask_t *oldp, const nodemask_t *newp, int nbits)
  318 +{
  319 + return bitmap_bitremap(oldbit, oldp->bits, newp->bits, nbits);
  320 +}
  321 +
  322 +#define nodes_remap(dst, src, old, new) \
  323 + __nodes_remap(&(dst), &(src), &(old), &(new), MAX_NUMNODES)
  324 +static inline void __nodes_remap(nodemask_t *dstp, const nodemask_t *srcp,
  325 + const nodemask_t *oldp, const nodemask_t *newp, int nbits)
  326 +{
  327 + bitmap_remap(dstp->bits, srcp->bits, oldp->bits, newp->bits, nbits);
308 328 }
309 329  
310 330 #if MAX_NUMNODES > 1
... ... @@ -511,6 +511,172 @@
511 511 }
512 512 EXPORT_SYMBOL(bitmap_parselist);
513 513  
  514 +/*
  515 + * bitmap_pos_to_ord(buf, pos, bits)
  516 + * @buf: pointer to a bitmap
  517 + * @pos: a bit position in @buf (0 <= @pos < @bits)
  518 + * @bits: number of valid bit positions in @buf
  519 + *
  520 + * Map the bit at position @pos in @buf (of length @bits) to the
  521 + * ordinal of which set bit it is. If it is not set or if @pos
  522 + * is not a valid bit position, map to zero (0).
  523 + *
  524 + * If for example, just bits 4 through 7 are set in @buf, then @pos
  525 + * values 4 through 7 will get mapped to 0 through 3, respectively,
  526 + * and other @pos values will get mapped to 0. When @pos value 7
  527 + * gets mapped to (returns) @ord value 3 in this example, that means
  528 + * that bit 7 is the 3rd (starting with 0th) set bit in @buf.
  529 + *
  530 + * The bit positions 0 through @bits are valid positions in @buf.
  531 + */
  532 +static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
  533 +{
  534 + int ord = 0;
  535 +
  536 + if (pos >= 0 && pos < bits) {
  537 + int i;
  538 +
  539 + for (i = find_first_bit(buf, bits);
  540 + i < pos;
  541 + i = find_next_bit(buf, bits, i + 1))
  542 + ord++;
  543 + if (i > pos)
  544 + ord = 0;
  545 + }
  546 + return ord;
  547 +}
  548 +
  549 +/**
  550 + * bitmap_ord_to_pos(buf, ord, bits)
  551 + * @buf: pointer to bitmap
  552 + * @ord: ordinal bit position (n-th set bit, n >= 0)
  553 + * @bits: number of valid bit positions in @buf
  554 + *
  555 + * Map the ordinal offset of bit @ord in @buf to its position in @buf.
  556 + * If @ord is not the ordinal offset of a set bit in @buf, map to zero (0).
  557 + *
  558 + * If for example, just bits 4 through 7 are set in @buf, then @ord
  559 + * values 0 through 3 will get mapped to 4 through 7, respectively,
  560 + * and all other @ord valuds will get mapped to 0. When @ord value 3
  561 + * gets mapped to (returns) @pos value 7 in this example, that means
  562 + * that the 3rd set bit (starting with 0th) is at position 7 in @buf.
  563 + *
  564 + * The bit positions 0 through @bits are valid positions in @buf.
  565 + */
  566 +static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
  567 +{
  568 + int pos = 0;
  569 +
  570 + if (ord >= 0 && ord < bits) {
  571 + int i;
  572 +
  573 + for (i = find_first_bit(buf, bits);
  574 + i < bits && ord > 0;
  575 + i = find_next_bit(buf, bits, i + 1))
  576 + ord--;
  577 + if (i < bits && ord == 0)
  578 + pos = i;
  579 + }
  580 +
  581 + return pos;
  582 +}
  583 +
  584 +/**
  585 + * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap
  586 + * @src: subset to be remapped
  587 + * @dst: remapped result
  588 + * @old: defines domain of map
  589 + * @new: defines range of map
  590 + * @bits: number of bits in each of these bitmaps
  591 + *
  592 + * Let @old and @new define a mapping of bit positions, such that
  593 + * whatever position is held by the n-th set bit in @old is mapped
  594 + * to the n-th set bit in @new. In the more general case, allowing
  595 + * for the possibility that the weight 'w' of @new is less than the
  596 + * weight of @old, map the position of the n-th set bit in @old to
  597 + * the position of the m-th set bit in @new, where m == n % w.
  598 + *
  599 + * If either of the @old and @new bitmaps are empty, or if@src and @dst
  600 + * point to the same location, then this routine does nothing.
  601 + *
  602 + * The positions of unset bits in @old are mapped to the position of
  603 + * the first set bit in @new.
  604 + *
  605 + * Apply the above specified mapping to @src, placing the result in
  606 + * @dst, clearing any bits previously set in @dst.
  607 + *
  608 + * The resulting value of @dst will have either the same weight as
  609 + * @src, or less weight in the general case that the mapping wasn't
  610 + * injective due to the weight of @new being less than that of @old.
  611 + * The resulting value of @dst will never have greater weight than
  612 + * that of @src, except perhaps in the case that one of the above
  613 + * conditions was not met and this routine just returned.
  614 + *
  615 + * For example, lets say that @old has bits 4 through 7 set, and
  616 + * @new has bits 12 through 15 set. This defines the mapping of bit
  617 + * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
  618 + * bit positions to 12 (the first set bit in @new. So if say @src
  619 + * comes into this routine with bits 1, 5 and 7 set, then @dst should
  620 + * leave with bits 12, 13 and 15 set.
  621 + */
  622 +void bitmap_remap(unsigned long *dst, const unsigned long *src,
  623 + const unsigned long *old, const unsigned long *new,
  624 + int bits)
  625 +{
  626 + int s;
  627 +
  628 + if (bitmap_weight(old, bits) == 0)
  629 + return;
  630 + if (bitmap_weight(new, bits) == 0)
  631 + return;
  632 + if (dst == src) /* following doesn't handle inplace remaps */
  633 + return;
  634 +
  635 + bitmap_zero(dst, bits);
  636 + for (s = find_first_bit(src, bits);
  637 + s < bits;
  638 + s = find_next_bit(src, bits, s + 1)) {
  639 + int x = bitmap_pos_to_ord(old, s, bits);
  640 + int y = bitmap_ord_to_pos(new, x, bits);
  641 + set_bit(y, dst);
  642 + }
  643 +}
  644 +EXPORT_SYMBOL(bitmap_remap);
  645 +
  646 +/**
  647 + * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit
  648 + * @oldbit - bit position to be mapped
  649 + * @old: defines domain of map
  650 + * @new: defines range of map
  651 + * @bits: number of bits in each of these bitmaps
  652 + *
  653 + * Let @old and @new define a mapping of bit positions, such that
  654 + * whatever position is held by the n-th set bit in @old is mapped
  655 + * to the n-th set bit in @new. In the more general case, allowing
  656 + * for the possibility that the weight 'w' of @new is less than the
  657 + * weight of @old, map the position of the n-th set bit in @old to
  658 + * the position of the m-th set bit in @new, where m == n % w.
  659 + *
  660 + * The positions of unset bits in @old are mapped to the position of
  661 + * the first set bit in @new.
  662 + *
  663 + * Apply the above specified mapping to bit position @oldbit, returning
  664 + * the new bit position.
  665 + *
  666 + * For example, lets say that @old has bits 4 through 7 set, and
  667 + * @new has bits 12 through 15 set. This defines the mapping of bit
  668 + * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
  669 + * bit positions to 12 (the first set bit in @new. So if say @oldbit
  670 + * is 5, then this routine returns 13.
  671 + */
  672 +int bitmap_bitremap(int oldbit, const unsigned long *old,
  673 + const unsigned long *new, int bits)
  674 +{
  675 + int x = bitmap_pos_to_ord(old, oldbit, bits);
  676 + return bitmap_ord_to_pos(new, x, bits);
  677 +}
  678 +EXPORT_SYMBOL(bitmap_bitremap);
  679 +
514 680 /**
515 681 * bitmap_find_free_region - find a contiguous aligned mem region
516 682 * @bitmap: an array of unsigned longs corresponding to the bitmap