__builtin_ffs 的使用方法
前言
- __builtin_ffs 在Linux 系统上比较的常见,有一些其他的操作系统,也会看到 __builtin_ffs的使用,作用到底是什么?
- 如何正确的使用 __builtin_ffs?
作用
- __builtin_ffs 是 gcc 内置的函数,获取一个数值:从低位起,第一个1 出现的位置,如0x11,返回的是1,0x00返回的是0,0x02,返回的是2
- 在Keil MDK armcc的编译环境下,需要使用 --gnu的编译选项,armclang 默认支持 gnu选项,所以不需要手动设置
测试环境
- Keil MDK5,这里查看 __builtin_ffs 的返回值,什么场景下需要计算第一个1的返回位置呢?如操作系统的优先级算法中,低位代表高优先级,第一个出现1的位,代表最高的优先级
- uCOS-II 的优先级判定表格,其实就是 __builtin_ffs 计算出来的值
测试代码
- 这里使用RT-Thread Keil MDK5 环境, shell命令验证
struct _ffs
{const char *name;rt_uint32_t value;
};
typedef struct _ffs ffs_t;#define FFS_ITEM(a) { #a, a }static ffs_t ffs_tbl[] =
{FFS_ITEM(0x00),FFS_ITEM(0x01),FFS_ITEM(0x02),FFS_ITEM(0x04),FFS_ITEM(0x08),FFS_ITEM(0x10),FFS_ITEM(0x11),FFS_ITEM(0x12),FFS_ITEM(0x14),FFS_ITEM(0x18),FFS_ITEM(0x20)
};void builtin_ffs_test(void)
{rt_uint32_t tbl_size = sizeof(ffs_tbl) / sizeof(ffs_tbl[0]);for (rt_uint32_t i = 0; i < tbl_size; i++){rt_kprintf("%s -> %d\r\n", ffs_tbl[i].name, __builtin_ffs(ffs_tbl[i].value));}
}MSH_CMD_EXPORT(builtin_ffs_test, builtin_ffs_test);void builtin_ffs_test2(void)
{for (rt_uint32_t i = 0; i < 256; i++){if ((i % 16) == 0x00)rt_kprintf("\r\n");rt_kprintf("%d, ", __builtin_ffs(i));}rt_kprintf("\r\n");
}
MSH_CMD_EXPORT(builtin_ffs_test2, builtin_ffs_test2);
测试结果
msh >builtin_ffs_test
0x00 -> 0
0x01 -> 1
0x02 -> 2
0x04 -> 3
0x08 -> 4
0x10 -> 5
0x11 -> 1
0x12 -> 2
0x14 -> 3
0x18 -> 4
0x20 -> 6
- 这里需要注意:如果第一位为1,就返回的是1,而不是0(C语言一般以0 作为起始)
msh >builtin_ffs_test20, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
5, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
6, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
5, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
7, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
5, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
6, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
5, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
8, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
5, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
6, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
5, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
7, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
5, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
6, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
5, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
- 注意:这个跟uCOS-II 的优先级列表对比,发现除了 第一个0之外,都多了一个1,这是因为 uCOS-II 的优先级判断表,0x01 的1 为BIT0 位置,所以需要: __builtin_ffs(value) - 1
应用方法
- 获取最高优先级的方法,位示图法
- 每个优先级,从低到高,占一个位
- 1024 个优先级
- 1024 / 32 = 32 (32个组),每组 32个优先级(每位代表一个优先级)
- uint32_t prio_group
- uint32_t prio_table[32]
- 优先级设置时,由两部分组成:纵坐标 Y, 横坐标X ,优先级 = Y * 32 + X
- 优先级存在,相应的组 prio_group 置位, prio << 5 响应的 prio_table 置位 prio_table[prio << 5] |= 1 << prio % 32
- 最高优先级:最低位为最高优先级
- 在优先级组 prio_group 中从低位开始,找到第一个1的位置,也就是最高优先级的组,如prioBitY
- 在 prio_table[prioBitY]中,从低位开始,找到第一个1的位置,如prioBitX
- 获取的最高优先级(数值最小的)为: prioBitY << 5 + prioBitX
小结
- 这部分的计算很巧妙,可以快速的获取一个数值,如32位数值,从低位开始,第一个1出现的位置
- 通过分组,可以很快的查找【位图】中最小的数值
__builtin_ffs 的使用方法相关推荐
- 在 Oracle Enterprise Linux 和 iSCSI 上构建您自己的 Oracle RAC 11g 集群
作者:Jeffrey Hunter 了解如何以低于 2,700 美元的费用在 Oracle Enterprise Linux 上安装并配置 Oracle RAC 11g 第 2 版开发集群. 本指南中 ...
- Java面试题大全2021版
一.Java 基础 JDK 和 JRE 有什么区别? JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境. JRE:Java Run ...
- Keil MDK5 编译报Undefined symbol __builtin_ffs 的错误的解决方法
问题描述 __builtin_ffs 的作用,就是求一个32位数值中,从低位开始的1出现的位置,这算是一个内置的函数,所以直接使用,计算会比较的快. RT-Thread 内核代码中,使用这个 函数,作 ...
- Kotlin协程使用,协程使用注意事项,协程中的await方法使用|不使用suspend使用协程
参见 码云 协程使用方法一 (Dispatchers调度器模式) 指定不同线程.同线程会挂起并阻塞(挂起是不影响主线程执行,阻塞是同样的IO线程会阻塞) withContext(Dispatchers ...
- IDEA中将代码块封装为方法,IDEA代码重构快捷键
IDEA中将代码块封装为方法 选中要转换的代码块,快捷键: Windows快捷键:Alt + Shift + M Mac快捷键:Alt + Command + M 如图:
- IDEA自动生成对象所有set方法
idea中有一款插件能够生成对象所有的set方法,GenerateAllSetter :下载地址 步骤1:将下载好的压缩包放在自己记得的文件夹中,在idea中进行导入 步骤2:在本地选中刚才的压缩包, ...
- List元素互换,List元素转换下标,Java Collections.swap()方法实例解析
Java Collections.swap()方法解析 jdk源码: public static void swap(List<?> list, int i, int j) {// ins ...
- java1.8新增超实用Map方法——Map.getOrDefault()和Map.value()方法详解
1. Map.getOrDefault() 翻译一下官方解释: java.util.Map<K, V> V getOrDefault(Object key, V defaultValue) ...
- spring boot项目 中止运行 最常用的几种方法
spring boot项目 中止运行 最常用的几种方法: 1. 调用接口,停止应用上下文 @RestController public class ShutdownController impleme ...
最新文章
- ssm开发框架原理_SSM 单体框架 - 前端开发:视频讲解
- Context-----Activity,Application之间的交流使者
- js中Window跟window的区别
- Linux下静态库的创立与使用
- 在 Excel 中如何使用宏示例删除列表中的重复项
- flutte的第一个hello world程序
- Lyft Level 5 Challenge 2018 - Elimination Round翻车记
- 关于#include头文件问题
- 服务器503能自动恢复吗,服务器出现503错误的原因与解决方法
- 问题六十九:阴影(Shadow)——原理和C++实现
- Mysql 主从复制简易操作指南
- winpcap java封装_利 用jnetpcap 封装libpcap
- Python可视化--常用颜色
- MFC中窗口类、句柄的获取
- 南京大学2021计算机考研复试线是多少,快讯!南京大学2021年考研复试线公布,金融专硕425分!...
- 国内6大网络信息采集和页面数据抓取工具
- Tungsten Fabric解决方案指南-Gateway MX
- python是什么和c++是什么区别_编程c++和python的区别
- 【图形学】布林冯BlinnPhong
- mysql变量环境配置文件_Day44 Mysql环境变量、配置文件(2)
热门文章
- XBOX登录白屏,微软商店无法连接网络
- 文件路径名太长导致IAR编译报错:Fatal Error[Pe1696]: cannot open source file
- 最好的跑步耳机推荐、盘点五款公认最好的跑步耳机
- Blender雕刻模块:2.81新功能遮罩提取(Mask Extract)
- mysql建表是要注意什么问题_MySQL建表注意事项
- HTML5期末大作业:动漫人物介绍网站设计——柯南(5页) 含报告 HTML+CSS+JavaScript dw网页设计 web网页设计与开发
- 前端绘制小猪佩奇(CSS)
- 欧几里德算法、拓展欧几里德、中国剩余定理
- 远程办公:通过cpolar内网穿透,远程桌面控制家里公司内网电脑
- 物联网场景下,基于无线宽带的空中组网研究