Linux |
CentOS 4.8 |
|
disable_bh(9) |
init_bh, remove_bh, mark_bh, disable_bh, enable_bh − gestionnaire d’interruption découplé |
#include <linux/interrupt.h> |
void init_bh(int nr, void (*routine)(void)); |
void remove_bh(int nr); |
void mark_bh(int nr); |
void disable_bh(int nr); |
void enable_bh(int nr); |
Théorie |
Le découpage d’un gestionnaire d’interruptions en deux permet d’assurer un traitement des interruptions entrantes en temps réél critique par le gestionnaire haut tandis que le gestionnaire bas les traitera réellement dès que possible. Le gestionnaire haut (enregistré par request_irq(9)) se contente généralement de déplacer des données entre un périphérique et un tampon en mémoire, et de s’assurer que le périphérique est dans un état normal. Tant que ce gestionnaire est en cours d’éxécution, l’interruption correspondante est désactivée. S’il s’agit d’un gestionnaire d’interruption rapide (i.e., si SA_INTERRUPT est positionné), toutes les interruptions sont désactivées. Le gestionnaire bas fait ce qu’il reste à traiter pour l’interruption correspondante. Un gestionnaire bas est éxécuté alors que les interruptions sont autorisées. Cependant, un mécanisme de blocage assure qu’une seule instance d’un gestionnaire bas donné est exécutée à un instant donné. Les gestionnaires bas sont lancés par do_bottom_half(), qui est appelé par schedule() et ret_from_sys_call(). |
Usage |
init_bh() installe routine() en tant que gestionnaire bas numéro nr. Cela est réalisé par l’ajout d’une entrée au tableau bh_base[] , et le positionnement du bit approprié du vecteur bh_mask . Plutôt que forcer un numéro explicite, il est recommandé d’ajouter une entrée à l’énumération anonyme dans include/linux/interrupt.h. remove_bh() enlève le gestionnaire bas numéro nr de la liste des gestionnaires bas. L’entrée correspondante est enlevée de bh_base[] le bit approprié de bh_mask est réinitialisé. mark_bh() demande au noyau d’éxécuter le gestionnaire bas correspondant dès que possible. Cette fonction n’est normalement appelée que par le gestionnaire haut d’un gestionnaire d’interruptions. Il fonctionne en positionnant le bit correspondant du vecteur bh_active . disable_bh() désactive le gestionnaire bas numéro nr en réinitialisant le bit approprié de bh_mask. Cette fonction incrémente également bh_mask_count[nr], qui est utilisé pour assurer que des appels imbriqués à disable_bh() doivent correspondre à un nombre égal d’appels à enable_bh(). enable_bh() active un gestionnaire bas précédemment désactivé par disable_bh(). Cette fonction décrémente bh_mask_count[nr]. Ensuite, si cette valeur est zéro, le gestionnaire bas correspondant est activé en positionnant le bit approprié de bh_mask. |
Aucune valeur n’est renvoyée. |
Linux 2.0+. init_bh() et remove_bh() n’étaient pas présentes dans les anciennes versions de Linux. Dans ces versions, bh_base[] et bh_mask doivent être modifiés à la main. |
request_irq(9), queue_task(9) include/asm*/softirq.h, include/linux/interrupt.h, kernel/softirq.c “Kernel Korner” dans l’article 26 du magazine The Linux Journal comprend un article sur les gestionnaires bas d’interruptions sous Linux. Une copie en est disponible sur le web à http://www.ssc.com/lj/issue26/interrupt.html. |
Neil Moore <amethyst@maxwell.ml.org> |
Thierry Vignaud <tvignaud@mandrakesoft.com>, 2000 |
Seuls 32 gestionnaires bas peuvent exister. Augmenter ce nombre impose de modifier la taille de bh_base[] et bh_mask_count[] dans kernel/softirq.c, ainsi que de changer bh_active et bh_mask (dans le même fichier) pour un type plus large. Une meilleure solution, cependant, serait de rassembler les multiples gestionnaires bas en un seul en utilisant une liste chaînée de tâches. Voir queue_task(9) pour les détails. |
disable_bh(9) |