linux kernel threaded irq

来源:互联网 发布:中国加工贸易数据 编辑:程序博客网 时间:2024/05/22 03:44

1.How-to


request_threaded_irq()
{
action->handler = handler;
action->thread_fn = thread_fn;
->__setup_irq()
{
/*
* Create a handler thread when a thread function is supplied
* and the interrupt does not nest into another interrupt
* thread.
*/
if (new->thread_fn && !nested) {
struct task_struct *t;


t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
  new->name);
adb shell ps -P -p
可以看到创建的irq thread:
USER     PID   PPID  VSIZE  RSS   PRIO  NICE  RTPRI SCHED  PCY  WCHAN    PC        NAME
root      57    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/102-msm_iom
root      58    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/102-msm_iom
root      59    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/102-msm_iom
root      60    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/79-msm_iomm
root      61    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/78-msm_iomm
root      62    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/78-msm_iomm
root      63    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/74-msm_iomm
root      64    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/75-msm_iomm
root      65    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/75-msm_iomm
root      66    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/273-msm_iom
root      67    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/273-msm_iom
root      68    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/273-msm_iom
root      69    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/97-msm_iomm
root      70    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/97-msm_iomm
root      71    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/97-msm_iomm
root      77    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/402-mba
root      78    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/530-wcnss
root      134   2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/335-main_tt


2.什么时候执行

产生中断之后先执行中断对应的hard handler,之后根据hard handler中断服务程序是否返回IRQ_WAKE_THREAD flag决定是否执行中断对应的thread_fn。
(下半部tasklet 也是在hard handler 中断服务程序中执行tasklet_schedule()触发的)
执行流程是下面这个样子的:
handle_irq_event_percpu()
->
trace_irq_handler_entry(irq, action);
res = action->handler(irq, action->dev_id);
trace_irq_handler_exit(irq, action, res);
->
switch (res) {
case IRQ_WAKE_THREAD:
/*
* Catch drivers which return WAKE_THREAD but
* did not set up a thread function
*/
if (unlikely(!action->thread_fn)) {
warn_no_thread(irq, action);
break;
}


irq_wake_thread(desc, action);


->static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
{
wake_up_process(action->thread);




->
/*
 * Interrupt handler thread
 */
static int irq_thread(void *data)
{
static const struct sched_param param = {
.sched_priority = MAX_USER_RT_PRIO/2,
};
sched_setscheduler(current, SCHED_FIFO, &param);//irq thread 优先级比ksoftirqd/N 高很多
->
ret = action->thread_fn(action->irq, action->dev_id);

3. 一个threaded irq 典型的例子

static int __devinit ads7846_probe(struct spi_device *spi)
{
err = request_threaded_irq(spi->irq, ads7846_hard_irq, ads7846_irq,
  irq_flags, spi->dev.driver->name, ts);
这个驱动既申请了hard handler(ads7846_hard_irq) 也申请了thread_fn(ads7846_irq)。
0 0
原创粉丝点击