Linux内核源码分析(1)——compiler.h分析(2)

1.2 内核模块的宏定义
接下来是宏__KERNEL__的判断,后续部分的内容是内核模块相关的宏定义,不用于用户进程的代码。


#ifdef __GNUC__
#include <linux/compiler-gcc.h>
#endif


    这个部分说明,如果采用的是GNU C的编译器,包含gcc相关的头文件compiler-gcc.h。这个文件的分析在后续的文章中详细描述。


#define notrace __attribute__((no_instrument_function))


    宏notrace的定义,这个宏用于修饰函数,说明该函数不被跟踪。这里所说的跟踪是gcc一个很重要的特性,只要在编译时打开相关的跟踪选择,编译器会加入一些特性,使得程序在执行完后,可以通过工具(如Graphviz)来查看函数的调用过程。而对于内核来说,内部采用了ftrace机制,而不采用trace的特性。


#ifdef __INTEL_COMPILER
# include <linux/compiler-intel.h>
#endif


  __INTEL_COMPILER宏的判断,用于在使用INTEL编译器时,包含intel相关的头文件compiler-intel.h。这个文件不做展开说明。

 上面包含的文件compiler-gcc.h和compiler-intel.h里面定义了编译器相关的内容,下面开始定义通用的一些编译属性。


struct ftrace_branch_data {
 const char *func;
 const char *file;
 unsigned line;
 union {
  struct {
   unsigned long correct;
   unsigned long incorrect;
  };
  struct {
   unsigned long miss;
   unsigned long hit;
  };
  unsigned long miss_hit[2];
 };
};

/*
 * Note: DISABLE_BRANCH_PROFILING can be used by special lowlevel code
 * to disable branch tracing on a per file basis.
 */
#if defined(CONFIG_TRACE_BRANCH_PROFILING) /
    && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)
void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);

#define likely_notrace(x) __builtin_expect(!!(x), 1)
#define unlikely_notrace(x) __builtin_expect(!!(x), 0)

#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;     /
  })

/*
 * Using __builtin_constant_p(x) to ignore cases where the return
 * value is always the same.  This idea is taken from a similar patch
 * written by Daniel Walker.
 */
# 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

#ifdef CONFIG_PROFILE_ALL_BRANCHES
/*
 * "Define 'is'", Bill Clinton
 * "Define 'if'", Steven Rostedt
 */
#define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
#define __trace_if(cond) /
 if (__builtin_constant_p((cond)) ? !!(cond) :   /
 ({        /
  int ______r;      /
  static struct ftrace_branch_data   /
   __attribute__((__aligned__(4)))   /
   __attribute__((section("_ftrace_branch"))) /
   ______f = {     /
    .func = __func__,   /
    .file = __FILE__,   /
    .line = __LINE__,   /
   };      /
  ______r = !!(cond);     /
  ______f.miss_hit[______r]++;     /
  ______r;      /
 }))
#endif /* CONFIG_PROFILE_ALL_BRANCHES */

#else
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif


    对(defined(CONFIG_TRACE_BRANCH_PROFILING) && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)   )这个三个值的检查,确认likely和unlikely是否需要使用branch tracer跟踪。branch tracer是ftrace的一种trace功能。主要用于跟踪likely预测的正确率。为了实现这个功能,branch tracer重新定义了likely和unlikely。

    CONFIG_TRACE_BRANCH_PROFILING宏在配置内核时开启。DISABLE_BRANCH_PROFILING宏只在低级代码关闭基于每个文件的分支跟踪。!defined(__CHECKER__)说明在未使用Sparse工具时有效。

    struct ftrace_branch_data结构体用于记录ftrace branch的trace记录。

    likely_notrace和unlikely_notrace宏使用__builtin_expect函数,__builtin_expect告诉编译器程序设计者期望的比较结果,以便编译器对代码进行优化,改变汇编代码中的判断跳转语句。

    __branch_check__宏,记录当前trace点,并利用ftrace_likely_update记录likely判断的正确性,并将结果保存在ring buffer中,之后用户可以通过ftrace的debugfs接口读取分支预测的相关信息。从而优调整代码,优化性能。

    重定义likely和unlikely宏里面用到了GCC的build-in函数__builtin_constant_p判断一个表达式在编译时是否为常量。当是常量时,直接返回likely和unlikely表达式的值,没必要做预测的记录。当表达式为非常数时,使用宏__branch_check__检查分支并记录likely判断的预测信息。

    如果设置了CONFIG_PROFILE_ALL_BRANCHES宏,将重定义if()为__trace_if。__trace_if检查if的所有分支,并记录分支的跟踪信息。


/* Optimization barrier */
#ifndef barrier
# define barrier() __memory_barrier()
#endif


    这里表示如果没有定义barrier函数,则定义barrier()函数为__memory_barrier()。但在内核代码会包含 compiler-gcc.h,在里面定义了barrier()为__asm__ __volatile__("": : :"memory")。barrier是屏障的意思。因为CPU在执行的过程中,为了优化指令,会对部分指令进行优化执行,执行的顺序并不一定按照程序在源码内写的顺序。编译器也有可能在生成二进制指令的时候,也进行一些优化。有的时候可能在多CPU,多线程或是互斥锁执行中遇到问题。编译器利用内存屏障保证屏障以上的操作,不会影响到屏障以下的操作,避免优化造成的执行顺序不一致。__asm__表示后面的东西都是汇编指令,当然,这是一种在C语言中嵌入汇编的方法,语法有其特殊 性,我在这里只讲跟这条指令有关的。__volatile__表示不对此处的汇编指令做优化。""表示空指令,由于没有输出,两个冒号来代替输出操作数的位置,后面一个冒号分割输入,再加上空的输入,即为"" : : :。memory是gcc中的一个特殊的语法,加上它,gcc编译器则会产生一个动作,使gcc不保留在寄存器内内存的值,并且对相应的内存不会做存储与加载的优化处理。


#ifndef RELOC_HIDE
# define RELOC_HIDE(ptr, off)     /
  ({ unsigned long __ptr;     /
     __ptr = (unsigned long) (ptr);    /
    (typeof(ptr)) (__ptr + (off)); })
#endif



转载时请注明出处和作者联系方式

文章出处:http://www.mythfish.com/

作者联系方式:张天才 mythfish@gmail.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值