static inline long IS_ERR(const void *ptr)
{
return IS_ERR_VALUE((unsigned long)ptr);
}
内核返回的指针一般是指向页面的边界(4K边界),即
ptr & 0xfff == 0
这样ptr的值不可能落在(0xfffff000,0xffffffff)之间,
而一般内核的出错代码也是一个小负数,在-1000到0之间,转变成unsigned long,
正好在(0xfffff000,0xffffffff)之间。因此可以用
(unsigned long)ptr > (unsigned long)-1000L
来判断内核函数的返回值是一个有效的指针,还是一个出错代码。
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
# ifndef likely
# define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1))
# endif
# ifndef unlikely
# define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))
# endif
这个地方简单说下likely(x)和unlikely(x)
这两个函数其实对应的,而这只是结果不同而已,作用都是提高代码优化度,因为它们能够有效的预测分支。
其中
__builtin_constant_p(x)的功能是判断x是变量还是const
如果是常量的话,则!!(x),这个功能不需要我多说吧。取bool值,如果是变量,则执行__branch_check__
#define __branch_check__(x, expect) ({ \
int ______r; \
static struct ftrace_branch_data \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_annotated_branch"))) \
______f = { \
.func = __func__, \
.file = __FILE__, \
.line = __LINE__, \
}; \
______r = likely_notrace(x); \
ftrace_likely_update(&______f, ______r, expect); \
______r; \
})
别人的分析是:__branch_check__宏,记录当前trace点,并利用ftrace_likely_update记录likely判断的正确性,并将结果保 存在ring buffer中,之后用户可以通过ftrace的debugfs接口读取分支预测的相关信息。从而优调整代码,优化性能。
重定义likely和unlikely宏里面用到了GCC的build-in函数__builtin_constant_p判断一个表达式在编译时是否为 常量。当是常量时,直接返回likely和unlikely表达式的值,没必要做预测的记录。当表达式为非常数时,使用宏 __branch_check__检查分支并记录likely判断的预测信息。
阅读(1603) | 评论(0) | 转发(1) |