Bei speziellen Anforderungen, die durch signal()
und raise()
nicht abgedeckt sind, können die entsprechenden BS2000-Funktionen für Ereignissteuerung frei programmiert werden. Solche Anforderungen sind z.B. eine größere Anzahl von Ereignissen (mit rraise()
und signal()
lassen sich nur zwei Ereignisse selbst definieren) oder Inter-Task-Kommunikation (mit raise()
und signal()
ist Ereignissteuerung nur innerhalb einer Task möglich).
Funktionen zur eigentlichen Ereignissteuerung, wie etwa das Starten der ereignisgesteuerten Verarbeitung (Signale senden und empfangen) müssen in Assembler-Programmteilen mit den entsprechenden BS2000-Makroaufrufen (POSSIG
, SOLSIG
, ENAEI
) realisiert werden.
Die Makros zum Anmelden, Abmelden und Beenden von Contingency-Prozessen (ENACO, DISCO
, RETCO
) dürfen jedoch nicht im Assembler-Programmteil verwendet werden. Statt dieser Makros müssen die C-Bibliotheksfunktion cenaco()
bzw. cdisco()
aufgerufen werden. cenaco()
und cdisco()
führen neben dem An- und Abmelden einer Contingency-Routine Aktionen durch, die für die Konsistenz-Sicherung des C-Laufzeitstacks notwendig sind.
Die Contingency-Routine selbst kann sowohl in C als auch in Assembler geschrieben werden. Die Beendigung dieser Routine muss mit einem "normalen" Rücksprung erfolgen (in C mit return()
bzw. longjmp()
, in Assembler mit @EXIT
).
Contingency-Routine in C
Der Routine wird bei ihrem Anlauf ein Strukturparameter übergeben, der in der Include-Datei cont.h
folgendermaßen deklariert ist:
struct contp { int comess; /* contingency message */ evcode indicat; /* information indicator */ char filler[2]; /* reserved for int. use */ evcode switchc; /* event switch */ int pcode; /* post code */ int reg4; /* register 4 */ int reg5; /* register 5 */ int reg6; /* register 6 */ int reg7; /* register 7 */ int reg8; /* register 8 */ }; #define evcode char #define _normal 0 /* evceventnormal */ #define _abnormal 4 /* evceventabnormal */ #define _nmnpc 0 /* evcnocomessnopostcode */ #define _mnpc 4 /* evccomessnopostcode */ #define _nmpc 8 /* evcnocomesspostcode */ #define _mpc 12 /* evccomesspostcode */ #define _etnm 0 /* evcelapsedtimenocomess */ #define _etm 4 /* evcelapsedtimecomess */ #define _disnm 16 /* evceventdisablednocomess */ #define _dism 20 /* evceventdisabledcomess */
Wenn der oben beschriebene Strukturparameter ausgewertet werden soll, muss die C-Routine einen formalen Parameter für eine Struktur vom Typ contp
vorsehen und ist dann etwa folgendermaßen aufgebaut:
#include <cont.h> void controut (struct contp contpar) { ... return ...; }
Die C-Routine kann auf eine der folgenden zwei Arten beendet werden:
mit der
return
-Anweisung. Dann wird das Programm an der unterbrochenen Stelle fortgesetzt.durch Aufruf der Funktion
longjmp()
. Dann wird das Programm bei der mit einemsetjmp
-Aufruf definierten Stelle fortgesetzt.
Contingency-Routine in Assembler
Die Contingency-Routine muss z.B. dann in Assembler geschrieben werden, wenn in ihr weitere BS2000-Makroaufrufe erfolgen sollen (etwa SOLSIG zur Erneuerung der Contingency-Routine).
Ein strukturiertes ILCS-Assemblerprogramm für eine Contingency-Routine hat etwa folgenden Aufbau:
PARLIST DSECT COMESS DS F IND DS C FILLER DS CL2 EC DS C ... CONTROUT @ENTR TYP=E,ILCS=YES USING PARLIST,R1 ... SOLSIG ... @EXIT
In der Contingency-Routine darf der RETCO
-Makro nicht aufgerufen werden. Die Rückkehr muss mit dem Makro @EXIT
erfolgen.