【轉】中斷處理函數中不用disable_irq而用disable_irq_nosync原因

來源:互聯網
上載者:User

標籤:

原文網址:http://blog.csdn.net/skyflying2012/article/details/8265869

今天在寫觸控螢幕驅動時在中斷處理函數中使用disable_irq關中斷髮現在進入中斷處理後核心就掛掉了,於是研究了一下才發現disable_irq關閉中斷並等待中斷處理完後返回, 而disable_irq_nosync立即返回. 在中斷處理常式中應該使用disable_irq_nosync來關閉中斷 先看一下disable_irq_nosync,核心代碼中是這樣解釋的:

/**
 *    disable_irq_nosync - disable an irq without waiting
 *    @irq: Interrupt to disable
 *
 *    Disable the selected interrupt line. Disablesand Enables are
 *    nested.
 *    Unlike disable_irq(),this function doesnot ensure existing
 *    instances of the IRQ handler have completed before returning.
 *
 *    This function may be called from IRQ context.
 */
void disable_irq_nosync(unsigned int irq)
{
    struct irq_desc *desc = irq_to_desc(irq);
    unsigned long flags;

    if (!desc)
        return;

    chip_bus_lock(irq, desc);
    spin_lock_irqsave(&desc->lock, flags);
    __disable_irq(desc, irq, false);
    spin_unlock_irqrestore(&desc->lock, flags);
    chip_bus_sync_unlock(irq, desc);
}

關閉中斷後程式返回, 如果在中斷處理常式中, 那麼會繼續將中斷處理常式執行完.


/**
 * disable_irq - disable an irq and wait for completion
 * @irq: Interrupt to disable
 *
 * Disable the selected interrupt line. Enables and Disables are
 * nested.
 * This function waits for any pending IRQ handlers for this interrupt
 * to complete before returning. If you use this function while
 * holding a resource the IRQ handler may need you will deadlock.
 *
 * This function may be called - with care - from IRQ context.
 */
void disable_irq(unsignedint irq)
{
        struct irq_desc *desc = irq_desc + irq;
        if (irq>= NR_IRQS)
                return;
        disable_irq_nosync(irq);
        if (desc->action)
                synchronize_irq(irq);
}

關閉中斷並等待中斷處理完後返回.從代碼中可以看到, disable_irq先是調用了disable_irq_nosync, 然後檢測desc->action是否為1. 在中斷處理常式中, action是置1的, 所以進入synchronize_irq函數中.


/**
 * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
 * @irq: interrupt number to wait for
 *
 * This function waits for any pending IRQ handlers for this interrupt
 * to complete before returning. If you use this function while
 * holding a resource the IRQ handler may need you will deadlock.
 *
 * This function may be called - with care - from IRQ context.
 */
void synchronize_irq(unsignedint irq)
{
 struct irq_desc *desc= irq_to_desc(irq);
 unsigned int status;
 if (!desc)
  return;
 do {
  unsigned long flags;
  /*
   * Wait until we‘re out of the critical section. This might
   * give the wrong answer due to the lack of memory barriers.
   */
  while (desc->status& IRQ_INPROGRESS)
   cpu_relax();
  /* Ok, that indicated we‘re done: double-check carefully. */
  spin_lock_irqsave(&desc->lock, flags);
  status = desc->status;
  spin_unlock_irqrestore(&desc->lock, flags);
  /* Oops, that failed? */
 } while (status & IRQ_INPROGRESS);
 /*
  * We made sure that no hardirq handler is running. Now verify
  * that no threaded handlers are active.
  */
 wait_event(desc->wait_for_threads,!atomic_read(&desc->threads_active));
}


注釋中說明該函數是在等待中斷處理常式的結束, 這也是disable_irq與disable_irq_nosync不同的主要所在. 但是在中斷處理函數中調用會發生什麼情況呢? 進入中斷處理函數前IRQ_INPROGRESS會被__setup_irq設定, 所以程式會一直陷在while迴圈中, 而此時核心以經被獨佔, 這就導致系統死掉.  總結:
由於在disable_irq中會調用synchronize_irq函數等待中斷返回, 所以在中斷處理常式中不能使用disable_irq, 否則會導致cpu被synchronize_irq獨佔而發生系統崩潰.

【轉】中斷處理函數中不用disable_irq而用disable_irq_nosync原因

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.