Protection du mutex du gestionnaire d'interruption du noyau Linux?

Dois-je protéger mon gestionnaire d'interruption d'être appelé plusieurs fois pour la même interruption?

Donné le code suivant, je ne suis pas sûr sur le système d'appels que je doit faire. Je suis rare, au hasard des morts-serrures avec ce courant de la mise en œuvre :-

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. Devrait interrupt_handler:down_interruptible être spin_lock_irq /spin_lock_irqsave /local_irq_disable?
  2. Devrait set/clear_intr:spin_lock_irq être spin_lock_irqsave /local_irq_disable?
  3. Peut-il (H/W -> noyau> gestionnaire de pilote) générer/obtenir de l'interrompt jusqu'à ce que ses effacé? Peut le interrupt_handler reçois appelé tout à l'intérieur?
  4. Si tel qu'il est actuellement mis en oeuvre le gestionnaire d'interruption est réentrant alors qu'il bloc sur le down_interruptible?

De LDD3 :-

doit être réentrant—il doit être capable de fonctionner dans plus d'un contexte à la fois.


Edit 1) après quelques belles de l'aide, des suggestions sont :-

  1. supprimer down_interruptible de l'intérieur interrupt_handler
  2. Déplacer spin_lock_irq à l'extérieur de définir/effacer les méthodes (pas besoin de spin_lock_irqsave vous dire?) Je ne vois vraiment pas l'avantage à cela?!

Code :-

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) Après la lecture de certains plus messages : lecture Pourquoi le code du noyau/thread en cours d'exécution dans l'interrompre contexte ne peut pas dormir? qui liens de Robert Aime l'articlej'ai lu ceci :

certains gestionnaires d'interruption (connu dans
Linux aussi vite gestionnaires d'interruption) exécuter
avec toutes les interruptions sur le local
processeur désactivé. C'est fait pour
s'assurer que le gestionnaire d'interruption s'exécute
sans interruption, aussi rapidement que
possible. Plus, tous les interrompre
les gestionnaires de courir avec leur actuel
ligne d'interruption désactivé sur tous les
les processeurs. Cela garantit que les deux
gestionnaires d'interruption pour le même
ligne d'interruption de ne pas exécuter
en même temps. Il empêche aussi l'appareil
pilote d'écrivains d'avoir à gérer de
récursive interruptions, ce qui complique
de la programmation.

Et j'ai vite interruptions activées (SA_INTERRUPT)! Donc, pas besoin de mutex/serrures/sémaphores/spins/attend/dort/, etc/, etc!

source d'informationauteur Ian Vaughan