• 在RT-Thread中,获取已就绪最高优先级线程索引会使用此函数。而此函数所包含的算法为bitmap算法。
  • 为什么使用此函数获取已就绪最高优先级线程索引?为什么使用bitmap算法?目的在于提升索引值获取的执行效率,以及保证系统的稳定执行。
  • 通常,为了获取已就绪最高优先级线程,最简单的方法就是遍历当前线程列表中的每一个线程状态及优先级,通过比较最后获取。而这种方法会随着最大支持线程数的增加而增加时间复杂度O(n)(采用bitmap算法后时间复杂度为O(1)),且执行时间非恒定,影响系统的稳定。
  • 此函数在RT-Thread中实现如下,
const rt_uint8_t __lowest_bit_bitmap[] =
{/* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};/*** This function finds the first bit set (beginning with the least significant bit)* in value and return the index of that bit.** Bits are numbered starting at 1 (the least significant bit).  A return value of* zero from any of these functions means that the argument was zero.** @return return the index of the first bit set. If value is 0, then this function* shall return 0.*/
int __rt_ffs(int value)
{if (value == 0) return 0;if (value & 0xff)return __lowest_bit_bitmap[value & 0xff] + 1;if (value & 0xff00)return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;if (value & 0xff0000)return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
}
  • 以上C实现中,提供了一个__lowest_bit_bitmap,这个最低位图表是结合系统支持最大线程数(256),提前计算出来的最高优先级结果。假设设置系统最大线程数为32,则通常会使用一个32bit变量来表示所有线程的状态,每一个bit,1表示就绪,0表示挂起,若此变量值为6,则表示当前优先级为1,优先级为2的线程处于就绪态,那么此时的已就绪最高优先级线程索引就为1;若此变量值为15,则表示前四优先级线程均为就绪态,那么此时的已就绪最高优先级线程索引就为0。其余,以此类推。
  • 在最大线程数设置为大于32的情况下,在RT-Thread中采用了二级位图的形式,即将所有线程已8个为一组的方式分为若干组。那么,同理,这时候在获取已就绪最高优先级线程索引前增加一步,获取已就绪最高优先级线程组索引。
  • RT-Thread中还针对各处理器及编译器提供了ARM汇编的优化实现,适配Cortex-M4处理器实现如下:
/*** This function finds the first bit set (beginning with the least significant bit)* in value and return the index of that bit.** Bits are numbered starting at 1 (the least significant bit).  A return value of* zero from any of these functions means that the argument was zero.** @return return the index of the first bit set. If value is 0, then this function* shall return 0.*/
#if defined(__CC_ARM) || defined(__CLANG_ARM)
__asm int __rt_ffs(int value)
{// 判断value是否为0,若为0则直接返回CMP     r0, #0x00BEQ     exitRBIT    r0, r0          // 反转value的高低位CLZ     r0, r0            // 计算value低bit位为0的个数ADDS    r0, r0, #0x01   // 以上得到的结果+1,则得到为1的最低bit索引exitBX      lr
}
#elif defined(__IAR_SYSTEMS_ICC__)
int __rt_ffs(int value)
{if (value == 0) return value;asm("RBIT %0, %1" : "=r"(value) : "r"(value));asm("CLZ  %0, %1" : "=r"(value) : "r"(value));asm("ADDS %0, %1, #0x01" : "=r"(value) : "r"(value));return value;
}
#elif defined(__GNUC__)
int __rt_ffs(int value)
{return __builtin_ffs(value);
}
#endif

RT-Thread源码-__rt_ffs函数剖析相关推荐

  1. 从Thread.start()方法看Thread源码,多次start一个线程会怎么样

    这篇文章作为Thread类源码剖析的补充,从一个侧面来看Thread源码.也解答了面试高频问题:"多次start一个线程会怎么样?" 答案是:java.lang.IllegalTh ...

  2. 从 Android 6.0 源码的角度剖析 Binder 工作原理 | CSDN 博文精选

    在从Android 6.0源码的角度剖析Activity的启动过程一文(https://blog.csdn.net/AndrExpert/article/details/81488503)中,我们了解 ...

  3. Java Thread 源码解析

    Thread 源码解析 线程的方法大部分都是使用Native使用,不允许应用层修改,是CPU调度的最基本单元.线程的资源开销相对于进程的开销是相对较少的,所以我们一般创建线程执行,而不是进程执行. T ...

  4. 从Android 6.0源码的角度剖析View的绘制原理

    在从Android 6.0源码的角度剖析Activity的启动过程和从Android 6.0源码的角度剖析Window内部机制原理的文章中,我们分别详细地阐述了一个界面(Activity)从启动到显示 ...

  5. 【动态代理】从源码实现角度剖析JDK动态代理

    相比于静态代理,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定一组接口及目标类对象就能动态的获得代理对象.动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代 ...

  6. 面试官系统精讲Java源码及大厂真题 - 27 Thread 源码解析

    27 Thread 源码解析 书籍乃世人积累智慧之长明灯. 引导语 从本章开始我们开始学习线程的知识,线程是非常有趣的一个章节,大多数同学对于线程 API,属于不用就忘,到用时需要百度的情况,希望通过 ...

  7. Thread源码-----传实现了Runnable接口的类的实例给Thread的作用

    传送门:https://wangchangchung.github.io/2016/12/05/Java常用类源码--Thread源码解析/ 1. thread的构造函数有: public Threa ...

  8. 深度解析源码strcpy函数

    深度解析源码strcpy函数@TOC 前言 提示:这里可以添加本文要记录的大概内容: 本文将介绍c语言中string.h中strcpy函数的源码解析 提示:以下是本篇文章正文内容,下面案例可供参考 一 ...

  9. 《Spark商业案例与性能调优实战100课》第25课:Spark Hash Shuffle源码解读与剖析

    <Spark商业案例与性能调优实战100课>第25课:Spark Hash Shuffle源码解读与剖析

最新文章

  1. 一个计算机高手的成长(转)
  2. 来客推多用户商城源码哪里下载?多用户多商城模式有哪些盈利模式?
  3. 人群密度估计--CNN-based Cascaded Multi-task Learning of High-level Prior and Density Estimation for Crowd
  4. java线程能做什么_java中的多线程能做什么 ?基本作用能说下吗?
  5. Android音频底层调试-基于tinyalsa
  6. java 远程修改linux服务器文件_linux服务器之间复制文件
  7. 前端学习(3010):vue+element今日头条管理--回顾
  8. 面向对象程序设计_Task5_Calculator1.5.0
  9. 40.Linux/Unix 系统编程手册(下) -- 登录记账
  10. 七月算法机器学习 7 工作流程与模型调优 Kaggle案例泰坦尼克号问题
  11. wamp php不可用_PHPWAMP开启php
  12. 照相机成像原理 数码相机的成像原理
  13. Latex——插入罗马字母或更改字体为公式体
  14. 隐马尔可夫模型(HMM:Hidden Markov Models)
  15. 国美易卡利用数据挖掘技术,国美易卡精准分析决策
  16. 软件设计测试过程术语BD FD DD
  17. 致远OA漏洞分析、利用与防护合集
  18. speechSynthesis没有声音
  19. JavaScript函数式编程入门-计算器应用
  20. TeamTalk安装部署手册

热门文章

  1. 跑步运动蓝牙耳机哪个好?跑步无线运动蓝牙耳机推荐
  2. XP系统如搭建ftp服务器,XP系统如搭建ftp服务器
  3. win10蓝牙链接上的标准串行com口无法删除
  4. 程序员期望月薪那些事儿
  5. sqlite 数据库连接问题以及解决方法
  6. 如果禅道忘记了管理员密码怎么拯救
  7. 女孩子生理期最易达成的5种效果[女生必看,男生为了女朋友也要转
  8. Pygame实战之外星人入侵NO.9——消灭外星人
  9. U3D游戏开发工程师正确入行姿势指南
  10. NCNN+Int8+YOLOv4量化模型和实时推理