preempt_disable

#define preempt_disable() /
  do { /
      inc_preempt_count(); /
      barrier(); /
  } while (0)

  实现很简单,就两行代码,第一行把进程描述符中的preempt_count加1,第二行加一个优化屏障。展开inc_preempt_count()后就是:

  current->thread_info->preempt_count++;

  barrier();//有些CPU为了优化并行度, 会调整指令执行的顺序。barrier就是迫使cpu严格按照指令序执行的

内核抢占发生在硬件中断唤醒一个高优先级任务的时候,当发现当前任务的优先级低于被唤醒的任务的优先级且当前任务的preempt_count为0,那么就会抢占当前任务。因此硬件中断是导火索,也就是说只有在临界区中的指令执行后,preempt_count++未执行前发生一个硬件中断,才有可能发生抢占。但是硬件中断都是precise interrupt,精确中断,即中断发生时的PC指针记录的指令之前的指令都已完成,之后的指令都未执行。这样即使在上述情况发生一个硬件中断,硬件只能有两种方法来保证中断的精确性: 1. 丢弃临界区中指令的执行结果,将PC指针指向preempt_disable()。这样即使被抢占,临界区中的指令的执行结果也被丢弃了,所以不会出问题。 2. 等preempt_disable()指令执行后,将PC指针指向临界区中最后完成的指令的下一条指令。这样由于preempt_count被加1了,该任务就不能被抢占了,所以也不会出问题。 分析到这里,可以看出此处确实不需要内存屏障了,用barrier()保证编译器不乱排临界区中的指令就可以了。但是实际上这里这个barrier()还有另外一个作用,就是保证编译器会产生写内存的指令,把preempt_count的值写到内存。否则编译器可能对preempt_count进行优化,仅仅把更新后的值放到寄存器中。这样会出问题,比如在临界区中产生一个中断,中断处理程序只能从内存中去读preempt_count的值,它可能无法看到内核抢占已经被禁止,而错误的将不能被抢占的任务抢占。这是中断和进程共享数据时用barrier()来保持同步而不用锁的一个很好的例子。

/* Optimization barrier *//* The "volatile" is due to gcc bugs */#define barrier() __asm__ __volatile__("": : :"memory")



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值