Bei speziellen Anforderungen, die durch die Funktionen signal und raise nicht abgedeckt sind (siehe Abschnitt "C-Bibliotheksfunktionen (alarm, raise, signal)“), können die entsprechenden BS2000-Funktionen für Ereignissteuerung frei programmiert werden. Solche Anforderungen sind z.B. eine größere Anzahl von Ereignissen (mit raise und signal lassen sich nur zwei Ereignisse selbst definieren) oder Inter-Task-Kommunikation (mit raise und signal ist Ereignissteuerung nur innerhalb eines Tasks möglich).
Funktionen zur eigentlichen Ereignissteuerung, wie etwa das Eröffnen 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 _abnorm1 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 */
Aufbau der Contingency-Routine:
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>
int controut (struct contp contpar)
{ .
.
.
return ...;
}
Die C-Routine kann auf eine der folgenden zwei Arten beendet werden:
mit der
return-Anweisung, das Programm wird an der unterbrochenen Stelle fortgesetzt oderdurch Aufruf der Funktion
longjmp, das Programm wird 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.