Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2305045
  • 博文数量: 318
  • 博客积分: 8752
  • 博客等级: 中将
  • 技术积分: 4944
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-23 07:56
文章分类

全部博文(318)

文章存档

2019年(1)

2017年(2)

2016年(12)

2015年(2)

2014年(1)

2013年(17)

2012年(22)

2011年(9)

2010年(37)

2009年(33)

2008年(44)

2007年(43)

2006年(95)

分类: LINUX

2010-05-18 21:42:56

unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
        unsigned long offset)
{
    const unsigned long *p = addr + BITOP_WORD(offset); // offset位于p指向的long地址32位空间
    unsigned long result = offset & ~(BITS_PER_LONG-1); // offset是第result个4字节
    unsigned long tmp;

    if (offset >= size)
        return size;
    size -= result;                                     // 调整32位整倍数上
    offset %= BITS_PER_LONG;                            // offset位于32位的第几位
    if (offset) {                                       // offset不在一个long数据的第0位上,在1-31位中[luther.gliethttp]
        tmp = *(p++);
        tmp |= ~0UL >> (BITS_PER_LONG - offset);        // 将0-offset数据填充上1.
        if (size < BITS_PER_LONG)                       // 不足32bits
            goto found_first;
        if (~tmp)                                       // 取非非0说明含有0值
            goto found_middle;
        size -= BITS_PER_LONG;                          // 如果上面~tmp等于0,那么说明该*p数据为32位全1.[luther.gliethttp]
        result += BITS_PER_LONG;
    }
    while (size & ~(BITS_PER_LONG-1)) {                 // 好了,执行到这里,我们的offset已经处在4字节的第0位上,下面进行
        if (~(tmp = *(p++)))                            // 4字节快速查询.如果~tmp非0,说明该32位数据中含有0数据,找到.[luther.gliethttp]
            goto found_middle;
        result += BITS_PER_LONG;                        // 到下一个4字节空间
        size -= BITS_PER_LONG;                          // 减少4字节数据
    }
    if (!size)                                          // size等于0,说明首先size等于4字节整倍数,其次所有数据已经查完,
        return result;                                  // 所有数据全部为1,没有发现0位,result等于size.[luther.gliethttp]
    tmp = *p;                                           // size不是32位整倍数,还剩几个bit没有检查,继续执行下面检查工作.[luther.gliethtp]

found_first:
    tmp |= ~0UL << size;                                // 现在0-size为有效数据,size-31为未使用空间,所以先将size-31置成全1.
    if (tmp == ~0UL)    /* Are any bits zero? */        // 如果tmp全1,那么说明就没找找1个
        return result + size;    /* Nope. */             // result+size就等于函数传入的参数size大小.[luther.gliethttp]
found_middle:
    return result + ffz(tmp);                           // 我们在32位数据的0-31中发现必定存在0位值,计算他是第几位.[luther.gliethttp]
}

#define ffz(x)  __ffs(~(x))                             // __ffs找到第一次出现1值的偏移值,从bit0开始到bit31依次找[luther.gliethttp]
/**
 * __ffs - find first bit in word.
 * @word: The word to search
 *
 * Undefined if no bit exists, so code should check against 0 first.
 */
static inline unsigned long __ffs(unsigned long word)
{
    int num = 0;

#if BITS_PER_LONG == 64
    if ((word & 0xffffffff) == 0) {
        num += 32;
        word >>= 32;
    }
#endif
    if ((word & 0xffff) == 0) {                         // 低16位没有1值,那么num加16,同时高16位移动到低16位
        num += 16;                                      // 这样低16位永远都是去掉根本不存在的那种必然情况后的数据.
        word >>= 16;
    }
    if ((word & 0xff) == 0) {                           // 低8位是否有
        num += 8;
        word >>= 8;
    }
    if ((word & 0xf) == 0) {
        num += 4;
        word >>= 4;
    }
    if ((word & 0x3) == 0) {
        num += 2;
        word >>= 2;
    }
    if ((word & 0x1) == 0)
        num += 1;
    return num;                                         // 这样num就是出现1的偏移值了.[luther.gliethttp]
}
阅读(3566) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~