find.c (1918B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * MSB0 numbered special bitops handling. 4 * 5 * The bits are numbered: 6 * |0..............63|64............127|128...........191|192...........255| 7 * 8 * The reason for this bit numbering is the fact that the hardware sets bits 9 * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap 10 * from the 'wrong end'. 11 */ 12 13#include <linux/compiler.h> 14#include <linux/bitops.h> 15#include <linux/export.h> 16 17unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size) 18{ 19 const unsigned long *p = addr; 20 unsigned long result = 0; 21 unsigned long tmp; 22 23 while (size & ~(BITS_PER_LONG - 1)) { 24 if ((tmp = *(p++))) 25 goto found; 26 result += BITS_PER_LONG; 27 size -= BITS_PER_LONG; 28 } 29 if (!size) 30 return result; 31 tmp = (*p) & (~0UL << (BITS_PER_LONG - size)); 32 if (!tmp) /* Are any bits set? */ 33 return result + size; /* Nope. */ 34found: 35 return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); 36} 37EXPORT_SYMBOL(find_first_bit_inv); 38 39unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size, 40 unsigned long offset) 41{ 42 const unsigned long *p = addr + (offset / BITS_PER_LONG); 43 unsigned long result = offset & ~(BITS_PER_LONG - 1); 44 unsigned long tmp; 45 46 if (offset >= size) 47 return size; 48 size -= result; 49 offset %= BITS_PER_LONG; 50 if (offset) { 51 tmp = *(p++); 52 tmp &= (~0UL >> offset); 53 if (size < BITS_PER_LONG) 54 goto found_first; 55 if (tmp) 56 goto found_middle; 57 size -= BITS_PER_LONG; 58 result += BITS_PER_LONG; 59 } 60 while (size & ~(BITS_PER_LONG-1)) { 61 if ((tmp = *(p++))) 62 goto found_middle; 63 result += BITS_PER_LONG; 64 size -= BITS_PER_LONG; 65 } 66 if (!size) 67 return result; 68 tmp = *p; 69found_first: 70 tmp &= (~0UL << (BITS_PER_LONG - size)); 71 if (!tmp) /* Are any bits set? */ 72 return result + size; /* Nope. */ 73found_middle: 74 return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); 75} 76EXPORT_SYMBOL(find_next_bit_inv);