DTS

Email: BuddyZhang1 buddy.zhang@aliyun.com


_find_next_bit

/*
 * This is a common helper function for find_next_bit, find_next_zero_bit, and
 * find_next_and_bit. The differences are:
 *  - The "invert" argument, which is XORed with each fetched word before
 *    searching it for one bits.
 *  - The optional "addr2", which is anded with "addr1" if present.
 */
static inline unsigned long _find_next_bit(const unsigned long *addr1,
                const unsigned long *addr2, unsigned long nbits,
                unsigned long start, unsigned long invert)
{
        unsigned long tmp;

        if (unlikely(start >= nbits))
                return nbits;

        tmp = addr1[start / BITS_PER_LONG];
        if (addr2)
                tmp &= addr2[start / BITS_PER_LONG];
        tmp ^= invert;

        /* Handle 1st word */
        tmp &= BITMAP_FIRST_WORD_MASK(start);
        start = round_down(start, BITS_PER_LONG);

        while (!tmp) {
                start += BITS_PER_LONG;
                if (start >= nbits)
                        return nbits;

                tmp = addr1[start / BITS_PER_LONG];
                if (addr2)
                        tmp &= addr2[start / BITS_PER_LONG];
                tmp ^= invert;
        }

        return min(start + __ffs(tmp), nbits);
}

_find_next_bit() 函数用于查找下一个置位的位置。参数 addr1 指向第一个 bitmap; 参数 addr2 指向第二个 bitmap;参数 nbts 指向需要查找的范围;参数 start 指定 开始查找的位置;参数 invert 用于翻转 bitmap。函数首先判断 start 是否比 nbits 大,如果打代表已经查过查找的范围,直接返回 nbits;反之可以正常查找。函数继续 计算 start 位于 bitmap 的第几个 long 里,并将对于的 long 存储在 tmp 变量里, 如果此时 addr2 存在,那么将 start 在 addr2 中对应的 long 变量与 tmp 相与, 结果存储在 tmp 中。此时将 tmp 与 参数 invert 做异或运算,相同的 bit 为 0, 不相同的 bit 为 1,以此构造一个 1 的 bitmap。接下来,函数首先通过 BITMAP_FIRST_WORD_MASK() 函数获得 start 对应的掩码,该掩码与 tmp 相与,以 此获得 start 之后的 bit。接着调用 round_down() 函数计算 start 的上一个 long 的位置。如果此时 tmp 的值为 0,那么代表对应的 long 包含的 bit 全为 0,那么 通过 while 循环跳转到下一个 long,并对下一个 long 对应的值做异或运算。最后 调用 __ffs(tmp) 函数获得 tmp 中第一次置位的位置,然后通过 min 比较 start

  • __ffs() 与 nbits 的大小,以此获得第一个置位的位置。

附录

BiscuitOS Home

BiscuitOS Driver

BiscuitOS Kernel Build

Linux Kernel

Bootlin: Elixir Cross Referencer

搭建高效的 Linux 开发环境

赞赏一下吧 🙂

MMU