servizio in differita delle ISR
L'unica forma di servizio in differita sostenibile, anzi, direi pure "richiesta/fondamentale", nel mondo da cui provengo io, è la seguente (mi scuso per l'OTP parziale nel quale sto incorrendo):
servizio in differita dell'interrupt "PendSV" (Pending Super-Visor Call): se hai un RTOS, tipo FreeRTOS, che gira su un microcontrollore mono-core per applicazioni embedded, è importante accertarsi che lo scheduler dei processi possa effettuare il cambio di contesto, fra il task attuale da sottoporre a preemption, e quello successivo al quale dobbiamo consegnare la CPU, in modo che il contesto del processo da abbandonare/freezare sia FUORI da ogni interrupt.
Se lo scheduler facesse le push nello stack del task da abbandonare/freezare, mentre questo task è ancora interrotto da un IRQ oppure peggio ancora da più IRQs nested, incorreremmo in problemi, probabilmente in crash, ad ogni modo situazioni non prevedibili, perchè quando poi lo scheduler riassegnerà la CPU a questo task, quindi quando riavremo le pop dallo stack di questo task (ripristino di quel contesto), avremmo il ripristino di un contesto di task interrotto da IRQs, quindi con una situazione di registri R0, R1, ... R15 particolare/sbagliata, flags particolari (modalità Handler, non Thread), insomma un ripristino di contesto "strano".
Quindi è importante servire in differita l'IRQ "PendSV" che si occupa della chiamata di sistema che determina il cambio di contesto.
Mi spiego meglio:
ad ogni tick di sistema, diciamo ogni 100us, l'IRQ scatenato dal tick di sistema setta il flag di avvenuto interrupt del PendSV, ma l'IRQ del PendSV non viene effettivamente servita fino a quando il program-counter PC della CPU non ritorna al task interrotto dai vari interrupts annidati: facciamo conto che il PC prima esca dall'IRQ ad altissima priorità, tornando ad un IRQ a media priorità, adesso finisce di eseguire questo IRQ, poi esce da questo IRQ ed il PC entra in un IRQ a bassa priorità, poi eseguiamo quest'ultimo IRQ, poi una volta terminato il PC ne esce e torna nel loop "while(1) { ... } " del task interrotto da questi IRQs nested.
Solo adesso l'OS serve l'IRQ "PendSV", per effettuare lo switch-context, poichè adesso l'immagine di CPU da salvare nello stack del task che stiamo per lasciare è un'immagine di CPU di task in condizioni normali, di running, non più di task interrotto.