La réintégration est / devient un casse-tête majeur plus vos ISR sont complexes. L ' entrée wikipedia a une description assez succincte d'un ISR rentrant:
Un gestionnaire d'interruption réentrante est un gestionnaire d'interruption qui réactive les interruptions au début du gestionnaire d'interruption. Cela peut réduire la latence d'interruption. [6] En général, lors de la programmation des routines de service d'interruption, il est recommandé de réactiver les interruptions dès que possible dans le gestionnaire d'interruption. Cette pratique permet d'éviter de perdre des interruptions. [7]
En supposant que vous n'écrivez pas un système d'exploitation à usage général où la ré-entrée pourrait très bien être inévitable, vous devez garder à l'esprit la complexité supplémentaire d'avoir une ré-entrée dans votre code de contrôleur personnalisé personnalisé pourrait ne pas valoir la peine facilité d'écriture des ISR de longue durée paresseux.
Voici un exemple:
- ISR de longue durée et de faible priorité commence à faire quelque chose, appelle une version de
malloc
que vous avez implémentée.
- Au cours d'un appel
malloc
, vous êtes interrompu par un thread de priorité plus élevée: il appelle également malloc
- Scénario A: ISR haute priorité quitte malloc avant la basse priorité
- scénario b: ISR haute priorité sort de malloc après une priorité basse *
Ok, direz-vous, je vais mettre un verrou tournant sur malloc, alors tout ce que vous avez à faire est de répéter la condition ci-dessus à la primitive spinlock_aquire
que vous avez créée: is il rentrant?
Je dois souligner ici que le simple fait de gifler des choses et de l'appeler un jour est une recette pour les blocages basés sur l'inversion de priorité. Ce n’est pas si simple.
La solution du pauvre homme à tous ces problèmes est de garder vos ISR courts. Par exemple, dans le noyau NT, il y a longtemps (pas tenu à jour), tout IRQL au-dessus des deux derniers n'était pas autorisé à même regarder la mémoire paginée. En effet, la pagination était gérée par une interruption ...
Le choix devient donc: implémenter un mécanisme de mise en file d'attente de base et faire répartir vos unités de travail ISR, ou faire en sorte que vos ISR se comportent librement, mais assurez-vous d'avoir un environnement extrêmement robuste qui ne s'étouffera pas sur des problèmes étranges (par exemple inversion de priorité).
Si votre tâche est super simple, comme allumer une lumière dans votre drone contrôlé par arduino, alors allez-y. Mais si vous voulez éviter les maux de tête d'ingénierie plus tard à mesure que votre code devient plus complexe, vous devriez vraiment éviter l'avantage perçu de ne vous donner aucune contrainte avec un ISR.
* clarification: le scénario b ne peut pas se produire à sa valeur nominale puisque l'ISR de priorité supérieure s'exécutera et se terminera toujours avant celui de priorité inférieure. Cependant, le chemin-code emprunté par l'un ou l'autre peut être échangé. Ainsi, dans la routine malloc
elle-même, s'il y a un accès à une structure de données globale, ce code peut être interrompu de toutes les combinaisons possibles.
En plus de ce point, il convient de préciser que l'exigence de ré-entrée pour toute fonction concerne l'intégralité de son arbre d'appels. Cela devient très difficile à garantir si vous utilisez des bibliothèques tierces.
A noter également: pour répondre à un commentaire de @ user253751, la rentrée n'est pas résolue en enveloppant simplement les choses dans un verrou. Au contraire, la réintégration a un ensemble d ' exigences qui sont bien comprises. Voici quelques exemples de code triviaux qui illustrent le problème.
On peut voir, en regardant cela, que l'écriture d'une fonction réentante de malloc ou d'acquisition de ressources devient très difficile.