Inhalt
Grundsätzliches
Dispatcher-Ring
Interrupt-Service-Routinen
Traps
Input / Output
Dispatcher
Scheduler
|
Die innere Struktur von RTOS-UH
Wenn in diesem Text von Input/Output (I/O) und von Schnittstellen die
Rede ist, ist damit das I/O gemeint, was wesentlich länger als ein
Prozessorbefehl dauert (Festplatten / Netzwerk /Serielle- und
parallele Schnittstellen...), nicht jedoch digitales oder analoges I/O.
Hinweis: Der Event-Scheduler betreut die auf Hochsprachebene (vor allem
PEARL und PEARL90, aber auch C) auf Interrupts eingeplanten Tasks,
nicht jedoch Interrupts für I/O-Dämonen. Der Clock-Scheduler
betreut die für Zeitpunkte eingeplanten Tasks.
/\ Grundsätzliches
- Prozesse zweiter Art (Nutzerprogramme und [I/O-]Dämonen) laufen
im User-Mode des Prozessors, Prozesse erster Art (Traps,
Interrupt-Service-Routinen (IRSR), Dispatcher und Scheduler) im
Supervisor-Mode.
- Ruft ein Prozeß zweiter Art einen Trap auf, läuft dieser im
Supervisor-Mode, aber das auf den Systemstack gerettete
Statusregister hat das Supervisor Bit gelöscht. Der sogenannte
"Outer-State" ist in diesem Fall der User-Mode. Die
Unterscheidung, welchen Zustand der unterbrochene Prozeß hat, ist
für das Anlaufen der beiden Scheduler und des Dispatchers
von großer Bedeutung.
- Die systemeigenen Datenstrukturen, die als Ketten oder Ringe
verwaltet werden, dürfen nur von Traps manipuliert werden. Denn
dann ist der Trap selbst im Supervisor-Mode, der
"Outer-State" ist der User-Mode. Dadurch ist garantiert, daß
sowohl vor Aufruf des Traps als auch nach Beendigung des Traps die
Strukturen konsistent sind.
- Es gibt globale Zellen, in denen abgelegt ist, ob einer der
beiden Scheduler oder der Dispatcher laufen muß. Wünscht eine
IRSR einen Dispatcherstart, muß sie das "Dispatcher-Call-Flag
(DPC-Flag)" setzen. Für die Scheduler gibt es je nach
Prozessorfamilie ein leicht unterschied-liches Verhalten:
Ist eine zeitliche Einplanung fällig (wird von der
Timer-IRSR festgestellt), wird in der 68xxx-Familie das DPC-Flag
von der Timer-IRSR gesetzt und der Clock-Scheduler
angesprungen. Entsprechendes gilt für den Event-Scheduler.
Da beim PowerPC der Interruptausstieg hardwareabhängig ist, setzt
eine-IRSR lediglich das DPC-Flag und das Flag für den gewünschten
Scheduler und verzweigt am Ende in den Dispatcher (siehe auch (<)
und (<)).
-
RTOS-UH ist frei von Polling-Schleifen, da es komplett
interruptgetrieben arbeitet.
-
Der wichtigste Dämon in RTOS-UH ist der Error-Dämon. Er ist
immer im Dispatcher-Ring, seine Adresse ist allen Traps und IRSRs
bekannt. Der Error-Dämon verfügt über einen Ringpuffer, in den
Traps und IRSRs Aufträge ablegen können, die sie nicht selbst
erledigen dürfen. Typisch sind z.B. Fehlermeldungen von Traps und
Aktivierung von Tasks durch IRSRs.
Nach Abarbeitung eines Auftrags prüft der Error-Dämon bei
gesetzter Interruptsperre des Prozessors, ob weitere Aufträge
anliegen. Bei gefülltem Ringpuffer arbeitet er im User-Mode
weiter, anderenfalls begibt er sich in den Zustand "zur
Fortsetzung eingeplant".
/\ Dispatcher-Ring
- Im Dispatcher-Ring sind alle Tasks prioritätssortiert
aufgenommen, die nicht den Taskzustand "schlafend" haben.
- Der Dispatcher teilt der höchstpriorisierten lauffähigen
Task den Prozessor zu.
- Im Dispatcher-Ring wird nicht zwischen "lauffähig" und
"laufend" unterschieden, da einfach die höchstpriorisierte
lauffähige Task den Prozessor zugeteilt bekommt.
-
Es gibt eine systemweite Zelle, in der die Taskadresse der Task
steht, die gerade den Prozessor hat. Diese Zelle kann den Wert 0
haben, (Inter-Task-State, siehe (<) und (<)).
-
Die einzigen Traps, die Tasks in den Ring einketten dürfen,
sind die für sofortige oder verzögerte Aktivierungen.
Die einzigen Traps zum Ausklinken aus dem Ring sind die für
Terminierungen.
-
Das Ändern der Priorität einer Task erfordert ein Umketten.
(Nur für bestimmte Traps erlaubt.)
- Hat bei einer Einkettung in den Dispatcher-Ring die
einzufügende Task die gleiche Priorität wie eine bereits
vorhandene, wird sie hinter der vorhandenen eingekettet.
/\ Interrupt-Service-Routinen
-
Die IRSR haben von allen Prozessen die höchste Priorität. Jede
IRSR beendet sich mit einem Aussprung in den Dispatcher (der aber
nicht jedesmal deshalb anläuft, siehe (<)).
- Für IRSR ist es verboten, Traps aufzurufen.
- IRSR dürfen den Taskzustand aller Tasks ändern, die sich im
Dispatcher-Ring befinden, solange die Tasks an der gleichen Stelle
im Ring bleiben.
- IRSR dürfen kein I/O machen (Siehe (<)).
- Will eine IRSR eine Task aktivieren, kann sie das indirekt über
den Error-Dämon machen (Siehe (<)). Arbeitet der Error-Dämon
z.Zt. keinen Auftrag ab, kann die IRSR den Dämon fortsetzen.
- PEARL-Tasks können auf Interrupts eingeplant werden. Soll eine
IRSR eine PEARL-Task fortsetzen oder aktivieren, muß sie anstelle
des Dispatchers den Event-Scheduler anspringen.
/\ Traps
- Jeder Trapaufruf endet mit einem Sprung in den Dispatcher
(der aber nicht jedesmal deshalb anläuft, siehe (<)).
-
Traps dürfen den Taskzustand aller Tasks ändern, die sich im
Dispatcher-Ring befinden, solange die Tasks an der gleichen Stelle
im Ring bleiben (Ausnahme: siehe (<) und (<)).
- Traps dürfen kein I/O machen. Wollen sie eine Fehlermeldung
ausgeben, können sie das indirekt über den Error-Dämon
ausführen (siehe (<)). Arbeitet der Error-Dämon z.Zt. keinen
Auftrag ab, kann der Trap den Dämon fortsetzen (siehe
(<)).
- Die Traps laufen zwar im Supervisor-Mode, die Interruptsperre
ist allerdings fast nie gesetzt. (=> Während ein Trap läuft,
kann jeder der Scheduler oder der Dispatcher für den Aufruf
vorgemerkt werden. Siehe auch (<))
-
Preemption: Ist innerhalb eines Traps eine Schleife programmiert,
deren Abarbeitungsdauer nicht determiniert ist (z.B. Suche nach
freiem Speicherplatz), prüft der Trap immer wieder am Ende eines
Befehlsblockes, ob das DPC-Flag gesetzt ist. Ist das der Fall,
rettet der Trap die gerade bearbeitete Adresse in eine Systemzelle
und springt den Dispatcher an. Der Dispatcher löscht bei jedem
Taskwechsel diese Zelle, so daß der Trap weiß, ob er an der
alten Stelle weitermachen kann oder von vorne beginnen muß.
(Gedanke: Falls zwischendurch eine andere Task lief, könnte sich
ein Ring/eine Kette geändert haben => Neustart der
Systemfunktion notwendig.)
/\ Input / Output
- Für jede Rechnerschnittstelle gibt es einen oder mehrere
I/O-Dämonen und eine IRSR (Siehe (<)), die mit dem Dämon/ den
Dämonen zusammenarbeitet.
- Das I/O geschieht über Traps, die Nachrichten an I/O-Dämonen
senden. Das I/O macht dann der Dämon.
Neben dem Dämon darf nur noch die IRSR, die die
Rechnerschnittstelle betreut, Daten und Zustände der
angeschlossenen Peripherie auslesen und die Daten im Eingabepuffer
ablegen. Falls im Ausgabepuffer des Dämons noch Zeichen sind, kann
eine IRSR auch gleich das nächste Zeichen an die Peripherie senden.
Evtl. ändert die IRSR den Taskzustand des Dämons. Es gelten die
gleichen Einschränkungen wie bei (<).
/\ Dispatcher
- Der Dispatcher hat drei Aufgaben:
- Ist die laufende Task nicht länger lauffähig oder wurde eine
höherpriore Task lauffähig, rettet er den Taskkontext dieser Task.
- Wird eine "schlafende" Task die höchstpriorisierte
lauffähige, reserviert der Dispatcher freien Speicher, der neben
den Task-Variablen auch Platz für den Kontext enthält.
Anschließend teilt er der Task die CPU zu.
- Lief die höchstpriore lauffähige Task schon einmal, lädt
er deren Kontext und teilt der Task die CPU zu. Der Dispatcher
macht selbst kein I/O.
- Stellt der Dispatcher bei einem Lauf fest, daß die vorher
laufende Task auch weiterhin die CPU behalten darf, wird kein
Kontext gerettet bzw. geladen und die Task einfach fortgesetzt.
-
Der Dispatcher prüft als erstes, ob einer der beiden Scheduler
laufen muß (Siehe (<)). Ist das der Fall, verzweigt er in den
Scheduler, dessen Lauf von einer IRSR gewünscht wurde.
- Der Dispatcher läuft nur an, wenn der "Outer-State" der
User-Mode ist. Ist der "Outer-State" der Supervisor-Mode, setzt er
lediglich das DPC-Flag, und setzt den Prozeß erster Art, auf den
der System-Stack-Pointer zeigt, mit dem Assembler-Befehl "Return
from Interrupt" fort. Möglich wenn:
- Nach dem Anlauf löscht der Dispatcher als erstes bei gesetzter
Interruptsperre des Prozessors das DPC-Flag.
-
Beendet sich eine IRSR, die einen Prozeß zweiter Art
unterbrochen hat, durch Aussprung in den Dispatcher und hat kein
Prozeß erster Art in der Zwischenzeit das DPC-Flag gesetzt,
läuft der Dispatcher gar nicht erst an und kehrt in den Prozeß
zweiter Art zurück.
-
Hat der Dispatcher den Kontext einer Task gerettet, löscht er
die Zelle mit der Taskadresse (siehe auch (<)). Auf diese Weise kann
er im Inter-Task-State erneut anlaufen oder auch zwischendurch,
falls benötigt, die Scheduler aufrufen.
-
Unmittelbar nach dem Laden eines Taskkontextes schreibt der
Dispatcher die Taskadresse in die entsprechende Systemzelle
(siehe auch (<)).
- Der Dispatcher läuft zwar im Supervisor-Mode, die
Interruptsperre des Prozessors ist allerdings fast nie gesetzt.
-
Während der Dispatcher läuft, kann er erneut für den Aufruf
vorgemerkt werden bzw. sogar angesprungen werden. (Siehe (<)).
Beendet sich eine IRSR durch Sprung in den Dispatcher, dann erkennt
der Dispatcher, daß der "Outer-State" der Supervisor-Mode ist und
kehrt per Assembler-Befehl "Return from Interrupt" an die Stelle
des Dispatchers zurück, die auf dem Supervisor-Stack liegt.
- Auch der Dispatcher prüft an verschiedenen Stellen, ob ein
Re-Dispatching notwendig ist und startet ggf. (durch einen Sprung
und nicht durch einen Procedure-Call!!!) von vorne. Die
vorletzte Prüfung erfolgt im Inter-Task-State (siehe (<)). Ein
letzter Test erfolgt bei gesetzter Interruptsperre des Prozessors,
kurz bevor der höchstpriore lauffähige Prozeß zweiter Art im
User-Mode fortgesetzt bzw. gestartet wird.
- Im System gibt es immer eine lauffähige Task, die sogenannte
Idle-Task. Sie hat die niedrigste Priorität. Ihr einziger Befehl
lautet "BRA $" (Sprung auf sich selbst).
- Seitdem selbst der Dispatcher preemptionfähig ist, ist die
Idle-Task eigentlich überflüssig geworden. Hat keine Task den
Zustand lauffähig, können nur noch IRSR oder die beiden Scheduler
eine Task in den Zustand lauffähig versetzen. Beides bekommt der
Dispatcher mit.
/\ Scheduler
- Die Scheduler haben zwei grundsätzliche Aufgaben:
- Sie können Taskzustände von "blockiert" auf
"lauffähig" ändern (Hochsprach-Befehle
WHEN...CONTINUE,
AT...CONTINUE,
AFTER...CONTINUE,
AFTER...RESUME)
oder von "eingeplant" auf "lauffähig" (Hochsprach-Befehle
WHEN...ACTIVATE,
AT...ACTIVATE,
AT...ALL...UNTIL...ACTIVATE,
AFTER...ALL...UNTIL...ACTIVATE etc.)
- Ereilt eine Task eine Aktivierung, während sie läuft,
werden bis zu drei Aktivierungen samt Priorität für die Task
gepuffert.
Der Clock-Scheduler hat darüber hinaus vier weitere:
- Er prüft, bei welcher Uhrzeit die nächste zeitliche
Einplanung fällig ist und legt diese Zeit in einer mit der
Timer-IRSR und den entsprechenden Traps gemeinsam genutzten
Zelle ab.
- Bei zyklisch eingeplanten Tasks (z.B. durch
ALL...ACTIVATE) berechnet der Clock-Scheduler den Zeitpunkt,
wann die Task erneut aktiviert bzw. fortgesetzt werden muß
und trägt den neuen Zeitpunkt in der Verwaltungsstruktur der Task
ein.
- Bei zyklisch eingeplanten Tasks mit Einplanungsende
(z.B. durch
ALL...ACTIVATE...UNTIL)
plant er die Task nach Erreichen des Endezeitpunkts aus.
- Um Mitternacht setzt er die Uhrzeit auf 0:0:0.00000 und
erhöht die Datumszelle.
- Die Scheduler laufen nur an, wenn der "Outer-State" der
User-Mode ist. Ist der "Outer-State" der Supervisor-Mode, setzt
der gerufene Scheduler das entsprechende Scheduler-Call-Flag,
und setzt den Prozeß erster Art, auf den der System-Stack-Pointer
zeigt, fort. Möglich, wenn:
- Sich eine IRSR durch Scheduleransprung beendet, diese IRSR
jedoch einen niederpriore IRSR unterbrochen hatte.
- Sich eine IRSR durch Scheduleransprung beendet, diese IRSR
jedoch einen Trap unterbrochen hatte.
- Nach dem Anlaufen löschen die Scheduler bei gesetzter
Interruptsperre des Prozessors ihr Scheduler-Call-Flag. Die
Scheduler beenden sich durch Aussprung in den Dispatcher.
- Die Scheduler laufen zwar im Supervisor-Mode, die
Interruptsperre des Prozessors ist allerdings fast nie gesetzt.
(=> Während einer der Scheduler läuft, kann er erneut für den
Aufruf vorgemerkt werden bzw. sogar angesprungen werden.
(<) gilt analog.)
- Die für die zeitlichen und zyklischen Einplanungen
vorgesehenen Traps ändern den Zeitpunkt, an dem die Timer-IRSR
in den Clock-Scheduler springt, wenn die neue Einplanung früher
eintritt als die bisher früheste zeitliche Einplanung.
- Der Clock-Scheduler wird nur aktiv, wenn die Timer-IRSR
festgestellt hat, daß die vom Clock-Scheduler bzw. von den
entsprechenden Traps vorgegebene Zeit erreicht ist.
/\
|