Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1306591
  • 博文数量: 860
  • 博客积分: 425
  • 博客等级: 下士
  • 技术积分: 1464
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-20 19:57
个人简介

对技术执着

文章分类

全部博文(860)

文章存档

2019年(16)

2018年(12)

2015年(732)

2013年(85)

2012年(15)

我的朋友

分类: LINUX

2015-03-14 17:13:11

浅析alsa声卡驱动中检测是否有1个元素被置位的小算法

#define SNDRV_MASK_BITS    64    /* we use so far 64bits only */
#define SNDRV_MASK_SIZE    (SNDRV_MASK_BITS / 32)

#define SNDRV_MASK_MAX    256
struct snd_mask {
    __u32 bits[(SNDRV_MASK_MAX+31)/32];
};

// 如下函数用来检测SNDRV_MASK_BITS个bit位数据中是否有多余1个bit被置位了[luther.gliethttp]
static inline int snd_mask_single(const struct snd_mask *mask)
{
    int i, c = 0;
    for (i = 0; i < SNDRV_MASK_SIZE; i++) {
        if (! mask->bits[i])                        // 如果当前32bits全0,那么表示空,continue到下一个32bits组
            continue;
        // 执行到这里说明该32bits位组中一定有>=1个bit被置位[luther.gliethttp],
        // 下面继续判断该32bits位组中只有1个bit置位,还是多于1个bit.
        if (mask->bits[i] & (mask->bits[i] - 1))    // 这是算法的核心,其实就是简单的利用了减法借位原理:
            return 0;                               // 因为减1操作,会向高位借位,那么第1次出现1的高位,将因为借位置0,
        // 而从第0位到第1次出现1之间的所有bits都将取反,而第1次出现1的位置到第31bit之间的数据将保持不变,比如:
        // 只有1个bit置位:00001000,那么减1之后为00000111
        // 多余1个bit置位:01001000,那么减1之后为01000111
        // 所以如果mask->bits[i] & (mask->bits[i] - 1)非0,说明该32bits位组一定有2个或2个以上bit被置位
        // 那么直接return 0;表示有多于1个bit都被置位[luther.gliethttp]
        if (c)        // 如果c非0,说明之前的mask->bits[0..i-1]的位组中已经有1个仅仅有1个bit
            return 0; // 被置位的情况,所以加上i这次的,那么就表示mask->bits[]至少包含2个bit置位
                      // 所以直接return 0;表示有多于1个bit都被置位[luther.gliethttp]
        // 如果执行到这里,说明当前i对应的mask->bits[i]这个32bits位组只有1个bit被置位.
        c++;
    }
    // 表示<=1个bit被置位,都当作有1个bit置位[luther.gliethttp],
    // 如果想细分是否真的有1个bit被置位,可以通过
    // if (c) return 1;
    return 1;
}
阅读(509) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~