Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * MSB0 numbered special bitops handling.
0004  *
0005  * The bits are numbered:
0006  *   |0..............63|64............127|128...........191|192...........255|
0007  *
0008  * The reason for this bit numbering is the fact that the hardware sets bits
0009  * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
0010  * from the 'wrong end'.
0011  */
0012 
0013 #include <linux/compiler.h>
0014 #include <linux/bitops.h>
0015 #include <linux/export.h>
0016 
0017 unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size)
0018 {
0019     const unsigned long *p = addr;
0020     unsigned long result = 0;
0021     unsigned long tmp;
0022 
0023     while (size & ~(BITS_PER_LONG - 1)) {
0024         if ((tmp = *(p++)))
0025             goto found;
0026         result += BITS_PER_LONG;
0027         size -= BITS_PER_LONG;
0028     }
0029     if (!size)
0030         return result;
0031     tmp = (*p) & (~0UL << (BITS_PER_LONG - size));
0032     if (!tmp)       /* Are any bits set? */
0033         return result + size;   /* Nope. */
0034 found:
0035     return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
0036 }
0037 EXPORT_SYMBOL(find_first_bit_inv);
0038 
0039 unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
0040                 unsigned long offset)
0041 {
0042     const unsigned long *p = addr + (offset / BITS_PER_LONG);
0043     unsigned long result = offset & ~(BITS_PER_LONG - 1);
0044     unsigned long tmp;
0045 
0046     if (offset >= size)
0047         return size;
0048     size -= result;
0049     offset %= BITS_PER_LONG;
0050     if (offset) {
0051         tmp = *(p++);
0052         tmp &= (~0UL >> offset);
0053         if (size < BITS_PER_LONG)
0054             goto found_first;
0055         if (tmp)
0056             goto found_middle;
0057         size -= BITS_PER_LONG;
0058         result += BITS_PER_LONG;
0059     }
0060     while (size & ~(BITS_PER_LONG-1)) {
0061         if ((tmp = *(p++)))
0062             goto found_middle;
0063         result += BITS_PER_LONG;
0064         size -= BITS_PER_LONG;
0065     }
0066     if (!size)
0067         return result;
0068     tmp = *p;
0069 found_first:
0070     tmp &= (~0UL << (BITS_PER_LONG - size));
0071     if (!tmp)       /* Are any bits set? */
0072         return result + size;   /* Nope. */
0073 found_middle:
0074     return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
0075 }
0076 EXPORT_SYMBOL(find_next_bit_inv);