Kernel散记——常见宏

1,likely()和unlikey()

1.1,来自哪里?@kernel.h

#  define likely(x)     (__builtin_expect(!!(x), 1))

#  define unlikely(x)     (__builtin_expect(!!(x), 0))

1.2,作用?

代码优化。详细占说是告诉编译器,优化预取指。

1.3,细节?

细节也说不清,说个大概;

#define likely(x) __builtin_expect(!!(x), 1)也就是说明x==1是“经常发生的”或是“很可能发生的”。

使用likely ,执行if后面语句的可能性大些,编译器将if{}是的内容编译到前面, 使用unlikely ,执行else后面语句的可能性大些,编译器将else{}里的内容编译到前面。这样有利于cpu预取,提高预取指令的正确率,因而可提高效率。

1.4,举个例子

ret = copy_to_user(to, fifo->data + off, l);

if (unlikely(ret))

ret = DIV_ROUND_UP(ret + len - l, esize);

else {

ret = copy_to_user(to + l, fifo->data, len - l);

...

}

也就是说ret=0的可能性很大,else的内容被编译到if之前,优化处理器取指

另外,使用!!(x)而不使用x是把x值转化为bool值。这个也是kernel常见的。

2,在Input 子系统中,对bits有几个常用的位操作宏

@include/linux/input.h struct input_dev

unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];

先看定义:

#define BITS_TO_LONGS(nr)     DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))

#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))

在32位系统中,long占用4个字节。

BITS_TOLONGS就是探测一下共总有多少个32bit。

比较ABS_CNT = 0x3f + 1 = 0x40

(也就是说0x40 = 64 = 32 *2

两个long<32bit>型就可以装下)

所以BITS_TO_LONGS(ABS_CNT) = 2

@input.c

test_bit(ABS_MT_TRACKING_ID, dev->absbit)

test_bit 简单地说就是返回(dev->absbit)这个地址,对应的位(ABS_MT_TRACKING)的值。

@input.c

__set_bit(EV_SYN, dev->evbit);

定义:

/**

* __set_bit - Set a bit in memory

* @nr: the bit to set

* @addr: the address to start counting from

*

* Unlike set_bit(), this function is non-atomic and may be reordered.

* If it‘s called on the same region of memory simultaneously, the effect

* may be that only one operation succeeds.

*/

static inline void __set_bit(int nr, volatile unsigned long *addr)

{

unsigned long mask = BIT_MASK(nr);

unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);

*p  |= mask;

}

简单地说,就是把(dev-evbit)这个内存开始的地址的第EV_SYN(0)位

综上:

理解了上述代码,则其它比特位操作API就容易懂了。

__clear_bit: 将addr所指的地址处的值第nr位清0,方法一般 addr[nr/32] & 11111011111

__change_bit: 将addr所指的地址处的值第nr位取反,方法一般 addr[nr/32]  ^ 00000100000

__test_and_set_bit:将addr所指的地址处的值第nr位置1,返回该bit原始值(0或1);

__test_and_clear_bit:将addr所指的地址处的值第nr位清0,返回该bit原始值(0或1);

__test_and_change_bit:将addr所指的地址处的值第nr位取反,返回该bit原始值(0或1);

test_bit:即测试nr位是否被置位,置位返回1;

3,还是在Input系统中,关于bitmap的操作。

@input.c input_match_device()函数

if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX))

bitmap_subset src1的nbits指定位数中设置1的比特位是src2中nbits指定位数中设置1的比特的子集,则返回1,否则返回0。精确到位。

关于bitmap,参考

http://blog.chinaunix.net/uid-20608849-id-3027971.html

  • bitmap_zero 清所有比特位为0,被用来初始化位图。圆整到unsigned long。
  • bitmap_fill 置nbits指定个数的比特位为1。精确到位。
  • bitmap_copy 从src复制所有比特位到dst。圆整到unsigned long。
  • bitmap_and 将nbits指定的位数按位与结果存放到dst。圆整到unsigned long。
  • bitmap_or 将nbits指定的位数按位或结果存放到dst。圆整到unsigned long。
  • bitmap_xor 将nbits指定的位数按位异或结果存放到dst。圆整到unsigned long。
  • bitmap_andnot 根据nbits指定的位数, 将src1按位与上src2的按位非,结果存放到dst。圆整到unsigned long。
  • bitmap_complement 根据nbits指定的位数, 按位取反后存放到dst。精确到位。
  • bitmap_equal 比较nbits指定的位数,如果这些为全部相同返回1,否则返回0。精确到位。
  • bitmap_intersects 比较nbits指定的位数中是否有重合(相交Overlap)的1比特位,也即src1和src2中有共同设置为1的标志位。有则返回1,否则返回0。精确到位。
  • bitmap_subset src1的nbits指定位数中设置1的比特位是src2中nbits指定位数中设置1的比特的子集,则返回1,否则返回0。精确到位。
  • bitmap_empty 测试src中的低nbits位是否全为0,是则返回1,否则返回0。精确到位。
  • bitmap_full 测试src中的低nbits位是否全为1,是则返回1,否则返回0。精确到位。
  • bitmap_weight 返回低nbits位的汉明重量(Hamming Weight)。
  • bitmap_shift_right 逻辑右移n位,左边补0。n可以大于nbits数。圆整到unsigned long。
  • bitmap_shift_left 逻辑左移n位,右边补0。n可以大于nbits数。圆整到unsigned long。
