眼下正在调试msix中断,在測试过程中发现会概率性的丢失中断。Msix中断默认是edge触发的中断,edge触发的中断是在中断相应pin发生电平信号跳变的时候,会发出一个中断请求。

由于跳变是一瞬间的。不会像level触发中断那样一直保持电平不变,这样就可能会漏掉某一个跳变的瞬间,表现就是丢失了一个中断。

内核中处理edge触发中断的函数为handle_edge_irq,此函数有do_IRQ函数调用而来。

void handle_edge_irq(unsigned int irq, struct irq_desc *desc)

{

raw_spin_lock(&desc->lock);

/*由于接收到中断,所以清除以下两个标志*/

desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);

/*IRQ是否被禁止,或者正在处理中。或者没有挂接中断处理函数*/

if (unlikely(irqd_irq_disabled(&desc->irq_data) ||

irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {

if (!irq_check_poll(desc)) {

desc->istate |= IRQS_PENDING;  /*设置irq处于挂起状态*/

mask_ack_irq(desc);  /*向硬件发ACK,屏蔽中断*/

goto  out_unlock;

}

}

kstat_incr_irqs_this_cpu(irq, desc); /*process/interrupts中相应irq计算加1*/

/*cpu对此IRQ的回应,表示准备接收此IRQ的下一个中断*/

desc->irq_data.chip->irq_ack(&desc->irq_data);

do {

if (unlikely(!desc->action)) { /*没有挂接中断处理函数*/

mask_irq(desc);    /*屏蔽IRQ*/

goto  out_unlock;

}

/*IRQ处于中断挂起状态*/

if (unlikely(desc->istate & IRQS_PENDING)) {

if (!irqd_irq_disabled(&desc->irq_data) &&

irqd_irq_masked(&desc->irq_data))

unmask_irq(desc);

}

/*处理中断*/

handle_irq_event(desc);

}  while ((desc->istate & IRQS_PENDING) &&    /*有挂起的中断须要处理*/

!irqd_irq_disabled(&desc->irq_data));   /*irq没有禁止*/

istate成员刚開始在irq_desc结构体中没找到,事实上它的定义例如以下

#define istate core_internal_state__do_not_mess_with_it

istate相应的是core_internal_state__do_not_mess_with_it成员。

IRQS_REPLAY标志是用来拯救丢失的中断。此标志在check_irq_resend函数中设置,通过中断控制器APIC上的中断信号又一次向cpu发中断。而不是通过外设硬件来重发中断。这里进入到了handle_edge_irq函数表示已经收到了中断。不须要重发,所以清除此标志。

IRQS_WAITING标志表示中断的到来,这里收到了中断,因此也清除此标志。

此标志在handle_xxx_irq函数的開始都会清除掉。

假设<1>当前irq被禁止,<2>当前irq正在处理中,<3>当前irq没有挂接处理函数。则我们不处理接收到的此IRQ。假设满足上面的条件,我们就设置此IRQ为IRQS_PENDING挂起状态,并屏蔽中断,然后返回。放弃中断的处理过程,留给正在处理此IRQ中断的cpu来处理此次pending的中断。

irq_ack函数的底层实现是写eoi寄存器。是cpu对此IRQ的回应,表示irq希望清除此IRQ的pending状态(用于清除APIC IRR的pending位),准备接收下一个中断。这样其它的cpu就能够接收此IRQ进行处理了。

程序接下来是一个while循环,循环的条件是此IRQ没有被禁止而且有pending的待处理的中断。

由于在处理中断的过程中,由于ack了。可能其它的cpu又接收到了此IRQ新的中断。

假设此IRQ没有挂接中断处理函数,就直接屏蔽此IRQ,返回。

假设irq处于IRQS_PENDING状态。中断没有被禁止可是被屏蔽的情况下。调用unmask_irq取消屏蔽。想想为什么会处于IRQS_PENDING状态。并这样处理?前面讲到当此IRQ正在处理中,新接收到的中断,就会设置IRQS_PENDING状态。并屏蔽此IRQ。

Edge触发方式的中断easy丢中断,因此在处理中断时候不能长时间的屏蔽IRQ。

在handle_edge_irq函数一上来就推断在irq没用被禁止,没用正在处理的情况下,仅仅是ack回应了硬件。没用屏蔽irq,表示另外的cpu能够接收此IRQ的中断。

最新文章

  1. python动态创建类的声明
  2. 发布报错:Error ITMS-90635 - Invalid Mach-O in bundle - submitting to App store
  3. 2.Nginx优化
  4. Sphinx 配置文件的说明【备忘】
  5. TextToSpeech之阅读文字
  6. ubuntu14.04美化
  7. XML 解析器
  8. C#中IP地址转换为数值的方法
  9. 语音识别之梅尔频谱倒数MFCC(Mel Frequency Cepstrum Coefficient)
  10. (十)Hibernate 查询方式
  11. 小笔记(一):ajax传递数组及将ajax返回数据赋值
  12. leetcode第八题 String to Integer (atoi) (java)
  13. google 推荐 android 像素统一使用dip,字体统一使用sp
  14. 五,ESP8266 TCP服务器多连接
  15. 什么是面向切面编程AOP
  16. vue的一些随记
  17. Bridge (br0) Network on Linux
  18. Hdoj 1789 Doing Homework again 题解
  19. M600 Pro 安装问题解决
  20. Intellij IDEA神器值得收藏的小技巧

热门文章

  1. 【HDU 6021】 MG loves string (枚举+容斥原理)
  2. 【静态主席树】POJ2104-K-th Number
  3. [CodeForces-375E]Red and Black Tree
  4. 修改选择排序 Exercise07_20
  5. bzoj 1004 Cards 组合计数
  6. bzoj 3585: mex &amp;&amp; 3339: Rmq Problem -- 主席树
  7. python开发_常用的python模块及安装方法
  8. (转)资源监控工具Spotlight监测LINUX
  9. 【ASP】Window2008站点安全设置,IIS7/IIS7.5中目录执行权限的设置方法
  10. windows端口