aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Jackson <pj@sgi.com>2005-10-30 18:02:33 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-30 20:37:21 -0500
commitfb5eeeee44edb248b4837416966f19731f497f79 (patch)
treef947a4dcf103f55d526bb5c71f69b657d8f22e61
parent28a42b9ea7e42e1efb02cc2dcacba0b6af234e1b (diff)
[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>
-rw-r--r--include/linux/bitmap.h6
-rw-r--r--include/linux/cpumask.h20
-rw-r--r--include/linux/nodemask.h20
-rw-r--r--lib/bitmap.c166
4 files changed, 212 insertions, 0 deletions
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 86dd5502b05c..7d8ff97b3e92 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -40,6 +40,8 @@
40 * bitmap_weight(src, nbits) Hamming Weight: number set bits 40 * bitmap_weight(src, nbits) Hamming Weight: number set bits
41 * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n 41 * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
42 * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n 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 * bitmap_scnprintf(buf, len, src, nbits) Print bitmap src to buf 45 * bitmap_scnprintf(buf, len, src, nbits) Print bitmap src to buf
44 * bitmap_parse(ubuf, ulen, dst, nbits) Parse bitmap dst from user buf 46 * bitmap_parse(ubuf, ulen, dst, nbits) Parse bitmap dst from user buf
45 * bitmap_scnlistprintf(buf, len, src, nbits) Print bitmap src as list to buf 47 * bitmap_scnlistprintf(buf, len, src, nbits) Print bitmap src as list to buf
@@ -104,6 +106,10 @@ extern int bitmap_scnlistprintf(char *buf, unsigned int len,
104 const unsigned long *src, int nbits); 106 const unsigned long *src, int nbits);
105extern int bitmap_parselist(const char *buf, unsigned long *maskp, 107extern int bitmap_parselist(const char *buf, unsigned long *maskp,
106 int nmaskbits); 108 int nmaskbits);
109extern void bitmap_remap(unsigned long *dst, const unsigned long *src,
110 const unsigned long *old, const unsigned long *new, int bits);
111extern int bitmap_bitremap(int oldbit,
112 const unsigned long *old, const unsigned long *new, int bits);
107extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order); 113extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
108extern void bitmap_release_region(unsigned long *bitmap, int pos, int order); 114extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
109extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order); 115extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 9bdba8169b41..13e9f4a3ab26 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -12,6 +12,8 @@
12 * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c. 12 * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
13 * For details of cpulist_scnprintf() and cpulist_parse(), see 13 * For details of cpulist_scnprintf() and cpulist_parse(), see
14 * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c. 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 * The available cpumask operations are: 18 * The available cpumask operations are:
17 * 19 *
@@ -50,6 +52,8 @@
50 * int cpumask_parse(ubuf, ulen, mask) Parse ascii string as cpumask 52 * int cpumask_parse(ubuf, ulen, mask) Parse ascii string as cpumask
51 * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing 53 * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing
52 * int cpulist_parse(buf, map) Parse ascii string as cpulist 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 * for_each_cpu_mask(cpu, mask) for-loop cpu over mask 58 * for_each_cpu_mask(cpu, mask) for-loop cpu over mask
55 * 59 *
@@ -294,6 +298,22 @@ static inline int __cpulist_parse(const char *buf, cpumask_t *dstp, int nbits)
294 return bitmap_parselist(buf, dstp->bits, nbits); 298 return bitmap_parselist(buf, dstp->bits, nbits);
295} 299}
296 300
301#define cpu_remap(oldbit, old, new) \
302 __cpu_remap((oldbit), &(old), &(new), NR_CPUS)
303static 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)
311static 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);
315}
316
297#if NR_CPUS > 1 317#if NR_CPUS > 1
298#define for_each_cpu_mask(cpu, mask) \ 318#define for_each_cpu_mask(cpu, mask) \
299 for ((cpu) = first_cpu(mask); \ 319 for ((cpu) = first_cpu(mask); \
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index e96fe9062500..4726ef7ba8e8 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -12,6 +12,8 @@
12 * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c. 12 * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
13 * For details of nodelist_scnprintf() and nodelist_parse(), see 13 * For details of nodelist_scnprintf() and nodelist_parse(), see
14 * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c. 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 * The available nodemask operations are: 18 * The available nodemask operations are:
17 * 19 *
@@ -52,6 +54,8 @@
52 * int nodemask_parse(ubuf, ulen, mask) Parse ascii string as nodemask 54 * int nodemask_parse(ubuf, ulen, mask) Parse ascii string as nodemask
53 * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing 55 * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
54 * int nodelist_parse(buf, map) Parse ascii string as nodelist 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 * for_each_node_mask(node, mask) for-loop node over mask 60 * for_each_node_mask(node, mask) for-loop node over mask
57 * 61 *
@@ -307,6 +311,22 @@ static inline int __nodelist_parse(const char *buf, nodemask_t *dstp, int nbits)
307 return bitmap_parselist(buf, dstp->bits, nbits); 311 return bitmap_parselist(buf, dstp->bits, nbits);
308} 312}
309 313
314#define node_remap(oldbit, old, new) \
315 __node_remap((oldbit), &(old), &(new), MAX_NUMNODES)
316static 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)
324static 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);
328}
329
310#if MAX_NUMNODES > 1 330#if MAX_NUMNODES > 1
311#define for_each_node_mask(node, mask) \ 331#define for_each_node_mask(node, mask) \
312 for ((node) = first_node(mask); \ 332 for ((node) = first_node(mask); \
diff --git a/lib/bitmap.c b/lib/bitmap.c
index fb9371fdd44a..23d3b1147fe9 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -511,6 +511,172 @@ int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
511} 511}
512EXPORT_SYMBOL(bitmap_parselist); 512EXPORT_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 */
532static 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 */
566static 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 */
622void 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}
644EXPORT_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 */
672int 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}
678EXPORT_SYMBOL(bitmap_bitremap);
679
514/** 680/**
515 * bitmap_find_free_region - find a contiguous aligned mem region 681 * bitmap_find_free_region - find a contiguous aligned mem region
516 * @bitmap: an array of unsigned longs corresponding to the bitmap 682 * @bitmap: an array of unsigned longs corresponding to the bitmap