Linux内核中断处理程序互斥保护? [英] Linux kernel interrupt handler mutex protection?

查看:251
本文介绍了Linux内核中断处理程序互斥保护?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是否需要保护同一中断多次被调用的中断处理程序?

Do I need to protect my interrupt handler being called many times for the same interrupt?

鉴于以下代码,我不确定我应该进行的系统调用.在当前的实现中,我越来越少了,随机的死锁:-

Given the following code, I am not sure on the system calls I should make. I am getting rare, random dead-locks with this current implementation :-

void interrupt_handler(void)
{
    down_interruptible(&sem);  // or use a lock here ?

    clear_intr(); // clear interrupt source on H/W

    wake_up_interruptible(...);

    up(&sem); // unlock?

    return IRQ_HANDLED;
}

void set/clear_intr()
{
    spin_lock_irq(&lock);
    RMW(x); // set/clear a bit by read/modify/write the H/W interrupt routing register
    spin_unlock_irq(&lock);
}

void read()
{
    set_intr();  // same as clear_intr, but sets a bit
    wait_event_interruptible(...);
}

  1. interrupt_handler:down_interruptible应该是spin_lock_irq/spin_lock_irqsave/local_irq_disable吗?
  2. set/clear_intr:spin_lock_irq应该是spin_lock_irqsave/local_irq_disable吗?
  3. 它(硬件->内核->驱动程序处理程序)能否一直生成/获取中断,直到将其清除? interrupt_handler可以在里面通话时继续打电话吗?
  4. 如果当前执行的中断处理程序是可重入的,那么它将在down_interruptible上阻塞吗?
  1. Should interrupt_handler:down_interruptible be spin_lock_irq / spin_lock_irqsave / local_irq_disable?
  2. Should set/clear_intr:spin_lock_irq be spin_lock_irqsave / local_irq_disable?
  3. Can it (H/W -> kernel -> driver handler) keep generating/getting interrupts until its cleared? Can the interrupt_handler keep getting called while within it?
  4. If as currently implemented the interrupt handler is reentrant then will it block on the down_interruptible?

来自LDD3:-

必须是可重入-它必须能够同时在多个环境中运行.

must be reentrant—it must be capable of running in more than one context at the same time.


编辑1)在获得一些不错的帮助后,建议如下:-


Edit 1) after some nice help, suggestions are :-

  1. interrupt_handler内删除down_interruptible
  2. spin_lock_irq移到设置/清除方法之外(您不需要spin_lock_irqsave吗?)我真的看不到这样做的好处吗?!
  1. remove down_interruptible from within interrupt_handler
  2. Move spin_lock_irq outside set/clear methods (no need for spin_lock_irqsave you say?) I really don't see the benefit to this?!

代码:-

void interrupt_handler(void)
{
    read_reg(y); // eg of other stuff in the handler

    spin_lock_irq(&lock);

    clear_intr(); // clear interrupt source on H/W

    spin_unlock_irq(&lock);

    wake_up_interruptible(...);

    return IRQ_HANDLED;
}

void set/clear_intr()
{
    RMW(x);
}

void read()
{
    error_checks(); // eg of some other stuff in the read method

    spin_lock_irq(&lock);

    set_intr();  // same as clear_intr, but sets a bit

    spin_unlock_irq(&lock);

    wait_event_interruptible(...);

    // more code here...
}


Edit2)阅读更多SO帖子后:阅读为什么在中断上下文中执行的内核代码/线程无法休眠?链接到Robert Loves 文章,我读到了:


Edit2) After reading some more SO posts : reading Why kernel code/thread executing in interrupt context cannot sleep? which links to Robert Loves article, I read this :

一些中断处理程序(在 Linux作为快速中断处理程序)运行 所有本地中断 处理器已禁用.这样做是为了 确保中断处理程序运行 不受干扰,尽快 可能的.更是如此,所有中断 处理程序以当前状态运行 所有中断线均已禁用 处理器.这样可以确保两个 相同的中断处理程序 中断线不运行 同时.它也可以防止设备 司机作家不必处理 递归中断,使情况复杂化 编程.

some interrupt handlers (known in Linux as fast interrupt handlers) run with all interrupts on the local processor disabled. This is done to ensure that the interrupt handler runs without interruption, as quickly as possible. More so, all interrupt handlers run with their current interrupt line disabled on all processors. This ensures that two interrupt handlers for the same interrupt line do not run concurrently. It also prevents device driver writers from having to handle recursive interrupts, which complicate programming.

我启用了快速中断(SA_INTERRUPT)!因此,不需要互斥锁/锁/信号量/旋转/等待/睡眠/etc/etc!

And I have fast interrupts enabled (SA_INTERRUPT)! So no need for mutex/locks/semaphores/spins/waits/sleeps/etc/etc!

推荐答案

不要在中断上下文中使用信号量,而应使用spin_lock_irqsave.引用LDD3:

Don't use semaphores in interrupt context, use spin_lock_irqsave instead. quoting LDD3:

如果您有一个自旋锁,可以 由在其中运行的代码(硬件 或软件)中断上下文,您 必须使用spin_lock的一种形式 禁用中断.正在做 否则会使系统死锁, 迟早.如果您无法访问 您在硬件​​中断中的锁定 处理程序,但是您通过软件来执行 中断(用完了 Tasklet,例如,涵盖的主题 在第7章)中,您可以使用 spin_lock_bh安全地避免死锁 同时仍然允许硬件 要服务的中断.

If you have a spinlock that can be taken by code that runs in (hardware or software) interrupt context, you must use one of the forms of spin_lock that disables interrupts. Doing otherwise can deadlock the system, sooner or later. If you do not access your lock in a hardware interrupt handler, but you do via software interrupts (in code that runs out of a tasklet, for example, a topic covered in Chapter 7), you can use spin_lock_bh to safely avoid deadlocks while still allowing hardware interrupts to be serviced.

对于第2点,使您的set_intrclear_intr要求调用者锁定自旋锁,否则您将发现代码死锁.再次来自LDD3:

As for point 2, make your set_intr and clear_intr require the caller to lock the spinlock, otherwise you'll find your code deadlocking. Again from LDD3:

要使锁定正常工作, 你必须用写一些功能 他们的呼叫者拥有的假设 已经获得了相关的锁. 通常,只有您内部的,静态的 函数可以用这种方式编写; 从外部调用的函数必须 显式处理锁定.当你 编写内部函数 关于锁定的假设,自己动手 (以及与您合作的其他任何人 代码)帮忙并记录下来 明确的假设.可能非常 几个月后很难回来 弄清楚是否需要举行 锁定以调用特定功能或 不是.

To make your locking work properly, you have to write some functions with the assumption that their caller has already acquired the relevant lock(s). Usually, only your internal, static functions can be written in this way; functions called from outside must handle locking explicitly. When you write internal functions that make assumptions about locking, do yourself (and anybody else who works with your code) a favor and document those assumptions explicitly. It can be very hard to come back months later and figure out whether you need to hold a lock to call a particular function or not.

这篇关于Linux内核中断处理程序互斥保护?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