← InExtremis

Linux: L'essence des Softirqs

Un article technique, mais quand même compréhensible ; nous allons raconter ici comment les développeurs noyau ont fait pour que la gestion des urgences reste fluide tout au long de la vie du système....

Ça en devient presque une leçon de vie !

Mécanismes, ordonnancement et limites des softirq dans le noyau Linux.

Introduction

Il y a de cela bien longtemps, la gestion des interruptions pouvait se résumer vaguement au fait d'être scindée en deux phases distinctes pour maximiser la réactivité du système. Les softirqs (Software Interrupts) constituent de la "moitié inférieure" (bottom half) de cette gestion tandis que les actions très urgentes de gestion de l'interruption sont gérées dans le top half c'est à dire le handler d'interruption à proprement parler.

Origines et raison d'être

Le concept est né de la nécessité de minimiser le temps passé en contexte d'interruption matérielle (Top Half), où les interruptions doivent être désactivées pour éviter toute réentrance ; il serait dur de garder un système stable avec des interruptions qui surviennent pendant qu'on est encore en train de traiter les précédentes...

Pourquoi scinder en deux la gestion des interruptions en quelques points:

Mécanisme d'exécution

Les softirqs ne s'exécutent pas de manière arbitraire. Elles sont déclenchées (marquée "pending") via la fonction raise_softirq(). Le noyau vérifie leur présence à des points de contrôle précis:

Le Danger: Pourquoi ne pas en ajouter ?

Il est techniquement possible de modifier kernel/softirq.c pour ajouter une entrée à softirq_vec / softirq_to_name, mais c'est une pratique formellement proscrite pour les développeurs de drivers, et ce pour trois raisons majeures que nous allons détailler ici...

Statique et limité

Le nombre de softirqs est fixé à la compilation (Un petit peu plus de 10 actuellement... On y trouve par exemple HI_SOFTIRQ, TIMER_SOFTIRQ, NET_TX_SOFTIRQ, etc.). Ajouter une softirq nécessite une recompilation complète du noyau. Et si pour supporter votre produit le noyau doit être patché en son coeur et recompilé, c'est que vous êtes sur la mauvaise piste... (à moins d'être sur l'ajout d'une fonction révolutionnaire, mais il faut savoir raison garder !)

Complexité de la réentrance

Les softirqs sont statiques et CPU-bound. Une même softirq peut s'exécuter sur deux CPU différents en même temps. Cela impose une rigueur absolue sur le verrouillage des données partagées. Une erreur de conception ici conduit à des deadlocks ou des corruptions de mémoire très durs à débugger.

Affinement des ressources

Le scheduler ne peut pas différencier la priorité entre deux tâches au sein d'une même softirq. Pour 99% des besoins des drivers, les tasklets (qui sont basées sur les softirqs mais simplifiées pour être utilisées par les développeurs dans leurs travaux, mais dépréciée et à proscrire dans tout nouveau développement) ou mieux encore, les workqueues (qui s'exécutent en contexte de thread et peuvent s'endormir) sont les solutions recommandées. Il y a encore d'autre façon de faire, mais nous les détaillerons une autre fois peut-être...

Conclusion

Les softirqs sont un reliquat d'un temps où l'architecture du noyau était bien plus simple ; les développeurs aimeraient les déprécier tout comme les tasklet l'ont été, mais elles sont trop profondément ancrés dans l'architecture logicielle de ce dernier. Elles doivent rester réservées aux sous-systèmes les plus critiques et les plus performants (Réseau, Timers, RCU, etc..). Pour tout développement de driver moderne, privilégiez les threaded IRQs ou les workqueues qui auront le même impact compte tenu des performances actuelle du matériel.

← Retour à l'accueil InExtremis