Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1263148
  • 博文数量: 185
  • 博客积分: 495
  • 博客等级: 下士
  • 技术积分: 1418
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-02 15:12
个人简介

治肾虚不含糖,专注内核性能优化二十年。 https://github.com/KnightKu

文章分类

全部博文(185)

文章存档

2019年(1)

2018年(12)

2017年(5)

2016年(23)

2015年(1)

2014年(22)

2013年(82)

2012年(39)

分类: LINUX

2013-04-02 17:18:10

 实现代码,就两条语句,很简单,依然是经典的do{}while(0)的块式宏封装实现:
#define preempt_disable() /
  do { /
      inc_preempt_count(); /
      barrier(); /
  } while (0)

   第一行把进程描述符中的preempt_count加1,第二行加一个优化屏障。展开inc_preempt_count()后就是:

  current->thread_info->preempt_count++;

  barrier();

  看到这个实现的时候,觉的很奇怪,用个优化屏障就够了吗?似乎应该用内存屏障mb()。优化屏障只能保证编译器不乱排指令,而如果CPU乱序执行,被 preempt_disable保护的临界区中的指令岂不是有可能在preempt_count++之前执行。但可以肯定这不是个BUG,这么重要的地方 不可能出现这么低级的BUG。那么就结合preempt_disable的应用环境分析一下,以下为个人的分析,并未得到权威认证,如有错误还请指正。

  既然没有BUG,那只能有两种可能,第一就是禁用抢占后临界区中的指令,不会先于preempt_count++执行。第二就是在临界区中的指令先执行且 preempt_count++尚未执行的时候,不能发生抢占或者抢占不会有问题。第一种情况由于cpu的乱序执行显然无法保证。那么只能是第二种。为什 么呢?接着分析。

  内核抢占发生在硬件中断唤醒一个高优先级任务的时候,当发现当前任务的优先级低于被唤醒的任务的优先级且当前任务的preempt_count为0,那么 就会抢占当前任务。因此硬件中断是导火索,也就是说只有在临界区中的指令执行后,preempt_count++未执行前发生一个硬件中断,才有可能发生 抢占。但是硬件中断都是precise interrupt,精确中断,即中断发生时的PC指针记录的指令之前的指令都已完成,之后的指令都未执行。这样即使在上述情况发生一个硬件中断,硬件只 能有两种方法来保证中断的精确性:

  1. 丢弃临界区中指令的执行结果,将PC指针指向preempt_disable()。这样即使被抢占,临界区中的指令的执行结果也被丢弃了,所以不会出问题。

  2. 等preempt_disable()指令执行后,将PC指针指向临界区中最后完成的指令的下一条指令。这样由于preempt_count被加1了,该任务就不能被抢占了,所以也不会出问题。

  分析到这里,可以看出此处确实不需要内存屏障了。用barrier()保证编译器不乱排临界区中的指令就可以了。
  再来看看barrier()的实现:
 /* Optimization barrier */
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
更简单,一句空的内联汇编语句,volatile告诉编译器,这段代码不能忽略, "memory" 是编译器的clobber,告诉编译器,
  1. 内存信息已经修改,在这条指令后面的寄存器的值必须从内存中重新获取
  2. 代码的先后顺序必须按照原有的产生汇编代码
  这就告诉其后的指令在执行时都需要从内存中重现取值,而不能使用寄存器中的值。否则编译器可能对preempt_count进行优化, 后续的指令仍然使用寄存器中的值。这样会出问题,比如在临界区中产生一个中断,中断处理程序仍然使用原先寄存器中的preempt_count,它可能无法看到内核抢占已经被禁止,而错误的将不能被抢占的任务抢占。这是中断和进程共享数据时用barrier()来保持同步而不用锁的一个很好的例子。

  终于分析完了,不由的感叹,内核真是太精妙了,简单的两行代码,隐藏着这么深的问题。要想成为linux hacker,要走的路还有很长,努力吧。


阅读(1125) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~