zurück : weiter : inhalt =

 

3.2             **      Processor-Traps

 

Die Processor-Traps im QL sind eingeteilt:
 

 
Auf die Aufrufe der Traps #1 bis #3 wird des Umfangs und der Bedeutung wegen in besonderen Kapiteln ausführlich eingegangen. Wo anwenbar, finden sich weitere Hinweise.

Vorneweg die sonst noch vom System benutzten Traps abgehandelt, da deren Funktion recht schnell beschrieben ist.
 
 

3.2.1   *       Trap #0

Ein reiner Hilfsdient zum Übergang in den Supervisor-Betrieb, der keinerlei Probleme aufwirft. Wobei ja, um das noch einmal in's Gedächtnis zu rufen, im Processor nichts weiter geschieht, als daß der Stack gewechselt wird und danach ein paar mehr Befehle brauchbar sind.

Das System hält in dieser Betriebsart den Scheduler an. Darum kann kein anderer Job mehr in den laufenden Vorgang eingreifen. Unterbrechungen sind dann nur noch durch die verschiedenen Interrupts möglich oder mittelbar durch den Aufruf anderer QDOS-Traps mit Wartezeit (Trap #3) oder von Managertraps (Trap #1), die nicht "atomic" arbeiten, d.h. ohne den Scheduler zu aktivieren, s. Hinweise weiter unten.

Für zustandsunabhänge Programme ist zuvor der Statuscode zu sichern und bei der Rückkehr mit  unveränderten(!) Interrupt-Flags wiederherzustellen. Dabei ist zum Zurückschalten in den User-Mode der verschiedentlich in der Literatur zu findende Befehl

 and.w    #$d8ff,sr               {4}, {SNG}
gänzlich unbrauchbar, denn ungeachtet der wirklichen Verhältnisse gibt er stets alle Interruptebenen frei. Derselbe Unsinn ist das anscheinend gleichermaßen beliebte
move.w   #0,sr
Beides hat verschiedentlich schon übelste Fehler ausgelöst.

Im Standard-QL empfiehlt sich etwa eine Sequenz dieser Art:

                move.w  sr,d0                   Eingangs den Status holen
                trap       #0                      Supervisor
                move.w  d0,-(sp)               Status vom Aufruf kellern
                      ... Programm in Supervisor Mode ...
                move.w  sr,-(sp)                aktuelle Flags ablegen
                move.b  2(sp),(sp)             alten Status eintragen
                move.w  (sp)+,(sp)            Rest des Stack freigeben
                move.w  (sp)+,sr               zusammengesetzter Status,
                                                       zugleich alte Betriebsart
Womit bei unveränderten Registern einerseits die gerade ermittelten Rechner-Flags richtig weitergegeben werden, andererseits aber der Processorstatus vollständig erhalten bleibt. So erfolgt die Rückkehr in die alte Betriebsart, gleichgültig, ob dies nun User oder Supervisor Mode war. Der vorherige Interruptstatus bleibt ebenfalls erhalten.
Der Aufruf ist damit uneingeschränkt reentrant. Recursion und Wechsel der Betriebsarten zwischen den Aufrufen sind möglich. Restriktionen, solch ein Teilprogramm etwa nur im User Mode aufzurufen, sind unnötig.

O.a. Codebeispiel ist bei den Varianten mit Processoren ab 68010 nur brauchbar, wenn das System einen "exception-handler" bereitstellt (s.Anhang).

Erzwungener Übergang zum User-Modus durch Rücksetzen des Status-Bit 13:
 

                trap            #0
                  ... Supervisor Programm ...
                and.w   #$dfff,sr

Diese Befehlsfolge findet sich in etlichen Qdos-Aufrufen {MGG, MINERVA}. So erklärt sich von selbst, daß es Teile gibt, die nur im User-Mode aufgerufen werden dürfen. Denn die Rückkehr wird hierdurch ungeachtet des ursprüglichen Zustandes immer in dieser Betriebsart erfolgen.

Dazu gehören alle Trap-Aufrufe, bei denen der Scheduler in's Spiel gebracht wird.

In der Trap #1:
        MT.RJOB          4
        MT.FRJOB        5
        MT.SUSJB         8
        MT.RELJB         9
        MT.ACTIV       10 $0A
        MT.PRIOR       11 $0B

In der Trap #3  alle Aufrufe mit Wartezeit.
 
 

3.2.2                   *            Trap #4

Nach diesem Aufruf ist die relative Adressierung bezüglich A6 möglich. Strings beispielsweise, die als Parameter an eine Basic-Erweiterung übergeben wurden, lassen sich dann zum Öffnen eines Kanals als Filenamen ohne weiteres gleich weitergeben. Die Möglichkeiten zum Aufbau besonderer und flexibler Strukturen sind bei Unabhängigkeit von absolut bekannten Adressen außerordentlich vielfältig. Basic als im Speicher jederzeit verschiebbarer Job ist ein Beispiel.

Auf den nächsten Aufruf beschränkt wird bei Trap #2 die mit A0, bei Trap #3 die mit A1 übergebene Adresse relativ zu A6 ausgewertet.  Es sind weder besondere Parameter zu übergeben, noch werden irgendwelche Register verändert.

Wichtig ist die einzige Ausnahme bei Rückkehr mit ERR.NO (-6), wenn der angegebene Kanal nicht offen ist. In diesem Falle wirkt die relative Adressierung weiter {1}. Eine solche Situation kann nahezu ausgeschlossen werden, wenn vorher die übergebene ID geprüft wird. Wurde in der Zeit zwischen dieser Kontrolle und der Ausführung des Aufrufs der Kanal durch einen anderen Job doch noch weggenommen, ist notfalls durch irgendeine mit Sicherheit erfolgreiche Operation die relative Adressierung aufzuheben.

Der fällige Aufruf einer Trap #2 oder #3 muß in derselben Aufrufebene mit der Trap #4 erfolgen. Mit anderen Worten, der Trap #4 darf der Aufruf der Trap #2 oder #3 nicht in einer Subroutine folgen. Zwischen den beiden Trap-Aufrufen können Veränderungen im Stack  zu Fehlern führen. Das System legt dort Daten und Adressen ab, die für die ordentliche Rückkehr nicht gestört werden dürfen.

Wobei sich die Fehlersituation bislang allerdings nur mit älteren Versionen der MINERVA ergeben hat. Die Resultate mit der probehalber benutzten Funktion EDLINE$ aus {4} sind in den anderen Roms fehlerlos. Damit Programme überall sicher arbeiten, ist obige Schutzmaßnahme jedoch stets angebracht, zumal im allgemeinen allein die überlegte Anordnung ausreicht.

Anwendungen der Trap #4 sind in den Basic-Befehlen zum STAK-Device der Programmbeispiele gezeigt.

Damit sind diese besonderen Traps auch schon abgehandelt. Schwierigkeiten sollte es im Zusammenhang damit nicht geben, denn beide sind ansich ganz problemlos.
 
 

3.2.3                   *            Traps #5 bis #15

Aufrufe sind hier nicht vorgegeben. Allen Jobs lassen sich aber in einer Tabelle entsprechend definierte Vectoren mit der Qdos-Trap MT.TRAPV (1/7) mitgeben. Sie gelten dann bis zu einer Änderung für diesen und alle Jobs, die durch ihn eingerichtet werden - er muß nicht ihr Besitzer sein.

MT.TRAPV wird aufgerufen mit
        D0 = 7       Op-Code für diesen Aufruf
        D1             Job-ID / -1 für den aktuellen Job
        A1             Ptr auf die Vectorentabelle

Es kommen zurück
        D1              die wirkliche Job-ID
        A0              Basisadresse des Jobs
        A1              wird verdorben

Die Tabelle ist mit absolut angegebenen 32-Bit-Adressen folgendermaßen aufzubauen (bezeichnet nach M*rola):
          00     Address Error
          04     Illegal Instruction
          08     Division durch Null
        $0C     CHK
        $10     TRAPV
        $14     Privilege Violation
        $18     Trace
        $1C     Interrupt Level 7 (z.B. CTRL/ALT/"7")
        $20     Trap #5
        ...       frei einsetzbare Aufrufe weiter bis
        $48     Trap #15
        $4C     Ende der Tabelle

Die über diese Vectoren aufgerufenen Programme müssen mit RTE enden, alle benutzten Register sind zu sichern und vor dem Rücksprung wiederherzustellen.

Im Interesse der Übertragbarkeit von Programmen sollte auf den Zugriff auf Daten im Supervisor-Stack, oder über jenen hinaus, ganz verzichtet werden. Unbedingt aber muß dann der jeweils vorhandene Processortyp berücksichtigt werden, von denen jeder einzelne dort unterschiedliche Datenstrukturen anlegt, dies z. Teil auch noch in einer Vielzahl Varianten für die verschiedenen "exceptions" ein und desselben Processortyps.

Der Vector für Adressierungsfehler beispielsweise erhält im Stack folgende Mitteilungen über die Fehlerursache:

 00 .w  Bits 0-1   %01    Zugriff auf den Datenspeicher
                           %10    dto., Programmspeicher
                           %11    Interrupt-Quittung
            Bit  2   0 User-  1 Supervisor-Mode
            Bit  3   Befehlstyp beim Auslöser
                            1   Code, Programmierte Trap, Div. Null
                            0   andere Ausnahmevectoren
            Bit  4   1 Auslöser war Datenquelle, 0 -Ziel
 02 .l      Adresse der Fehlersituation
 06 .w    Befehlsregister des Processors (Op-Code)
 08 .w    Statusregister dto.
$0A .l     Programmzähler "2 - 10 Bytes nach dem Aufruf"

Ein erneuter Adressierungsfehler führt zum Stillstand des Processors. Start ist dann nur mit Hardware-Reset möglich.
 

 


oben : zurück : weiter : inhalt 

= (count)