forked from mirrors/linux
		
	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/20191022172922.61232-8-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Marek Vasut <marek.vasut+renesas@gmail.com> Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Cc: William Breathitt Gray <vilhelm.gray@gmail.com> Cc: Yury Norov <yury.norov@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									780ff33b8b
								
							
						
					
					
						commit
						30544ed5de
					
				
					 3 changed files with 66 additions and 0 deletions
				
			
		|  | @ -53,6 +53,7 @@ | |||
|  *  bitmap_find_next_zero_area_off(buf, len, pos, n, mask)  as above | ||||
|  *  bitmap_shift_right(dst, src, n, nbits)      *dst = *src >> n | ||||
|  *  bitmap_shift_left(dst, src, n, nbits)       *dst = *src << n | ||||
|  *  bitmap_replace(dst, old, new, mask, nbits)  *dst = (*old & ~(*mask)) | (*new & *mask) | ||||
|  *  bitmap_remap(dst, src, old, new, nbits)     *dst = map(old, new)(src) | ||||
|  *  bitmap_bitremap(oldbit, old, new, nbits)    newbit = map(old, new)(oldbit) | ||||
|  *  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, | |||
| 			const unsigned long *bitmap2, unsigned int nbits); | ||||
| extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1, | ||||
| 			const unsigned long *bitmap2, unsigned int nbits); | ||||
| extern void __bitmap_replace(unsigned long *dst, | ||||
| 			const unsigned long *old, const unsigned long *new, | ||||
| 			const unsigned long *mask, unsigned int nbits); | ||||
| extern int __bitmap_intersects(const unsigned long *bitmap1, | ||||
| 			const unsigned long *bitmap2, unsigned int nbits); | ||||
| 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 | |||
| 		__bitmap_shift_left(dst, src, shift, nbits); | ||||
| } | ||||
| 
 | ||||
| static inline void bitmap_replace(unsigned long *dst, | ||||
| 				  const unsigned long *old, | ||||
| 				  const unsigned long *new, | ||||
| 				  const unsigned long *mask, | ||||
| 				  unsigned int nbits) | ||||
| { | ||||
| 	if (small_const_nbits(nbits)) | ||||
| 		*dst = (*old & ~(*mask)) | (*new & *mask); | ||||
| 	else | ||||
| 		__bitmap_replace(dst, old, new, mask, nbits); | ||||
| } | ||||
| 
 | ||||
| static inline int bitmap_parse(const char *buf, unsigned int buflen, | ||||
| 			unsigned long *maskp, int nmaskbits) | ||||
| { | ||||
|  |  | |||
							
								
								
									
										12
									
								
								lib/bitmap.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								lib/bitmap.c
									
									
									
									
									
								
							|  | @ -222,6 +222,18 @@ int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1, | |||
| } | ||||
| EXPORT_SYMBOL(__bitmap_andnot); | ||||
| 
 | ||||
| void __bitmap_replace(unsigned long *dst, | ||||
| 		      const unsigned long *old, const unsigned long *new, | ||||
| 		      const unsigned long *mask, unsigned int nbits) | ||||
| { | ||||
| 	unsigned int k; | ||||
| 	unsigned int nr = BITS_TO_LONGS(nbits); | ||||
| 
 | ||||
| 	for (k = 0; k < nr; k++) | ||||
| 		dst[k] = (old[k] & ~mask[k]) | (new[k] & mask[k]); | ||||
| } | ||||
| EXPORT_SYMBOL(__bitmap_replace); | ||||
| 
 | ||||
| int __bitmap_intersects(const unsigned long *bitmap1, | ||||
| 			const unsigned long *bitmap2, unsigned int bits) | ||||
| { | ||||
|  |  | |||
|  | @ -42,6 +42,19 @@ static const unsigned long exp2[] __initconst = { | |||
| 	BITMAP_FROM_U64(0xffffffff77777777ULL), | ||||
| }; | ||||
| 
 | ||||
| /* Fibonacci sequence */ | ||||
| static const unsigned long exp2_to_exp3_mask[] __initconst = { | ||||
| 	BITMAP_FROM_U64(0x008000020020212eULL), | ||||
| }; | ||||
| /* exp3_0_1 = (exp2[0] & ~exp2_to_exp3_mask) | (exp2[1] & exp2_to_exp3_mask) */ | ||||
| static const unsigned long exp3_0_1[] __initconst = { | ||||
| 	BITMAP_FROM_U64(0x33b3333311313137ULL), | ||||
| }; | ||||
| /* exp3_1_0 = (exp2[1] & ~exp2_to_exp3_mask) | (exp2[0] & exp2_to_exp3_mask) */ | ||||
| static const unsigned long exp3_1_0[] __initconst = { | ||||
| 	BITMAP_FROM_U64(0xff7fffff77575751ULL), | ||||
| }; | ||||
| 
 | ||||
| static bool __init | ||||
| __check_eq_uint(const char *srcfile, unsigned int line, | ||||
| 		const unsigned int exp_uint, unsigned int x) | ||||
|  | @ -257,6 +270,30 @@ static void __init test_copy(void) | |||
| 	expect_eq_pbl("0-108,128-1023", bmap2, 1024); | ||||
| } | ||||
| 
 | ||||
| #define EXP2_IN_BITS	(sizeof(exp2) * 8) | ||||
| 
 | ||||
| static void __init test_replace(void) | ||||
| { | ||||
| 	unsigned int nbits = 64; | ||||
| 	DECLARE_BITMAP(bmap, 1024); | ||||
| 
 | ||||
| 	bitmap_zero(bmap, 1024); | ||||
| 	bitmap_replace(bmap, &exp2[0], &exp2[1], exp2_to_exp3_mask, nbits); | ||||
| 	expect_eq_bitmap(bmap, exp3_0_1, nbits); | ||||
| 
 | ||||
| 	bitmap_zero(bmap, 1024); | ||||
| 	bitmap_replace(bmap, &exp2[1], &exp2[0], exp2_to_exp3_mask, nbits); | ||||
| 	expect_eq_bitmap(bmap, exp3_1_0, nbits); | ||||
| 
 | ||||
| 	bitmap_fill(bmap, 1024); | ||||
| 	bitmap_replace(bmap, &exp2[0], &exp2[1], exp2_to_exp3_mask, nbits); | ||||
| 	expect_eq_bitmap(bmap, exp3_0_1, nbits); | ||||
| 
 | ||||
| 	bitmap_fill(bmap, 1024); | ||||
| 	bitmap_replace(bmap, &exp2[1], &exp2[0], exp2_to_exp3_mask, nbits); | ||||
| 	expect_eq_bitmap(bmap, exp3_1_0, nbits); | ||||
| } | ||||
| 
 | ||||
| #define PARSE_TIME 0x1 | ||||
| 
 | ||||
| struct test_bitmap_parselist{ | ||||
|  | @ -476,6 +513,7 @@ static void __init selftest(void) | |||
| 	test_zero_clear(); | ||||
| 	test_fill_set(); | ||||
| 	test_copy(); | ||||
| 	test_replace(); | ||||
| 	test_bitmap_arr32(); | ||||
| 	test_bitmap_parselist(); | ||||
| 	test_bitmap_parselist_user(); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Andy Shevchenko
						Andy Shevchenko