edge中断分析
来源:互联网 发布:java覆盖 编辑:程序博客网 时间:2024/06/05 16:56
目前正在调试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触发方式的中断容易丢中断,因此在处理中断时候不能长时间的屏蔽IRQ。在handle_edge_irq函数一上来就判断在irq没用被禁止,没用正在处理的情况下,只是ack回应了硬件,没用屏蔽irq,表示另外的cpu可以接收此IRQ的中断。
- edge中断分析
- 中断分析
- EDGE
- Edge
- EDGE
- Edge
- EDGE
- EDGE
- Edge
- Edge
- Edge
- edge
- Edge
- linux中断--中断原理分析
- linux中断--中断原理分析
- Giraph源码分析(六)——Edge 分析
- 中断分析以及程序设计
- ECOS中断机制分析
- eclipse 单步调试
- 杭电1000,1001
- sql行列互换
- Spark-1.2部署
- iOS实现图片轮播的简易步骤
- edge中断分析
- seajs的使用方法个人总结
- 黑马程序员 第二篇 Java 基础 多线程 (Foundation; completed)
- zepto使用中的一些注意点
- 《JAVA 核心技术 基础知识》第三章 笔记
- MySql优化--系统配置优化和硬件优化
- hasse数列
- busybox的作用和功能
- QT 环境的搭建