Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5534
  • 博文数量: 1
  • 博客积分: 66
  • 博客等级: 民兵
  • 技术积分: 20
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-06 23:13
文章分类
文章存档

2012年(1)

我的朋友

分类: LINUX

2012-10-28 15:19:50

 

Reentrant interrupt definition is “If an interrupt handler re-enables interrupts, then calls a subroutine, and another interrupt occurs ….” from ARM Information Center

 

Interrupt Process on Linux

 

         1.        When ARM entry to IRQ, disable I on CPSR register, which means default ARM disable irq Reentrant Interrupt.

         2.        Kernel received interrupt, when call “handle_level_irq”, it calls i.mx25 bsp to disable the same irq number on i.mx25 interrupt controller as below mark1.

         3.        But when Linux kernel calls “handle_IRQ_event”, kernel checks the flag which we set when call “request_irq” function. Default the flag we don’t set IRQF_DISABLED, Linux kernel enable irq as below market red color mark2 that means at this moment kernel enable Reentrant Interrupt but the same irq number on the interrupt controller can’t trigger interrupt.


点击(此处)折叠或打开

  1. void

  2. handle_level_irq(unsigned int irq, struct irq_desc *desc)

  3. {

  4.                 struct irqaction *action;

  5.                 irqreturn_t action_ret;



  6.                 spin_lock(&desc->lock);

  7.                 mask_ack_irq(desc, irq); // Mark1



  8.                 if (unlikely(desc->status & IRQ_INPROGRESS))

  9.                                 goto out_unlock;

  10.                 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);

  11.                 kstat_incr_irqs_this_cpu(irq, desc);



  12.                 /*

  13.                  * If its disabled or no action available

  14.                  * keep it masked and get out of here

  15.                  */

  16.                 action = desc->action;

  17.                 if (unlikely(!action || (desc->status & IRQ_DISABLED)))

  18.                                 goto out_unlock;



  19.                 desc->status |= IRQ_INPROGRESS;

  20.                 spin_unlock(&desc->lock);



  21.                 action_ret = handle_IRQ_event(irq, action);

  22.                ………………………………………….

  23. }

  24. irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)

  25. {

  26.                 irqreturn_t ret, retval = IRQ_NONE;

  27.                 unsigned int status = 0;



  28.             if (!(action->flags & IRQF_DISABLED)) // Mark2

  29.                         local_irq_enable_in_hardirq();



  30.                 do {

  31.                                 trace_irq_handler_entry(irq, action);

  32.                                 ret = action->handler(irq, action->dev_id); // Mark3

  33.                                 trace_irq_handler_exit(irq, action, ret);



  34.                 ……………………………………

  35. }


 

Summarize

 

         1.        When register irq interrupt by calling “request_irq”, we don’t set flags as “IRQF_DISABLED”, the irq interrupt is Reentrant.

         2.        But there is risk on setting “IRQF_DISABLED”, it means another high priority interrupt can’t interrupt irq handle process from ARM entry to irq mode, finish your irq handle, to kernel back to preview mode.

         3.        In my opinion for the system performance we don’t advice use “IRQF_DISABLED” flag.

For speed up or ensure concurrency safe on your irq handle, please add “spin_lock_irq” or “spin_lock_irqsave” in your register irq handle, “spin_unlock_irq “or “spin_unlock_irqrestore” when exits irqhandle.

It can be disable Reentrant Interrupt just in your register the irq handle. When high irq interrupt can preempt your irq before the kernel jump to your irq handle, so please keep your irq handle (top half) fast and small.

 

阅读(1332) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~