Skip to content

Commit fb5eeee

Browse files
Paul JacksonLinus Torvalds
authored andcommitted
[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>
1 parent 28a42b9 commit fb5eeee

File tree

4 files changed

+212
-0
lines changed

4 files changed

+212
-0
lines changed

include/linux/bitmap.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
* bitmap_weight(src, nbits) Hamming Weight: number set bits
4141
* bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
4242
* 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)
4345
* bitmap_scnprintf(buf, len, src, nbits) Print bitmap src to buf
4446
* bitmap_parse(ubuf, ulen, dst, nbits) Parse bitmap dst from user buf
4547
* 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,
104106
const unsigned long *src, int nbits);
105107
extern int bitmap_parselist(const char *buf, unsigned long *maskp,
106108
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);
107113
extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
108114
extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
109115
extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);

include/linux/cpumask.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
* see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
1313
* For details of cpulist_scnprintf() and cpulist_parse(), see
1414
* 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.
1517
*
1618
* The available cpumask operations are:
1719
*
@@ -50,6 +52,8 @@
5052
* int cpumask_parse(ubuf, ulen, mask) Parse ascii string as cpumask
5153
* int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing
5254
* 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)
5357
*
5458
* for_each_cpu_mask(cpu, mask) for-loop cpu over mask
5559
*
@@ -294,6 +298,22 @@ static inline int __cpulist_parse(const char *buf, cpumask_t *dstp, int nbits)
294298
return bitmap_parselist(buf, dstp->bits, nbits);
295299
}
296300

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);
315+
}
316+
297317
#if NR_CPUS > 1
298318
#define for_each_cpu_mask(cpu, mask) \
299319
for ((cpu) = first_cpu(mask); \

include/linux/nodemask.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
* see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
1313
* For details of nodelist_scnprintf() and nodelist_parse(), see
1414
* 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.
1517
*
1618
* The available nodemask operations are:
1719
*
@@ -52,6 +54,8 @@
5254
* int nodemask_parse(ubuf, ulen, mask) Parse ascii string as nodemask
5355
* int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
5456
* 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)
5559
*
5660
* for_each_node_mask(node, mask) for-loop node over mask
5761
*
@@ -307,6 +311,22 @@ static inline int __nodelist_parse(const char *buf, nodemask_t *dstp, int nbits)
307311
return bitmap_parselist(buf, dstp->bits, nbits);
308312
}
309313

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);
328+
}
329+
310330
#if MAX_NUMNODES > 1
311331
#define for_each_node_mask(node, mask) \
312332
for ((node) = first_node(mask); \

lib/bitmap.c

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,172 @@ int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
511511
}
512512
EXPORT_SYMBOL(bitmap_parselist);
513513

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+
514680
/**
515681
* bitmap_find_free_region - find a contiguous aligned mem region
516682
* @bitmap: an array of unsigned longs corresponding to the bitmap

0 commit comments

Comments
 (0)