zoukankan      html  css  js  c++  java
  • edge中断分析

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

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

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

    void handle_edge_irq(unsigned int irqstruct 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(irqdesc); /*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。假设满足上面的条件,我们就设置此IRQIRQS_PENDING挂起状态,并屏蔽中断,然后返回。放弃中断的处理过程,留给正在处理此IRQ中断的cpu来处理此次pending的中断。

    irq_ack函数的底层实现是写eoi寄存器。是cpu对此IRQ的回应,表示irq希望清除此IRQpending状态(用于清除APIC IRRpending位),准备接收下一个中断。这样其它的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的中断。

  • 相关阅读:
    chrome中打开 swf下载的问题
    爱对人比爱上人更重要
    ActiveMQ集群
    ActiveMQ相关API
    ActiveMQ持久化
    ActiveMQ处理模式
    ActiveMQ
    JMS与消息队列
    微服务设计、拆分原则
    web常用服务架构
  • 原文地址:https://www.cnblogs.com/yfceshi/p/7298568.html
Copyright © 2011-2022 走看看