RT-Thread源码-__rt_ffs函数剖析
- 在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函数剖析相关推荐
- 从Thread.start()方法看Thread源码,多次start一个线程会怎么样
这篇文章作为Thread类源码剖析的补充,从一个侧面来看Thread源码.也解答了面试高频问题:"多次start一个线程会怎么样?" 答案是:java.lang.IllegalTh ...
- 从 Android 6.0 源码的角度剖析 Binder 工作原理 | CSDN 博文精选
在从Android 6.0源码的角度剖析Activity的启动过程一文(https://blog.csdn.net/AndrExpert/article/details/81488503)中,我们了解 ...
- Java Thread 源码解析
Thread 源码解析 线程的方法大部分都是使用Native使用,不允许应用层修改,是CPU调度的最基本单元.线程的资源开销相对于进程的开销是相对较少的,所以我们一般创建线程执行,而不是进程执行. T ...
- 从Android 6.0源码的角度剖析View的绘制原理
在从Android 6.0源码的角度剖析Activity的启动过程和从Android 6.0源码的角度剖析Window内部机制原理的文章中,我们分别详细地阐述了一个界面(Activity)从启动到显示 ...
- 【动态代理】从源码实现角度剖析JDK动态代理
相比于静态代理,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定一组接口及目标类对象就能动态的获得代理对象.动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代 ...
- 面试官系统精讲Java源码及大厂真题 - 27 Thread 源码解析
27 Thread 源码解析 书籍乃世人积累智慧之长明灯. 引导语 从本章开始我们开始学习线程的知识,线程是非常有趣的一个章节,大多数同学对于线程 API,属于不用就忘,到用时需要百度的情况,希望通过 ...
- Thread源码-----传实现了Runnable接口的类的实例给Thread的作用
传送门:https://wangchangchung.github.io/2016/12/05/Java常用类源码--Thread源码解析/ 1. thread的构造函数有: public Threa ...
- 深度解析源码strcpy函数
深度解析源码strcpy函数@TOC 前言 提示:这里可以添加本文要记录的大概内容: 本文将介绍c语言中string.h中strcpy函数的源码解析 提示:以下是本篇文章正文内容,下面案例可供参考 一 ...
- 《Spark商业案例与性能调优实战100课》第25课:Spark Hash Shuffle源码解读与剖析
<Spark商业案例与性能调优实战100课>第25课:Spark Hash Shuffle源码解读与剖析
最新文章
- 一个计算机高手的成长(转)
- 来客推多用户商城源码哪里下载?多用户多商城模式有哪些盈利模式?
- 人群密度估计--CNN-based Cascaded Multi-task Learning of High-level Prior and Density Estimation for Crowd
- java线程能做什么_java中的多线程能做什么 ?基本作用能说下吗?
- Android音频底层调试-基于tinyalsa
- java 远程修改linux服务器文件_linux服务器之间复制文件
- 前端学习(3010):vue+element今日头条管理--回顾
- 面向对象程序设计_Task5_Calculator1.5.0
- 40.Linux/Unix 系统编程手册(下) -- 登录记账
- 七月算法机器学习 7 工作流程与模型调优 Kaggle案例泰坦尼克号问题
- wamp php不可用_PHPWAMP开启php
- 照相机成像原理 数码相机的成像原理
- Latex——插入罗马字母或更改字体为公式体
- 隐马尔可夫模型(HMM:Hidden Markov Models)
- 国美易卡利用数据挖掘技术,国美易卡精准分析决策
- 软件设计测试过程术语BD FD DD
- 致远OA漏洞分析、利用与防护合集
- speechSynthesis没有声音
- JavaScript函数式编程入门-计算器应用
- TeamTalk安装部署手册