Skip to content

Commit 30544ed

Browse files
andy-shevtorvalds
authored andcommitted
lib/bitmap: introduce bitmap_replace() helper
In some drivers we want to have a single operation over bitmap which is an equivalent to: *dst = (*old & ~(*mask)) | (*new & *mask) Introduce bitmap_replace() helper for this. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Andy Shevchenko <[email protected]> Acked-by: Linus Walleij <[email protected]> Cc: Rasmus Villemoes <[email protected]> Cc: Bartosz Golaszewski <[email protected]> Cc: Geert Uytterhoeven <[email protected]> Cc: Marek Vasut <[email protected]> Cc: Thomas Petazzoni <[email protected]> Cc: William Breathitt Gray <[email protected]> Cc: Yury Norov <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 780ff33 commit 30544ed

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

include/linux/bitmap.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
* bitmap_find_next_zero_area_off(buf, len, pos, n, mask) as above
5454
* bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
5555
* bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
56+
* bitmap_replace(dst, old, new, mask, nbits) *dst = (*old & ~(*mask)) | (*new & *mask)
5657
* bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src)
5758
* bitmap_bitremap(oldbit, old, new, nbits) newbit = map(old, new)(oldbit)
5859
* bitmap_onto(dst, orig, relmap, nbits) *dst = orig relative to relmap
@@ -140,6 +141,9 @@ extern void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
140141
const unsigned long *bitmap2, unsigned int nbits);
141142
extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
142143
const unsigned long *bitmap2, unsigned int nbits);
144+
extern void __bitmap_replace(unsigned long *dst,
145+
const unsigned long *old, const unsigned long *new,
146+
const unsigned long *mask, unsigned int nbits);
143147
extern int __bitmap_intersects(const unsigned long *bitmap1,
144148
const unsigned long *bitmap2, unsigned int nbits);
145149
extern int __bitmap_subset(const unsigned long *bitmap1,
@@ -434,6 +438,18 @@ static inline void bitmap_shift_left(unsigned long *dst, const unsigned long *sr
434438
__bitmap_shift_left(dst, src, shift, nbits);
435439
}
436440

441+
static inline void bitmap_replace(unsigned long *dst,
442+
const unsigned long *old,
443+
const unsigned long *new,
444+
const unsigned long *mask,
445+
unsigned int nbits)
446+
{
447+
if (small_const_nbits(nbits))
448+
*dst = (*old & ~(*mask)) | (*new & *mask);
449+
else
450+
__bitmap_replace(dst, old, new, mask, nbits);
451+
}
452+
437453
static inline int bitmap_parse(const char *buf, unsigned int buflen,
438454
unsigned long *maskp, int nmaskbits)
439455
{

lib/bitmap.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,18 @@ int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
222222
}
223223
EXPORT_SYMBOL(__bitmap_andnot);
224224

225+
void __bitmap_replace(unsigned long *dst,
226+
const unsigned long *old, const unsigned long *new,
227+
const unsigned long *mask, unsigned int nbits)
228+
{
229+
unsigned int k;
230+
unsigned int nr = BITS_TO_LONGS(nbits);
231+
232+
for (k = 0; k < nr; k++)
233+
dst[k] = (old[k] & ~mask[k]) | (new[k] & mask[k]);
234+
}
235+
EXPORT_SYMBOL(__bitmap_replace);
236+
225237
int __bitmap_intersects(const unsigned long *bitmap1,
226238
const unsigned long *bitmap2, unsigned int bits)
227239
{

lib/test_bitmap.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ static const unsigned long exp2[] __initconst = {
4242
BITMAP_FROM_U64(0xffffffff77777777ULL),
4343
};
4444

45+
/* Fibonacci sequence */
46+
static const unsigned long exp2_to_exp3_mask[] __initconst = {
47+
BITMAP_FROM_U64(0x008000020020212eULL),
48+
};
49+
/* exp3_0_1 = (exp2[0] & ~exp2_to_exp3_mask) | (exp2[1] & exp2_to_exp3_mask) */
50+
static const unsigned long exp3_0_1[] __initconst = {
51+
BITMAP_FROM_U64(0x33b3333311313137ULL),
52+
};
53+
/* exp3_1_0 = (exp2[1] & ~exp2_to_exp3_mask) | (exp2[0] & exp2_to_exp3_mask) */
54+
static const unsigned long exp3_1_0[] __initconst = {
55+
BITMAP_FROM_U64(0xff7fffff77575751ULL),
56+
};
57+
4558
static bool __init
4659
__check_eq_uint(const char *srcfile, unsigned int line,
4760
const unsigned int exp_uint, unsigned int x)
@@ -257,6 +270,30 @@ static void __init test_copy(void)
257270
expect_eq_pbl("0-108,128-1023", bmap2, 1024);
258271
}
259272

273+
#define EXP2_IN_BITS (sizeof(exp2) * 8)
274+
275+
static void __init test_replace(void)
276+
{
277+
unsigned int nbits = 64;
278+
DECLARE_BITMAP(bmap, 1024);
279+
280+
bitmap_zero(bmap, 1024);
281+
bitmap_replace(bmap, &exp2[0], &exp2[1], exp2_to_exp3_mask, nbits);
282+
expect_eq_bitmap(bmap, exp3_0_1, nbits);
283+
284+
bitmap_zero(bmap, 1024);
285+
bitmap_replace(bmap, &exp2[1], &exp2[0], exp2_to_exp3_mask, nbits);
286+
expect_eq_bitmap(bmap, exp3_1_0, nbits);
287+
288+
bitmap_fill(bmap, 1024);
289+
bitmap_replace(bmap, &exp2[0], &exp2[1], exp2_to_exp3_mask, nbits);
290+
expect_eq_bitmap(bmap, exp3_0_1, nbits);
291+
292+
bitmap_fill(bmap, 1024);
293+
bitmap_replace(bmap, &exp2[1], &exp2[0], exp2_to_exp3_mask, nbits);
294+
expect_eq_bitmap(bmap, exp3_1_0, nbits);
295+
}
296+
260297
#define PARSE_TIME 0x1
261298

262299
struct test_bitmap_parselist{
@@ -476,6 +513,7 @@ static void __init selftest(void)
476513
test_zero_clear();
477514
test_fill_set();
478515
test_copy();
516+
test_replace();
479517
test_bitmap_arr32();
480518
test_bitmap_parselist();
481519
test_bitmap_parselist_user();

0 commit comments

Comments
 (0)