linux kernel中常见的宏
阅读数:246 评论数:0
跳转到新版页面分类
Linux
正文
__CONCAT,连接两个参数,##用于粘贴两个参数,#用于替换参数
#define __CONCAT(a, b) a ## b
宏中使用do{...}while(0)的意义,用于定义复杂的宏,避免宏展开后分号造成编译不通过。
BUG_ON(condition)
条件为真,产生崩溃,相对应有WARN_ON
BUILD_BUG_ON
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
!!(e) 对 e 的结果进行两次求非。如果e为0,则结果为0;如果 e 不为 0,则结果为1。所以上述表达式的结果有两种:
-
condition为真时,sizeof(char[-1]),产生错误,编译不通过
-
condition为假时,sizeof(char[1]),编译通过
BUILD_BUG_ON_ZERO(e)
define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
检查表达式e是否为0,为0编译通过且返回0;如果不为0,则编译不通过。
typecheck宏
/*
* Check at compile time that something is of a particular type.
* Always evaluates to 1 so you may use it easily in comparisons.
*/
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
/*GCC的一个扩展特性,形如({ ... })这样的代码块会被视为一条语句,
* 其计算结果是{ ... }中最后一条语句的计算结果。
* 所以上述会返回1
*/
/*
* Check at compile time that 'function' is a certain type, or is a pointer
* to that type (needs to use typedef for the function type.)
*/
#define typecheck_fn(type,function) \
({ typeof(type) __tmp = function; \
(void)__tmp; \
})
typecheck用于检查x是否为type类型,如果不是会抛出(warning: comparison of distinct pointer types lacks a cast),typecheck_fn用于检查函数function是否为type类型,不一致抛出(warning: initialization from incompatible pointer type)。
__is_constexpor
/*
* This returns a constant expression while determining if an argument is
* a constant expression, most importantly without evaluating the argument.
* Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
*/
#define __is_constexpr(x) \
(sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
判断x是否为整数常量表达式,如果x是常量表达式,
sizeof(int) == sizeof(*((int *) (NULL))) // if `x` was an integer constant expression
sizeof(int) == sizeof(*((void *)(....))) // otherwise
因为sizeof(void)=1,所以如果x是整数常量表达式,则宏的结果为1,否则为0。
int __builtin_types_compatible_p(type_a, type_b);
此函数为GNU扩展,用来判断两个类型是否相同,如果type_a与 type_b相同的话,就会返回1,否则的话,返回0。
roundup宏
#define roundup(x, y) ( \
{ \
const typeof(y) __y = y; \
(((x) + (__y - 1)) / __y) * __y; \
} \
)
返回一个能够除y并且大于x,最接近x的值,向上取整,可用于地址的内存对齐。
clamp宏
/**
* clamp - return a value clamped to a given range with strict typechecking
* @val: current value
* @lo: lowest allowable value
* @hi: highest allowable value
*
* This macro does strict typechecking of @lo/@hi to make sure they are of the
* same type as @val. See the unnecessary pointer comparisons.
*/
#define clamp(val, lo, hi) min((typeof(val))max(val, lo), hi)
判断val是否在lo和hi的范围内,如果小于lo,返回lo,如果大于hi则返回hi,如果在lo和hi之间就返回val。
likely和unlikely宏
把分支预测的信息提供给编译器。
#define likely(x) __builtin_exp ect(!!(x), 1)
#define unlikely(x) __builtin_exp ect(!!(x), 0)
GCC的内建方法会判断 EXP == C 是否成立,成立则将if分支中的执行语句紧跟放在汇编跳转指令之后,否则将else分支中的执行语句紧跟汇编跳转指令之后。
这样cache在预取数据时就可以将分支后的执行语句放在cache中,提高cache的命中率。
ACCESS_ONCE
#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
volatile表示不进行优化,访问目标地址一次,先取得x的地址,然后把这个地址转换成一个指向这个地址的指针,然后再取得这个指针所指向的内容,达到了访问一次的目的。
ACCESS_OK
检查指针是不是属于用户空间。
barrier()
/* Optimization barrier */
/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")
执行该语句后cpu中的寄存器和cache中已缓存的数据将作废,重新读取内存中的数据,这就阻止了cpu将寄存器和cache中的数据用于去优化指令。