Защита мьютекса обработчика прерываний ядра Linux?

Нужно ли мне защищать мой обработчик прерываний, вызываемый много раз для одного и того же прерывания?

Учитывая следующий код, я не уверен, какие системные вызовы мне следует делать . Я получаю редкие случайные блокировки с этой текущей реализацией: -

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_irq67save / local_irq_disable ?
  2. Должен ли установить / clear_intr : spin_lock_irq быть spin_lock_irqsave / local_irq77] ? Может ли он (H / W -> ядро ​​-> обработчик драйвера) продолжать генерировать / получать прерывания, пока он не будет очищен? Может ли interrupt_handler продолжать вызываться, пока он находится внутри него?
  3. Если в настоящее время обработчик прерываний является реентерабельным, то будет ли он блокировать down_interruptible ?

Из LDD3: -

должен быть реентерабельным - он должен быть способен работать в более чем одном контексте одновременно.


Изменить 1) после некоторой хорошей помощи предлагаются следующие варианты: -

  1. удалить down_interruptible изнутри interrupt_handler
  2. Переместите spin_lock_irq вне методов set / clear (не нужны spin_lock_irqsave вы говорите?) Я правда не вижу выгода от этого?!

Код: -

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: чтение Почему код ядра / поток, выполняющийся в контексте прерывания, не может спать? , который ссылается на Роберт Лавс ] статью , я прочитал это:

некоторые обработчики прерываний (известные в Linux как обработчики быстрых прерываний) со всеми прерываниями на локальном процессор отключен. Это сделано для убедитесь, что обработчик прерывания работает без перерыва, так быстро, как возможное. Более того, все перебивают обработчики работают со своими текущими линия прерывания отключена на всех процессоры. Это гарантирует, что два обработчики прерываний для того же линия прерывания не работает одновременно. Это также предотвращает устройство писатели драйверов от необходимости обрабатывать рекурсивные прерывания, которые усложняют программирование.

И у меня включены быстрые прерывания (SA_INTERRUPT)! Так что нет необходимости в мьютексах / блокировках / семафорах / вращениях / ожиданиях / засыпании / и т.д. / и т.д.!

13
задан Community 23 May 2017 в 11:59
поделиться