中断处理程序中的关中断函数disable_irq和disable_irq_nosync

可能会有多个同一中断线的中断等待处理,使用 disable_irq在此中断线的中断处理例程中关闭此中断线, disable_irq会等待尚未处理完的中断申请处理完,
如果中断例程中占用了资源,则会死锁。
disable_irq关闭中断并等待中断处理完后返回, 而disable_irq_nosync立即返回. 那么在中断处理程序中应该使用哪一个函数来关闭中断呢?
在<linux设备驱动开发详解>中的按键驱动中, 使用disable_irq来关闭中断, 但是我在测试时进入中断后系统会死在中断处理程序, 而改为disable_irq_nosync则能正常退出中断处理程序.下面从内核代码来找一下原因:
先看一下disable_irq_nosync,内核代码中是这样解释的:
[cpp]  view plain copy
  1. /** 
  2.  *    disable_irq_nosync - disable an irq without waiting 
  3.  *    @irq: Interrupt to disable 
  4.  * 
  5.  *    Disable the selected interrupt line. Disables and Enables are 
  6.  *    nested. 
  7.  *    Unlike disable_irq(), this function does not ensure existing 
  8.  *    instances of the IRQ handler have completed before returning. 
  9.  * 
  10.  *    This function may be called from IRQ context. 
  11.  */  
  12. void disable_irq_nosync(unsigned int irq)  
  13. {  
  14.     struct irq_desc *desc = irq_to_desc(irq);  
  15.     unsigned long flags;  
  16.   
  17.     if (!desc)  
  18.         return;  
  19.   
  20.     chip_bus_lock(irq, desc);  
  21.     spin_lock_irqsave(&desc->lock, flags);  
  22.     __disable_irq(desc, irq, false);  
  23.     spin_unlock_irqrestore(&desc->lock, flags);  
  24.     chip_bus_sync_unlock(irq, desc);  
  25. }  

关闭中断后程序返回, 如果在中断处理程序中, 那么会继续将中断处理程序执行完.
[cpp]  view plain copy
  1. /** 
  2.  * disable_irq - disable an irq and wait for completion 
  3.  * @irq: Interrupt to disable 
  4.  * 
  5.  * Disable the selected interrupt line. Enables and Disables are 
  6.  * nested. 
  7.  * This function waits for any pending IRQ handlers for this interrupt 
  8.  * to complete before returning. If you use this function while 
  9.  * holding a resource the IRQ handler may need you will deadlock. 
  10.  * 
  11.  * This function may be called - with care - from IRQ context. 
  12.  */  
  13. void disable_irq(unsigned int irq)  
  14. {  
  15.         struct irq_desc *desc = irq_desc + irq;  
  16.         if (irq >= NR_IRQS)  
  17.                 return;  
  18.         disable_irq_nosync(irq);  
  19.         if (desc->action)  
  20.                 synchronize_irq(irq);  
  21. }  

关闭中断并等待中断处理完后返回.从代码中可以看到, disable_irq先是调用了disable_irq_nosync, 然后检测desc->action是否为1. 在中断处理程序中, action是置1的, 所以进入synchronize_irq函数中.
[cpp]  view plain copy
  1. /** 
  2.  * synchronize_irq - wait for pending IRQ handlers (on other CPUs) 
  3.  * @irq: interrupt number to wait for 
  4.  * 
  5.  * This function waits for any pending IRQ handlers for this interrupt 
  6.  * to complete before returning. If you use this function while 
  7.  * holding a resource the IRQ handler may need you will deadlock. 
  8.  * 
  9.  * This function may be called - with care - from IRQ context. 
  10.  */  
  11. void synchronize_irq(unsigned int irq)  
  12. {  
  13.  struct irq_desc *desc = irq_to_desc(irq);  
  14.  unsigned int status;  
  15.  if (!desc)  
  16.   return;  
  17.  do {  
  18.   unsigned long flags;  
  19.   /* 
  20.    * Wait until we're out of the critical section. This might 
  21.    * give the wrong answer due to the lack of memory barriers. 
  22.    */  
  23.   while (desc->status & IRQ_INPROGRESS)  
  24.    cpu_relax();  
  25.   /* Ok, that indicated we're done: double-check carefully. */  
  26.   spin_lock_irqsave(&desc->lock, flags);  
  27.   status = desc->status;  
  28.   spin_unlock_irqrestore(&desc->lock, flags);  
  29.   /* Oops, that failed? */  
  30.  } while (status & IRQ_INPROGRESS);  
  31.  /* 
  32.   * We made sure that no hardirq handler is running. Now verify 
  33.   * that no threaded handlers are active. 
  34.   */  
  35.  wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active));  
  36. }  

注释中说明该函数是在等待中断处理程序的结束, 这也是disable_irq与disable_irq_nosync不同的主要所在. 但是在中断处理函数中调用会发生什么情况呢? 进入中断处理函数前IRQ_INPROGRESS会被__setup_irq设置, 所以程序会一直陷在while循环中, 而此时内核以经被独占, 这就导致系统死掉.
 
总结:
由于在disable_irq中会调用synchronize_irq函数等待中断返回, 所以在中断处理程序中不能使用disable_irq, 否则会导致cpu被synchronize_irq独占而发生系统崩溃.
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值