1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* bit search implementation 3 * 4 * Copied from lib/find_bit.c to tools/lib/find_bit.c 5 * 6 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 7 * Written by David Howells (dhowells@redhat.com) 8 * 9 * Copyright (C) 2008 IBM Corporation 10 * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au> 11 * (Inspired by David Howell's find_next_bit implementation) 12 * 13 * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease 14 * size and improve performance, 2015. 15 */ 16 17 #include <linux/bitops.h> 18 #include <linux/bitmap.h> 19 #include <linux/kernel.h> 20 21 #if !defined(find_next_bit) || !defined(find_next_zero_bit) || \ 22 !defined(find_next_and_bit) 23 24 /* 25 * This is a common helper function for find_next_bit, find_next_zero_bit, and 26 * find_next_and_bit. The differences are: 27 * - The "invert" argument, which is XORed with each fetched word before 28 * searching it for one bits. 29 * - The optional "addr2", which is anded with "addr1" if present. 30 */ 31 unsigned long _find_next_bit(const unsigned long *addr1, 32 const unsigned long *addr2, unsigned long nbits, 33 unsigned long start, unsigned long invert, unsigned long le) 34 { 35 unsigned long tmp, mask; 36 (void) le; 37 38 if (unlikely(start >= nbits)) 39 return nbits; 40 41 tmp = addr1[start / BITS_PER_LONG]; 42 if (addr2) 43 tmp &= addr2[start / BITS_PER_LONG]; 44 tmp ^= invert; 45 46 /* Handle 1st word. */ 47 mask = BITMAP_FIRST_WORD_MASK(start); 48 49 /* 50 * Due to the lack of swab() in tools, and the fact that it doesn't 51 * need little-endian support, just comment it out 52 */ 53 #if (0) 54 if (le) 55 mask = swab(mask); 56 #endif 57 58 tmp &= mask; 59 60 start = round_down(start, BITS_PER_LONG); 61 62 while (!tmp) { 63 start += BITS_PER_LONG; 64 if (start >= nbits) 65 return nbits; 66 67 tmp = addr1[start / BITS_PER_LONG]; 68 if (addr2) 69 tmp &= addr2[start / BITS_PER_LONG]; 70 tmp ^= invert; 71 } 72 73 #if (0) 74 if (le) 75 tmp = swab(tmp); 76 #endif 77 78 return min(start + __ffs(tmp), nbits); 79 } 80 #endif 81 82 #ifndef find_first_bit 83 /* 84 * Find the first set bit in a memory region. 85 */ 86 unsigned long _find_first_bit(const unsigned long *addr, unsigned long size) 87 { 88 unsigned long idx; 89 90 for (idx = 0; idx * BITS_PER_LONG < size; idx++) { 91 if (addr[idx]) 92 return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); 93 } 94 95 return size; 96 } 97 #endif 98 99 #ifndef find_first_zero_bit 100 /* 101 * Find the first cleared bit in a memory region. 102 */ 103 unsigned long _find_first_zero_bit(const unsigned long *addr, unsigned long size) 104 { 105 unsigned long idx; 106 107 for (idx = 0; idx * BITS_PER_LONG < size; idx++) { 108 if (addr[idx] != ~0UL) 109 return min(idx * BITS_PER_LONG + ffz(addr[idx]), size); 110 } 111 112 return size; 113 } 114 #endif 115