2.2 LOS_BitmapClr()对状态字的某一标志位进行清0操作

对状态字的某一标志位进行清0操作,代码和置1操作对应,比较简单,~(1U << (pos & OS_BITMAP_MASK))表示需要改变内容的状态字的bit位为0,其余位为1,然后通过按位与运算设置状态字UINT32 *bitmap的指定bit位的内容为0。

VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos)
{
    if (bitmap == NULL) {
        return;
    }

    *bitmap &= ~(1U << (pos & OS_BITMAP_MASK));
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

2.3 LOS_HighBitGet()获取状态字中为1的最高位

代码中CLZ(bitmap)是宏,展开为(__builtin_clz(bitmap)),这是编译器内置的高效位运算的库函数,clzcount leading zeros的缩写,就是统计二进制数值中高位区开头的全是0的数目。使用OS_BITMAP_MASK减去该值,结果就是状态字中的1的最高位。

UINT16 LOS_HighBitGet(UINT32 bitmap)
{
    if (bitmap == 0) {
        return LOS_INVALID_BIT_INDEX;
    }

    return (OS_BITMAP_MASK - CLZ(bitmap));
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

2.4 LOS_LowBitGet()获取状态字中为1的最低位

代码其中CTZ(bitmap)是宏,展开为(__builtin_ctz(value)),这是编译器内置的高效位运算的库函数,ctzcount trailing zeros的缩写,就是统计二进制数值中低位区结尾的全是0的数目,该结果就是状态字中的1的最低位。

UINT16 LOS_LowBitGet(UINT32 bitmap)
{
    if (bitmap == 0) {
        return LOS_INVALID_BIT_INDEX;
    }

    return CTZ(bitmap);
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

2.5 LOS_BitmapSetNBits()对状态字的连续标志位进行置1操作

可以使用LOS_BitmapSetNBits()函数对状态字的连续比特位进行置1操作,第一个参数是需要改变bit位内容的状态字UINT32 *bitmap,第二个参数是需要置1的bit位开始数start,第三个参数是需要置1的数量numsSet。由于bit位开始数start并没有限制在[0,31],所以实际上设置的可能是UINT32 *bitmap状态字后面的状态字,需要根据业务实际情况进行设置,避免覆写其他内存。同样,需要置1的数量numsSet也可能跨多个状态字。如图所示:

我们看下代码,⑴处计算出需要操作的状态字,其中BITMAP_WORD(start)计算相对状态字bitmap需要偏移的数量,如果start处于区间[0,31],BITMAP_WORD(start)等于0,操作的就是状态字bitmap。如果start处于区间[32,63],BITMAP_WORD(start)等于1,操作的就是状态字bitmap后面的第一个状态字,以此类推。⑵处size可以和bit位开始数start结合来理解,size就是需要置1的bit位结束位数。⑶处需要置1操作的bit位的位数,⑷是对应需要置1操作的bit位的掩码。

⑸处如果条件成立,说明需要置1操作需要跨多个状态字进行操作,代码会一个状态字处理完毕,再去处理下一个状态字。⑹处把当前状态字的相应的bit位进行置1操作,然后执行⑺把剩余需要置1的位数减去已经置1的位数。⑻处更新bitsToSetmaskToSet,然后指针p指向下一个状态字。⑼处如果需要置1的位数大于0,并且此时已经可以在一个状态字内完成操作,执行⑽处计算需要置1操作的掩码,从bit开始位到结束位需要进行置1。⑾处代码执行置1操作,完成对状态字的连续标志位进行置1操作。

VOID LOS_BitmapSetNBits(UINTPTR *bitmap, UINT32 start, UINT32 numsSet)
{
⑴  UINTPTR *p = bitmap + BITMAP_WORD(start);
⑵  const UINT32 size = start + numsSet;
⑶  UINT16 bitsToSet = BITMAP_BITS_PER_WORD - (start % BITMAP_BITS_PER_WORD);
⑷  UINTPTR maskToSet = BITMAP_FIRST_WORD_MASK(start);

⑸  while (numsSet > bitsToSet) {
⑹      *p |= maskToSet;
⑺      numsSet -= bitsToSet;
⑻      bitsToSet = BITMAP_BITS_PER_WORD;
        maskToSet = OS_BITMAP_WORD_MASK;
        p++;
    }
⑼  if (numsSet) {
⑽      maskToSet &= BITMAP_LAST_WORD_MASK(size);
        *p |= maskToSet;
    }
}

 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

2.6 LOS_BitmapClrNBits()对状态字的连续标志位进行清0操作

可以使用LOS_BitmapClrNBits()函数对状态字的连续比特位进行清0操作,第一个参数是需要改变bit位内容的状态字UINT32 *bitmap,第二个参数是需要清0的bit位开始数start,第三个参数是需要清0的数量numsClear。该函数是函数LOS_BitmapSetNBits()的反向操作,代码解释可以参考函数LOS_BitmapSetNBits()

VOID LOS_BitmapClrNBits(UINTPTR *bitmap, UINT32 start, UINT32 numsClear)
{
    UINTPTR *p = bitmap + BITMAP_WORD(start);
    const UINT32 size = start + numsClear;
    UINT16 bitsToClear = BITMAP_BITS_PER_WORD - (start % BITMAP_BITS_PER_WORD);
    UINTPTR maskToClear = BITMAP_FIRST_WORD_MASK(start);

    while (numsClear >= bitsToClear) {
        *p &= ~maskToClear;
        numsClear -= bitsToClear;
        bitsToClear = BITMAP_BITS_PER_WORD;
        maskToClear = OS_BITMAP_WORD_MASK;
        p++;
    }
    if (numsClear) {
        maskToClear &= BITMAP_LAST_WORD_MASK(size);
        *p &= ~maskToClear;
    }
}

 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

2.8 LOS_BitmapFfz()获取从最低有效位开始的第一个0的bit位

可以使用LOS_BitmapFfz()函数获取从最低有效位开始的第一个0的bit位位数,第一个参数是需要改变bit位内容的状态字UINT32 *bitmap,第二个参数numBits表示最大的位数,对返回值进行限制,需要在指定的位数内找到符合条件的位数,否则返回-1。

在看函数代码之前,先了解下Ffz()函数,如下:调用内嵌函数__builtin_ffsl()可以获取一个unsigned long类型数字的二进制形式的从左开始的第一个1的位数,这个位数从1开始计数。比如对于二进制数字0110,该函数会返回2。在下面的函数中,给函数__builtin_ffsl()传入的参数进行了取反,并减去了1,所以Ffz()函数返回一个数字从左开始的第一个0的位数,这个位数从0开始计数。

/* find first zero bit starting from LSB */
STATIC INLINE UINT16 Ffz(UINTPTR x)
{
    return __builtin_ffsl(~x) - 1;
}

 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

我们接着看下函数LOS_BitmapFfz()的代码。⑴处根据位数numBits计算出对应的状态字的数量,然后依次循环每一个状态字,⑵处如果状态字全为1,则继续循环,否则执行⑶。执行到⑶说明,,前面有i个状态字的各个位全为1。i * BITMAP_BITS_PER_WORD + Ffz(bitmap[i])就表示各个状态字的二进制位中,从左到右第一个0的位置。⑷处如果获取的位数小于第二个参数,则返回获取的位数,否则返回-1。如下图所示:

源代码如下:

INT32 LOS_BitmapFfz(UINTPTR *bitmap, UINT32 numBits)
{
    INT32 bit, i;

⑴  for (i = 0; i < BITMAP_NUM_WORDS(numBits); i++) {
⑵      if (bitmap[i] == OS_BITMAP_WORD_MASK) {
            continue;
        }
⑶      bit = i * BITMAP_BITS_PER_WORD + Ffz(bitmap[i]);
⑷      if (bit < numBits) {
            return bit;
        }
        return -1;
    }
    return -1;
}

 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

小结

本文带领大家一起剖析了鸿蒙轻内核的位操作模块的源代码。

如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

系统架构分析:https://qr18.cn/CgxrRy

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

写在最后

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/maniuT/article/details/139600616","extend1":"pc","ab":"new"}">> id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type2" id="blog_extension"> class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}"> class="blog_extension_card_left"> class="blog_extension_card_cont"> 鸿蒙开发学习资料领取!!! class="blog_extension_card_cont_r"> 微信名片
注:本文转载自blog.csdn.net的沧海一笑-dj的文章"https://blog.csdn.net/dengjin20104042056/article/details/98444966"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!