RTOS

Das Echtzeitbetriebssystem für die Automatisierungstechnik

Home   Übersicht   Dokumentation   Downloads   Literatur   Kontakt  

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

  1. 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.
  2. 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.
  3. 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.
  4. 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 (<)).

  5. RTOS-UH ist frei von Polling-Schleifen, da es komplett interruptgetrieben arbeitet.
  6. 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

  1. Im Dispatcher-Ring sind alle Tasks prioritätssortiert aufgenommen, die nicht den Taskzustand "schlafend" haben.
  2. Der Dispatcher teilt der höchstpriorisierten lauffähigen Task den Prozessor zu.
  3. Im Dispatcher-Ring wird nicht zwischen "lauffähig" und "laufend" unterschieden, da einfach die höchstpriorisierte lauffähige Task den Prozessor zugeteilt bekommt.
  4. 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 (<)).
  5. 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.
  6. Das Ändern der Priorität einer Task erfordert ein Umketten. (Nur für bestimmte Traps erlaubt.)
  7. 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

  1. 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 (<)).
  2. Für IRSR ist es verboten, Traps aufzurufen.
  3. IRSR dürfen den Taskzustand aller Tasks ändern, die sich im Dispatcher-Ring befinden, solange die Tasks an der gleichen Stelle im Ring bleiben.
  4. IRSR dürfen kein I/O machen (Siehe (<)).
  5. 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.
  6. 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

  1. Jeder Trapaufruf endet mit einem Sprung in den Dispatcher (der aber nicht jedesmal deshalb anläuft, siehe (<)).
  2. 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 (<)).
  3. 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 (<)).
  4. 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 (<))
  5. 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

  1. 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.
  2. 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

  1. 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.

  2. 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.
  3. 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.
  4. 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:
    • Sich eine IRSR durch Dispatcheransprung beendet, diese IRSR jedoch eine niederpriore IRSR unterbrochen hatte.
    • Sich eine IRSR durch Dispatcheransprung beendet, diese IRSR jedoch einen Trap unterbrochen hatte.
    • Sich ein Prozeß zweiter Art in den Supervisor-Mode begeben hat (Trap "OFF") und dann einen anderen Trap (außer "DPC") aufruft, bevor er den Supervisor-Mode mit dem Trap "DPC" verlassen hat. Diese nicht erlaubte, aber vom System beherrschte Variante ist nur in Assemblerprogrammen möglich.

      Ausnahme: Der Dispatcher kann anlaufen, wenn im Supervisor-Mode Ausnahmebehandlungen forciert wurden, wie zum Beispiel Wrong-"Öpcode-Error und Bus-Error.

  5. Nach dem Anlauf löscht der Dispatcher als erstes bei gesetzter Interruptsperre des Prozessors das DPC-Flag.
  6. 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.
  7. 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.
  8. Unmittelbar nach dem Laden eines Taskkontextes schreibt der Dispatcher die Taskadresse in die entsprechende Systemzelle (siehe auch (<)).
  9. Der Dispatcher läuft zwar im Supervisor-Mode, die Interruptsperre des Prozessors ist allerdings fast nie gesetzt.
  10. 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.
  11. 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.
  12. 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).
  13. 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

  1. 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.

  2. 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.

  3. 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.
  4. 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.)
  5. 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.
  6. 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.

/\

07.08.2008     Thomas Probol, Torsten Lilge (E-Mail)     Impressum