edge中斷分析

來源:互聯網
上載者:User

標籤:linux   中斷   

目前正在調試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中斷分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.