.LEFT MARGIN 5.RIGHT MARGIN 80 .CENTER Abort AST's in Fortran (and other high level languages). .BLANK .CENTER B.#Z.#Lederman .BLANK .CENTER Bankers Trust Co. .PARAGRAPH Some time previously an article was published showing how to do such things as AST's from Fortran programs, and in particular the Abort AST CALL#SREA identified as calling and EXTERNAL function address. This is really nice when you want a program to clean itself up before exiting when it is aborted by command (or ran over the time limit in a Batch job, or some similar contition). I followed the instructions in the example, and it worked very well on RSX-11M-Plus, but I began to run into problems when I tried to move the same program to a PRO-350 with P/OS. The system documentation (both M-Plus and P/OS) clearly state that there are severe limitations on doing AST servicing in Fortran for various reasons, including the fact that the OTS impure regions can get very messed up. You are not supposed to do any Fortran I/O or file services in AST state, which limits the clean-up you can do. My program was doing some I/O, and got away with it on M-Plus, but it worked only some of the time on P/OS. Because I wanted my programs to work every time, I developed the following simple subroutine which does all of the AST servicing in a macro module: because it exits AST state when done, your high level language program can do what it wants when cleaning up. .PARAGRAPH The module is very simple: .BLANK.NO JUSTIFY.NO FILL .TITLE ABORT .IDENT /V2.0/ ; ; Abort AST function for Fortran programs ; ; B. Z. Lederman Bankers Trust Co. ; ; Use of this module is entirely at the users' risk. No liability ; of any kind is assumed. ; .MCALL ASTX$S, SREX$S ; ; The following PSECT matches the attributes set by Fortran for ; common areas. ; .PSECT ABOCOM, RW, D, GBL, REL, OVR ABOFLG:: .WORD 0 ; LOGICAL*2 data type ; .PSECT $ABRTC, RO, I, GBL, CON, LCL ; ABOINI:: CLR ABOFLG ; set abort to .FALSE. SREX$S #ABOAST ; specify AST point RETURN ; return to main program ; ABOAST:: ADD (SP), SP ; clean up stack DEC ABOFLG ; set abort to .TRUE. ASTX$S ; leave AST state ; .END .BLANK.JUSTIFY.FILL The PSECTs have been chosen to be compatible with those produced by the Fortran-77 (and Fortran-IV-Plus) compilers, and can be seperated into I and D space. It is an ABSOLUTE requirement that this module be in the ROOT of your program (both the code and the data common PSECTS), otherwise you may not receive AST notification properly. An example of how the module is used follows. .BLANK.NO JUSTIFY.NO FILL PROGRAM ABOTST C C Test Abort-AST action C C B. Z. Lederman C LOGICAL*2 ABOFLG C COMMON /ABOCOM/ ABOFLG C C Initialize abort C CALL ABOINI C OPEN (UNIT = 1, FILE = 'ABOTST.DAT', STATUS = 'NEW') C C Begin dummy loop C DO 100 I = 1, 10000 DO 100 J = 1, 10000 DO 100 K = 1, 10000 IF (ABOFLG) GOTO 900 WRITE (1, 920) I, J, K 100 CONTINUE STOP ' Reached end of all loops' C 900 WRITE (5, 920) I, J, K 920 FORMAT( 3( 1X, I5) ) CLOSE (UNIT = 1) CALL EXIT C END .JUSTIFY.FILL.PARAGRAPH The declaration of ABOFLG as LOGICAL*2 and ABOCOM are used to match up the variable and the area where it is stored. The call to ABOINI should occur at the beginning of your program to set ABOFLG and the abort AST entry points to the correct values. The task build would be something like this: .BLANK #TKB#ABOTST#=#ABOTST,#ABORT .BLANK Or if overlayed, the ODL file should have something like: .BLANK ########.ROOT###ABOTST-ABORT-*(#tree1,#tree2,#etc.) .BLANK Both of which are intended to force the ABORT module into the root of the program. .PARAGRAPH The benefit of abort AST's may be seen by running the above program: when aborted, the program will close the file ABOTST.DAT, and print out the current values of I, J, and K on the terminal. If you run the same program without the AST routines and abort it, the file ABOTST.DAT will be locked, and you will not learn the state the program was in when aborted. I am sure that nearly every reader can think of an application where it is desireable for a program to do clean-up work when aborted, or at least to leave files properly closed rather than locked. .PARAGRAPH To derive the greatest benefit from this abort AST routine, you must test ABOFLG fairly often: the macro module only sets the value of ABOFLG, and it is up to you to test it's status and shutup when you are supposed to. I generally put it at the beginning of any long loops, or before reading new data to process, or after writing out a data item, or in similar "breaks" in processing. In the above example, the test IF#(ABOFLG)#GOTO#900 will occur on every pass through the loop, so notification that an abort AST has been received will be quick. .PARAGRAPH I would hope the following information is superfluous, but in case it isn't: do not use the variable ABOFLG for anything else in your program, and don't put any other variables into ABOCOM. .PARAGRAPH This method should work just as well for other languages. The requirements are that you be able to declare some kind of common area for ABOFLG, and that you be able to declare a one word integer and test it's state. It will be zero (all bits off) if false (no abort yet), and a minus one (all bits on) if true (time to abort). Fortran-77 tests only the sign bit, but any test that can distinguish these two states is equally valid. The calling convention to ABOINI is the usual DEC convention (JSR#PC,#ABOFLG), with the argument list on R5: in this case, there are no arguments, so no registers are tested or altered. The RETURN statement translates to an RTS#PC. .PARAGRAPH An alternative I considered was to have the macro module do a subroutine call to an ENTRY in the main program from the AST service routine. The problem with this would be that the Fortran program would have to do servicing at AST time, which is exactly what needs to be avoided. However, the restrictions on AST service might not apply to some other high level languages, and if declaring a common region is difficult in that other language, then it might be easier to have the macro module do a call to the other language module which will do the abort clean up and exit. If you do try this, remember that when the AST service state is entered, the stack has additional information placed on it, and that other registers may not be preserved.