Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* bit search implementation
0003  *
0004  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  *
0007  * Copyright (C) 2008 IBM Corporation
0008  * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au>
0009  * (Inspired by David Howell's find_next_bit implementation)
0010  *
0011  * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
0012  * size and improve performance, 2015.
0013  */
0014 
0015 #include <linux/bitops.h>
0016 #include <linux/bitmap.h>
0017 #include <linux/export.h>
0018 #include <linux/math.h>
0019 #include <linux/minmax.h>
0020 #include <linux/swab.h>
0021 
0022 #if !defined(find_next_bit) || !defined(find_next_zero_bit) ||          \
0023     !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) ||    \
0024     !defined(find_next_and_bit)
0025 /*
0026  * This is a common helper function for find_next_bit, find_next_zero_bit, and
0027  * find_next_and_bit. The differences are:
0028  *  - The "invert" argument, which is XORed with each fetched word before
0029  *    searching it for one bits.
0030  *  - The optional "addr2", which is anded with "addr1" if present.
0031  */
0032 unsigned long _find_next_bit(const unsigned long *addr1,
0033         const unsigned long *addr2, unsigned long nbits,
0034         unsigned long start, unsigned long invert, unsigned long le)
0035 {
0036     unsigned long tmp, mask;
0037 
0038     if (unlikely(start >= nbits))
0039         return nbits;
0040 
0041     tmp = addr1[start / BITS_PER_LONG];
0042     if (addr2)
0043         tmp &= addr2[start / BITS_PER_LONG];
0044     tmp ^= invert;
0045 
0046     /* Handle 1st word. */
0047     mask = BITMAP_FIRST_WORD_MASK(start);
0048     if (le)
0049         mask = swab(mask);
0050 
0051     tmp &= mask;
0052 
0053     start = round_down(start, BITS_PER_LONG);
0054 
0055     while (!tmp) {
0056         start += BITS_PER_LONG;
0057         if (start >= nbits)
0058             return nbits;
0059 
0060         tmp = addr1[start / BITS_PER_LONG];
0061         if (addr2)
0062             tmp &= addr2[start / BITS_PER_LONG];
0063         tmp ^= invert;
0064     }
0065 
0066     if (le)
0067         tmp = swab(tmp);
0068 
0069     return min(start + __ffs(tmp), nbits);
0070 }
0071 EXPORT_SYMBOL(_find_next_bit);
0072 #endif
0073 
0074 #ifndef find_first_bit
0075 /*
0076  * Find the first set bit in a memory region.
0077  */
0078 unsigned long _find_first_bit(const unsigned long *addr, unsigned long size)
0079 {
0080     unsigned long idx;
0081 
0082     for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
0083         if (addr[idx])
0084             return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
0085     }
0086 
0087     return size;
0088 }
0089 EXPORT_SYMBOL(_find_first_bit);
0090 #endif
0091 
0092 #ifndef find_first_and_bit
0093 /*
0094  * Find the first set bit in two memory regions.
0095  */
0096 unsigned long _find_first_and_bit(const unsigned long *addr1,
0097                   const unsigned long *addr2,
0098                   unsigned long size)
0099 {
0100     unsigned long idx, val;
0101 
0102     for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
0103         val = addr1[idx] & addr2[idx];
0104         if (val)
0105             return min(idx * BITS_PER_LONG + __ffs(val), size);
0106     }
0107 
0108     return size;
0109 }
0110 EXPORT_SYMBOL(_find_first_and_bit);
0111 #endif
0112 
0113 #ifndef find_first_zero_bit
0114 /*
0115  * Find the first cleared bit in a memory region.
0116  */
0117 unsigned long _find_first_zero_bit(const unsigned long *addr, unsigned long size)
0118 {
0119     unsigned long idx;
0120 
0121     for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
0122         if (addr[idx] != ~0UL)
0123             return min(idx * BITS_PER_LONG + ffz(addr[idx]), size);
0124     }
0125 
0126     return size;
0127 }
0128 EXPORT_SYMBOL(_find_first_zero_bit);
0129 #endif
0130 
0131 #ifndef find_last_bit
0132 unsigned long _find_last_bit(const unsigned long *addr, unsigned long size)
0133 {
0134     if (size) {
0135         unsigned long val = BITMAP_LAST_WORD_MASK(size);
0136         unsigned long idx = (size-1) / BITS_PER_LONG;
0137 
0138         do {
0139             val &= addr[idx];
0140             if (val)
0141                 return idx * BITS_PER_LONG + __fls(val);
0142 
0143             val = ~0ul;
0144         } while (idx--);
0145     }
0146     return size;
0147 }
0148 EXPORT_SYMBOL(_find_last_bit);
0149 #endif
0150 
0151 unsigned long find_next_clump8(unsigned long *clump, const unsigned long *addr,
0152                    unsigned long size, unsigned long offset)
0153 {
0154     offset = find_next_bit(addr, size, offset);
0155     if (offset == size)
0156         return size;
0157 
0158     offset = round_down(offset, 8);
0159     *clump = bitmap_get_value8(addr, offset);
0160 
0161     return offset;
0162 }
0163 EXPORT_SYMBOL(find_next_clump8);