__context__属性

 在分析自旋锁代码时,最终跟踪下来,会在 include/linux/compiler.h 中看到下面的代码:
?
1
2
3
4
5
6
7
8
9
10
11
12
#ifdef __CHECKER__
...
# define __acquire(x)    __context__(x,1)
# define __release(x)    __context__(x,-1)
...
#else
# define __acquire(x) (void)0
# define __release(x) (void)0
  
  
...
#endif

其中含有 __context__ 这种属性。刚开始时认为这也是 gcc 支持的属性一种,其实不然。在应用程序里,模拟上面宏定义并包含 __context__ ,然后用 gcc 编译一下,会有错误提示。


实际上,该属性是提供给一种叫 sparse 的工具进行代码的静态检查的。关于 sparse 的介绍可参考:
引用

在我们编译内核代码时,在 make 时使用 C=1 或者 C=2 选项时都会对 sparse 工具的调用。

sparse 进行代码静态检查并不会对代码进行编译,也不会进行相关宏的处理,它的工作只是检查而已。那么可能会有疑问,检查后,那最终还不是要用 gcc 来编译么?那这样一来不是还不能编译通过?这里需要注意到,像 # define __acquire(x)    __context__(x,1) 这个宏,需要在 __CHECKER__ 这个宏定义下才能使用。那么搜遍整个内核代码,会发现没有 __CHECKER__ 的定义。但是回过头来查看 sparse 相关的源码时,会发现在对 sparse 初始化的函数里有这么一段(位于 lib.c 中):
?
1
2
3
4
5
6
struct symbol_list *sparse_initialize( int argc, char **argv, struct string_list **filelist)
{
      ....
      add_pre_buffer( "#define __CHECKER__ 1\n" );
      ...
}

再看 add_pre_buffer() 函数:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void add_pre_buffer( const char *fmt, ...)
{
         va_list args;
         unsigned int size;
         struct token *begin, *end;
         char buffer[4096];
  
  
         va_start (args, fmt);
         size = vsnprintf(buffer, sizeof (buffer), fmt, args);
         va_end (args);
         begin = tokenize_buffer(buffer, size, &end);
         if (!pre_buffer_begin)
                 pre_buffer_begin = begin;
         if (pre_buffer_end)
                 pre_buffer_end->next = begin;
         pre_buffer_end = end;
}


上面,就是将 "#define __CHECKER__ 1" 这一个字符串通过 vsnprintf(buffer, sizeof(buffer), fmt, args); 拷贝到缓冲区中。


一般的,对代码的静态检查工具,基本工作原理是将要检查的源代码读入缓冲区中在进行比较。所以,__CHECKER__ 这个定义是先在 sparse 的工具的缓冲区中定义好,这样,我们自然就能够使用带有 __context__ 属性的宏了。需要注意一点,带有 __context__ 的宏,只能在缓冲区中比较,在内核中最后仍然是使用没有 __context__ 这种属性的宏的,也就是说最终用到的是:
?
1
2
# define __acquire(x) (void)0
# define __release(x) (void)0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值