next up previous contents index
Next: ZVERIF - check Up: Global operational aids Previous: ZABEND - abnormal

ZTELL - recover trouble through ZTELL-ZTELUS

During normal operation any request from the user for space with MZWORK, MZLIFT et al. is satisfied, after garbage collection if necessary and possible. If however the request cannot be satisfied, the normal course of the program must be broken. To deliver the user from the burden of checking for success after each space request, the garbage collector sends control to the user at the entry-point QNEXT (via ZTELL and the KERNLIB routine QNEXTE), where he can program the recovery of the problem. Normally this will be to skip the current event and to continue with processing the next one.

Other Zebra packages, apart from MZ, and maybe the user himself, have similar problems. Therefore a general trouble control routine ZTELL has been included into Zebra. This is a switching routine with several modes of continuation, one of which is to send control to QNEXT. ZTELL can also be called by the user program, thus:

CALL ZTELL (ID,IFLAG)

    ID     is an integer between 101 and 999,
           ID's below 100 are reserved for system usage,
           ID=99 for 'no memory left' from MZGARB.

    IFLAG  is a flag indicating whether the calling code can
           accept a RETURN from ZTELL:
           = 0 ZTELL may return;
           = 1 the calling code is not capable to accept a RETURN;
           = 2 fatal error, the run must stop.

ZTELL prints a message, sets up a reasonable exit mode as a function of ID and IFLAG into the little labelled common /ZTELLC/ and calls ZTELUS to give the user a chance to modify this mode. On the obligatory return from ZTELUS it takes the selected exit as follows:

    COMMON /ZTELLC/ ID, MODE

    ID     is a copy of the first parameter to ZTELL;
    MODE   is the selected exit mode:
           = 0 RETURN to let the calling routine continue;
           = 1 CALL QNEXTE to enter QNEXT
           = 2 CALL ZFATAL
           = 3 CALL ZEND

The exit mode to QNEXT is enabled only if NQPHAS in /ZSTATE/ is larger than zero, indicating that the program is in the normal operation phase. During the initialisation or the termination phase of the program transfer is to ZFATAL instead, to avoid a program crash to be 'recovered' into normal operation.

The pre-loading of MODE is MODE=IFLAG for user calls (ID>100); and for system calls (ID<100) it is as shown in the diagnostics chapter for ZTELL.

CALL ZTELUS

Here is an example of a ZTELUS which is happy with the default modes, except that it wants to go to ZEND for ID=8:

      SUBROUTINE ZTELUS
      COMMON /ZTELLC/ ID,MODE

      IF (ID.EQ.8)  MODE=3
      RETURN
      END
The default subroutine ZTELUS on the library is a do-nothing dummy. The default subroutine QNEXT goes straight to ZFATAL.

CALL QNEXT

On most machines repeated recovery directly to QNEXT causes trouble with the Fortran trace-back and the subroutine stack. For this reason ZEBRA relies on the KERNLIB routine QNEXTE, which implies an organization for event processing as follows:

 _________________________
|                         |          Program flow with QNEXT recovery
|    MAIN program         |
|                         |
|    CALL MZEBRA (0)      |
|    CALL MZSTOR (...)    |
|                         |
|    program              |                                _________
|    initialization       |                               |         |
|                         |                               |         |
|    CALL ZPHASE (0)      | first entry           recover |         |
|    CALL QNEXTE          | ------       _________       _|         |
|_________________________|      `----> |         |     |           |
                                        | routine |     |  routine  |
          <---------------------------< | QNEXTE  | <-- |  ZTELL    |
         |                              |_________|     |_          |
 ________|________________                                |         |
|                         |                               |         |
|    subr QNEXT           |                               |         |
|                         |                               |         |
| 11 CALL MZWIPE (0)      |       requests                |         |
|    read event           | ----------------------------> |  Zebra  |
|    IF (end) CALL ZEND   |                               |  system |
|    process event        | <---------------------------- |         |
|    output event         |               normal RETURN's |         |
|    GO TO 11             |                               |         |
|_________________________|                               |         |
         |                                                |         |
 ________|________________        __________              |         |
|                         |      |          |             |         |
|    subr ZEND            | <--- |  subr    | <---        |         |
|                         |      |  ZABEND  |     |      _|         |
|    CALL ZPHASE (-3)     |      |__________|     |     |           |
|                         |                       |     |  routine  |
|    program              |                       `---< |  ZFATAL   |
|    termination          |                             |_          |
|_________________________|                               |_________|
The initialisation part prepares the program to be ready for execution and then calls itself QNEXTE for entry to QNEXT to process the 'next event', being the first event in this case. QNEXT loops internally to process all events.

CALL's from the processing program to the Zebra system are normally satisfied, and control comes back to the user with normal RETURN. Abnormal returns are either via ZFATAL to ZEND, or straight to ZEND, or to QNEXT via QNEXTE.

The Fortran version of QNEXTE is a simple CALL \Rind{QNEXT} followed by RETURN. If necessary on a given computer, QNEXTE is a machine-language or a C routine to unwind to itself the Fortran trace-back and the subroutine stack. So, if the user wishes at some point to abandon himself the curent event and to go to the next one, he should CALL \Rind{QNEXTE} and not QNEXT.

QNEXT is a user routine to the KERNLIB routine QNEXTE and has thus the usual problem of user routines called from a library routine in that it must be loaded explicitely:

   either:  compile it together with the other material
       or:  if it resides on a user library it must be
             INCLUDEd explicitly, for example on the VAX with
             $ LINK  ...   MYLIB/INC=QNEXT/LIB  ...

This flow-diagram is only an example for the most common case of actual usage of Zebra. If one's program is not of the event-processing type one has to look at QNEXTE/QNEXT from a different angle: program flow from MAIN has to go to QNEXTE to initialize for re-entry. Entry and all re-entries are then to QNEXT, which has to control the further program flow according to some flags, conveniently ID in /ZTELLC/ and NQPHAS in /ZSTATE/. ID is not initialized by MZEBRA, it is only changed by ZTELL which copies its first parameter to ID. This number is an integer in the range 1 to 99 for calls from the Zebra system. NQPHAS is initialized to zero by MZEBRA, it is then changed only by the user (or the default ZABEND) either directly or with ZPHASE.



next up previous contents index
Next: ZVERIF - check Up: Global operational aids Previous: ZABEND - abnormal


Janne Saarela
Mon May 15 08:34:47 METDST 1995