时间: 2024-10-05 12:24:22

Kernel散记——常见宏的相关文章

Linux 内核常见宏定义

我们在阅读Linux内核是,常见到这些宏 __init, __initdata, __initfunc(), asmlinkage, ENTRY(), FASTCALL()等等.它们定义在 /include/linux/init.h 和 /include/linux/linkage.h 以及其他一些.h 文件中. 1. __init 位置:/include/linux/init.h 定义: #define __init   __attribute__ ((__section__ (".init.

Kernel散记——系统调用

这里是指arm linux架构(Android4.4) 1,referen http://blog.csdn.net/myarrow/article/details/7036266 1.1,这是讲得比较全面.读完之后,你大致可以讲得清系统调用的过程 "系统调用就是用户民通过swi指令陷入内核,cpu由user模式进入svc模式的过程,调用的过程大致是先备份当前任务的上下文(相应的堆栈信息),然后通过swi指令的参数,来找到对应的系统调用表,执行完系统调用,把返回值写在指定的寄存器,恢复原来的现场

【编程基础】C语言常见宏定义

我们在使用C语言编写程序的时候,常常会使用到宏定义以及宏编译指令,有的可能比较常用,有的可能并不是很常用,是不是所有的C语言宏定义以及宏指令你都清楚呢? 指令 用途详细介绍 # 空指令,无任何效果 #include 包含另外一个文件 #define 定义宏 #undef 取消已定义的宏 #if 如果给定条件为真,则编译下面代码 #ifdef 如果宏已经定义,则编译下面代码 #ifndef 如果宏没有定义,则编译下面代码 #elif 如果前面的#if给定条件不为真,当前条件为真,则编译下面代码,其

iOS开发-常见宏定义

有些时候,我们需要将代码简洁化,这样便于读代码.我们可以将一些不变的东东抽取出来,将变化的东西作为参数.定义为宏,这样在写的时候就简单多了. 下面例举了一些常用的宏定义和大家分享: 1. 判断设备的操作系统是不是ios71.#define IOS7   (  [[[UIDevice currentDevice].systemVersion doubleValue] >= 7.0] ) 2. 判断当前设备是不是iPhone51.#define kScreenIphone5    (([[UIScr

Windows常见宏的使用

WIN32_LEAN_AND_MEAN 1.  参考资料:https://msdn.microsoft.com/en-us/library/windows/desktop/aa383745(v=vs.85).aspx 2.  使用说明: You can reduce the size of the Windows header files by excluding some of the less common API declarations as follows: • Define WIN3

常见宏任务与微任务

宏任务(macrotasks): 主js.UI渲染.setTimeout.setInterval.setImmediately.requestAnimationFrame.I/O等 微任务(microtasks):process.nextTick().promise.Object.observe()等 原文地址:https://www.cnblogs.com/yanze/p/11820302.html

Cocos2d-x 常见宏

1)NS_CC_BEGIN cocos2d命名空间開始 2) NS_CC_END  cocos2d命名空间结束 3)USING_NS_CC 声明cocos2d命名空间 4)CC_SYNTHESIZE_READONLY(varType, varName, funName)声明一个成员变量以及getfunName函数,没有set函数.getfunName已经实现,事实上现就是返回这个值. 5)CC_SYNTHESIZE_READONLY_PASS_BY_REF(varType, varName, f

js 宏任务和微任务

1.概念:宏任务(macrotask )和微任务(microtask ) 表示异步任务的两种分类.常见宏任务:I/O .setTimeout.setInterval:微任务:Promise.then catch finally.process.nextTick 在挂起任务时,JS 引擎会将 所有任务 按照类别分到这两个队列中, 首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行: 之后再取 m

rpm包制作(一)

rpm介绍 rpm的全称是RedhatPackage Manager,常见的使用rpm软件包的系统主要有Fedora.CentOS.openSUSE.SUSE企业版.PCLinuxOS等.使用deb软件包后缀的类Debian系统最常见的有Debian.Ubuntu.Finnix等. 从软件运行的结构来说,一个软件主要可以分为三个部分:可执行程序.配置文件和动态库.当然还有可能会有相关文档.手册.供二次开发用的头文件以及一些示例程序等等.可执行文件是必须的,其他部分都是可选的. 制作rpm软件包的