.TITLE RSULOA .IDENT /V7.07/ ;**************************************************************************** ; ; RSULOA ; ; THIS OVERLAY IS RESPONSIBLE FOR THE ANALYSIS OF THE STATISTICS ; WRITTEN BY TASK UPD... ; ; TO BE USED WITH ACCOUNTING SYSTEM VERSION 7. ; ; VERSION: V7 OCTOBER 1981 ; ; STEVE THOMPSON ; SCHOOL OF CHEMICAL ENGINEERING ; OLIN HALL ; CORNELL UNIVERSITY ; ITHACA NY 14853 ; ; REVISION HISTORY ; ---------------- ; ; SMT777 27-OCT-81 THIS MODULE CREATED IN ADDING NEW FUNCTIONALITY ; TO THE RSU COMMAND. ; ; SMT786 10-NOV-81 ADDED /PL SWITCH AND SYSTEM AVAILABILITY ; DISPLAY. ; ; SMT797 8-JAN-82 FIX A BUG IN THE "GETYR" ROUTINE THAT ; INCORRECTLY CALCULATED THE LENGTH OF THE PERIOD ; WHEN A NEW YEAR WAS SPANNED. ; ; SMT812 5-APR-82 CHANGED COMMAND NAME FROM RPT TO RSU ; ; SMT814 12-APR-82 LOWER CASE MESSAGES FOR RSX-11M V4.0 ; ; SMT821 23-APR-82 CHANGED ENTRY POINT NAMES OF ACCOUNTING ; SUPPORT ROUTINES (SEE MODIFY.TXT) ; ; SMT836 6-SEP-82 CHANGED "CALLR" TO "JMP" SINCE RSXMC.MAC ; IS NO LONGER INVOLVED IN THE ASSEMBLY. ; ; SMT839 1-DEC-82 FIX OUTPUT FORMAT PROBLEM ON TERMINALS WITH ; 80-BYTE BUFFERS. ; ; SMT851 22-JUL-83 ADDED RSX-11M V4.1 SUPPORT ; ;*********************************************************************** .MCALL DIR$,DELET$,OPNS$R,PUT$ .MCALL EXST$S,EXIT$S,DELET$,CLOSE$,DELET$,PRINT$ .MCALL EXIT$S STADF$ ; DEFINE STATISTICS BLOCK OFFSETS LF = 12 ; LINEFEED CR = 15 ; CARRIAGE RETURN FF = 14 ; FORMFEED HT = 11 ; HORIZONTAL TAB SPA = 40 ; SPACE ; ; MACROS ; .MACRO PRINT MSG,MSGSZ MOV MSG,TIDPB+Q.IOPL .IF B MSGSZ MOV MSG'SZ,TIDPB+Q.IOPL+2 .IFF MOV MSGSZ,TIDPB+Q.IOPL+2 .ENDC DIR$ #TIDPB .ENDM .MACRO FILE MSG,MSGSZ MOV MSG,FILADR .IF B MSGSZ MOV MSG'SZ,FILSIZ .IFF MOV MSGSZ,FILSIZ .ENDC CALL FILOUT .ENDM .MACRO MOVAX ADR MOV ADR,R1 .REPT 4 MOVB (R1)+,(R0)+ .ENDR .ENDM ; ; ERROR MESSAGES ; .NLIST BEX .IIF DF AA$V40 ! AA$V41, .ENABL LC .IF DF AA$USE & AA$STA .IFF ERR1: .ASCII /RSU -- Feature not supported/ ERR1SZ=.-ERR1 .IFT ERR2: .ASCII /RSU -- Open error on input file/ ERR2SZ=.-ERR2 ERR3: .ASCII /RSU -- Insufficient dynamic memory to allocate plot buffer/ ERR3SZ=.-ERR3 ERR4: .ASCII /RSU -- Read error on input file/ ERR4SZ=.-ERR4 ERR5: .ASCII /RSU -- Unexpected record length at record / ERR5A: .BLKB 10. ERR6: .ASCII /RSU -- Illegal format in record number / ERR6A: .BLKB 10. ERR7: .ASCII /RSU -- *WARNING* no load statistics in specified time period/ ERR7SZ=.-ERR7 ; ; TEXT MESSAGES ; .ENABL LC FROM: .ASCII /System load statistics over the period from: / FROM1: .ASCII / / FROMSZ=.-FROM TO: .ASCII / to: / TO1: .ASCII / / TOSZ=.-TO TOTREC: .ASCII "Total number of data records read/counted = " TOTRC1: .BLKB 12. TOTDYN: .ASCII "Total dynamic memory available/used (bytes) = " TOTDY1: .BLKB 14. MSTOT: .ASCII /Total Elapsed Time / MSTOT1: .BLKB 40. MSELP: .ASCII /Total recorded System Uptime / MSELP1: .BLKB 40. MSEXE: .ASCII /Total recorded Executive Time/ MSEXE1: .BLKB 40. MSIDL: .ASCII /Total recorded Idle Time / MSIDL1: .BLKB 40. MSUSR: .ASCII /Total recorded User Time / MSUSR1: .BLKB 40. MSBAT: .ASCII /Total recorded Batch Time / MSBAT1: .BLKB 40. MSAVL: .ASCII /** System Availability was / MSAVL1: .BLKB 20. XAXIS0: .ASCIZ /T I M E O F D A Y/ XTSIZ=.-XAXIS0-1 XAXIS1: .ASCII / / .ASCII /00:00 / .ASCII /02:00 / .ASCII /04:00 / .ASCII /06:00 / .ASCII /08:00 / .ASCII /10:00 / .ASCII /12:00 / .ASCII /14:00 / .ASCII /16:00 / .ASCII /18:00 / .ASCII /20:00 / .ASCII /22:00 / .ASCIZ /24:/ YAXIS0: .ASCIZ /ESU UPC EGATNECREP/ ; THIS IS BACKWARDS! YTSIZ=.-YAXIS0-1 YAXIS1: .ASCII /100-/ YAXIS2: .ASCII / 80-/ YAXIS3: .ASCII / 60-/ YAXIS4: .ASCII / 40-/ YAXIS5: .ASCII / 20-/ YAXIS6: .ASCII / 0-/ .IFTF .EVEN .IFT ; ; ALLOCATE TABLES FOR STATISTICS STORAGE ; WIDTH = 127. ; PLOT WIDTH (BYTES) HEIGHT = 53. ; PLOT HEIGHT (BYTES) TIMINT = 120. ; NUMBER OF TIME INTERVALS TABLEN = 4*TIMINT ; TABLE LENGTH (BYTES) TABSTT: ; START OF TABLES CPUUSR: .BLKB TABLEN ; USER CPU TIME CPUBAT: .BLKB TABLEN ; BATCH CPU TIME CPUEXE: .BLKB TABLEN ; EXECUTIVE CPU TIME CPUIDL: .BLKB TABLEN ; IDLE CPU TIME CPUTOT: .BLKB TABLEN ; ELAPSED TIME .IF DF AA$LDR LOADER: .BLKB TABLEN ; LOADER REQUSETS .ENDC ; DF AA$LDR .IF DF AA$QIO QIOREQ: .BLKB TABLEN ; I/O REQUSETS .ENDC ; DF AA$QIO .IF DF AA$CSW CONSWT: .BLKB TABLEN ; CONTEXT SWITCHES .ENDC ; DF AA$CSW TOTTIM: .BLKW 2 ; TOTAL ELAPSED TIME TOTUSR: .BLKW 2 ; TOTAL USER CPU TIME TOTBAT: .BLKW 2 ; TOTAL BATCH CPU TIME TOTEXE: .BLKW 2 ; TOTAL EXECUTIVE CPU TIME TOTIDL: .BLKW 2 ; TOTAL IDLE CPU TIME TIMDIV: .BLKW 2 ; TOTAL TIME DIVIDED BY 1000. .IF DF AA$LDR TOTLDR: .BLKW 2 ; TOTAL LOADER REQUESTS .ENDC ; DF AA$LDR .IF DF AA$QIO TOTQIO: .BLKW 2 ; TOTAL I/O REQUSETS .ENDC ; DF AA$QIO .IF DF AA$CSW TOTCSW: .BLKW 2 ; TOTAL CONTEXT SWITCHES .ENDC ; DF AA$CSW TABEND: ; END OF TABLES TABSIZ=<<.-TABSTT>/4> ; LENGTH OF TABLES IN DOUBLE-WORDS TIMAVL: .BLKW 2 ; TOTAL TIME AVAILABILITY TIM1: .BLKW 8. ; TIME BUFFER FOR START OF PERIOD TIM2: ; TIME BUFFER FOR END OF PERIOD ; (SHARES STORAGE WITH STABUF) STABUF: .BLKB S.LSTA ; INPUT BUFFER PCNFLG: .BYTE 0 ; FORMAT PERCENTAGE, 0=NO, 1=YES .EVEN PLTADR: .BLKW 1 ; ADDRESS OF PLOT BUFFER ; ; DATA FOR TOTAL ELAPSED TIME CALCULATION ; NOLEAP: .WORD 0.,31.,59.,90.,120.,151.,181.,212.,243.,273.,304.,334. LEAP: .WORD 0.,31.,60.,91.,121.,152.,182.,213.,244.,274.,305.,335. .IFTF .EVEN $LOAEP:: ; .IFF PRINT #ERR1 ; FEATURE NOT SUPPORTED DELET$ #OUTFDB ; DELETE OUTPUT FILE .IFT ; ; ZERO THE STATISTICS TABLES ; MOV #TABSTT,R0 ; GET START ADDRESS OF TABLES MOV #TABSIZ,R1 ; AND SIZE IN DOUBLE-WORDS 5$: CLR (R0)+ ; CLEAR A DOUBLE-WORD CLR (R0)+ ; DEC R1 ; DONE? BGT 5$ ; IF GT NO, LOOP ; ; INITIALISE PLOT BUFFER ; BIT #PLMSK,MASKW ; /PL SWITCH SPECIFIED? BEQ 6$ ; IF EQ NO CALL INIPLT ; INITIALISE PLOT BUFFER 6$: ; REF. LABEL ; ; OPEN DATA FILE FOR SHARED READ ; OPNS$R #$SFFDB ; OPEN THE INPUT FILE BCC 10$ ; IF CC GOOD PRINT #ERR2 ; OPEN FAILURE CALL $FCSEP ; GIVE RROR DETAILS JMP EXSEV ; EXIT WITH SEVERE ERROR 10$: ; REF. LABEL ; ; NOW READ IN THE DATA FROM THE FIRST RECORD. THIS MARKS THE START OF THE ; CURRENT LOAD PERIOD. ; CLR NRECT ; CLEAR RECORD COUNTERS CLR NRECC ; CALL INPUT ; READ IN THE FIRST RECORD BCS 30$ ; IF CS ERROR MOV #FROM1,R0 ; GET BUFFER ADDRESS FOR DATE/TIME MOV #STABUF+S.TIME,R1 ; SET ADDRESS OF BINARY DATE/TIME BUFFER CALL DATTIM ; FILL IN ASCII DATE/TIME MOV #TIM1,R0 ; COPY DATE/TIME PORTION TO "TIM1" MOV #STABUF+S.TIME,R1 ; MOV #8.,R2 ; CALL CO.PYW ; BR 40$ ; ANALYSE THE DATA ; ; LOOP OVER REST OF DATA RECORDS ; 20$: CALL INPUT ; READ MORE INPUT DATA BCC 40$ ; IF CC, OK 30$: CMPB $SFFDB+F.ERR,#IE.EOF ; END OF FILE REACHED? BNE 32$ ; IF NE NO JMP 70$ ; YES 32$: PRINT #ERR4 ; ELSE SHOW AN ERROR MESSAGE MOV #$SFFDB,R0 ; SET FDB ADDRESS CALL $FCSEP ; AND GIVE THE ERROR DETAILS JMP EXSEV ; AND EXIT WITH SEVERE ERROR 40$: CMP $SFFDB+F.NRBD,#S.LSTA ; RECORD THE RIGHT LENGTH? BEQ 50$ ; IF EQ YES MOV #ERR5,R4 ; GET ERROR MESSAGE ADDRESS MOV #ERR5A,R0 ; GET PLACE FOR ASCII RECORD NUMBER 45$: MOV NRECT,R1 ; GET RECORD NUMBER CALL DE.CML ; CONVERT TO ASCII DECIMAL SUB R4,R0 ; CALCULATE MESSAGE LENGTH PRINT R4,R0 ; PRINT ERROR MESSAGE BR 20$ ; GET MORE DATA 47$: MOV #ERR6,R4 ; ILLEGAL FORMAT ERROR MESSAGE ADDRESS MOV #ERR6A,R0 ; BR 45$ ; 50$: MOV #STABUF,R3 ; GET DATA BUFFER ADDRESS MOV S.TIME+G.TIHR(R3),R0 ; GET HOUR OF RECORDING BLT 47$ ; IF LT IT'S NONSENSE CMP R0,#24. ; HOUR TOO BIG? BGE 47$ ; IF GE YES MOV #60.,R1 ; SET HOURS TO MINUTES CONVERSION FACTOR CALL $MUL ; CONVERT HOURS TO MINUTES MOV S.TIME+G.TIMI(R3),R0 ; GET MINUTE OF RECORDING BLT 47$ ; IF LT IT'S NONSENSE CMP R0,#60. ; MINUTE TOO BIG? BGE 47$ ; IF GE YES ADD R1,R0 ; GET TIME OF DAY IN MINUTES PAST MIDNIGHT MOV #12.,R1 ; DIVIDE INTO TWELVE MINUTE INTERVALS CALL $DIV ; TST R0 ; INTERVAL NUMBER ZERO? BNE 52$ ; IF NE NO MOV #120.,R0 ; YES, MAKE IT THE LAST INTERVAL 52$: DEC R0 ; CONVERT TO TABLE INDEX ASL R0 ; (EACH ENTRY IS 4 BYTES LONG) ASL R0 ; INC NRECC ; COUNT ANOTHER RECORD ADD S.ELAP+2(R3),TOTTIM+2 ; UPDATE TOTAL ELAPSED TIME ADC TOTTIM ; ADD S.ELAP(R3),TOTTIM ; ADD S.ELAP+2(R3),CPUTOT+2(R0) ; UPDATE TOTAL TIME TABLE ENTRY ADC CPUTOT(R0) ; ADD S.ELAP(R3),CPUTOT(R0) ; ADD S.EXEC+2(R3),TOTEXE+2 ; UPDATE TOTAL EXEC TIME ADC TOTEXE ; ADD S.EXEC(R3),TOTEXE ; ADD S.EXEC+2(R3),CPUEXE+2(R0) ; UPDATE TOTAL TIME TABLE ENTRY ADC CPUEXE(R0) ; ADD S.EXEC(R3),CPUEXE(R0) ; ADD S.NULL+2(R3),TOTIDL+2 ; UPDATE TOTAL NULL TIME ADC TOTIDL ; ADD S.NULL(R3),TOTIDL ; ADD S.NULL+2(R3),CPUIDL+2(R0) ; UPDATE IDLE TIME TABLE ENTRY ADC CPUIDL(R0) ; ADD S.NULL(R3),CPUIDL(R0) ; .IF DF AA$LDR ADD S.LOAD+2(R3),TOTLDR+2 ; UPDATE TOTAL LOADER REQUESTS ADC TOTLDR ; ADD S.LOAD(R3),TOTLDR ; ADD S.LOAD+2(R3),LOADER+2(R0) ; UPDATE LOADER TABLE ENTRIES ADC LOADER(R0) ; ADD S.LOAD(R3),LOADER(R0) ; .ENDC ; DF AA$LDR .IF DF AA$QIO ADD S.TQIO+2(R3),TOTQIO+2 ; UPDATE TOTAL I/O REQUESTS ADC TOTQIO ; ADD S.TQIO(R3),TOTQIO ; ADD S.TQIO+2(R3),QIOREQ+2(R0) ; UPDATE I/O TABLE ENTRIES ADC QIOREQ(R0) ; ADD S.TQIO(R3),QIOREQ(R0) ; .ENDC ; DF AA$QIO .IF DF AA$CSW ADD S.CSWT+2(R3),TOTCSW+2 ; UPDATE TOTAL CONTEXT SWITCHES ADC TOTCSW ; ADD S.CSWT(R3),TOTCSW ; ADD S.CSWT+2(R3),CONSWT+2(R0) ; UPDATE CONTEXT SWITCH TABLE ENTRIES ADC CONSWT(R0) ; ADD S.CSWT(R3),CONSWT(R0) ; .ENDC ; DF AA$CSW ADD S.USER+2(R3),TOTUSR+2 ; UPDATE TOTAL USER TIME ADC TOTUSR ; ADD S.USER(R3),TOTUSR ; ADD S.USER+2(R3),CPUUSR+2(R0) ; UPDATE USER TIME TABLE ENTRIES ADC CPUUSR(R0) ; ADD S.USER(R3),CPUUSR(R0) ; .IF DF AA$BAT ADD S.BCPU+2(R3),TOTBAT+2 ; UPDATE TOTAL BATCH CPU ADC TOTBAT ; ADD S.BCPU(R3),TOTBAT ; ADD S.BCPU+2(R3),CPUBAT+2(R0) ; UPDATE BATCH CPU TABLE ENTRIES ADC CPUBAT(R0) ; ADD S.BCPU(R3),CPUBAT(R0) ; .ENDC ; DF AA$BAT JMP 20$ ; GET MORE INPUT 70$: CALL $SFCLS ; MAKE SURE DATA FILE IS CLOSED TSTB TTYFLG ; OUTPUT DEVICE A TERMINAL? BEQ 72$ ; IF EQ NO DIR$ #TIATT ; YES, ATTACH IT 72$: ; REF. LABEL ; ; HAVING COME TO THE END OF THE DATA FILE, WE USE THE DATE AND TIME ; CONTAINED IN THE LAST RECORD AS THE END OF THE PERIOD RECORDED IN ; THE FILE. ; MOV #TO1,R0 ; GET BUFFER ADDRESS FOR TIME MOV #STABUF+S.TIME,R1 ; SET ADDRESS OF BINARY DATE/TIME BUFFER CALL DATTIM ; INSERT DATE AND TIME TST NRECC ; ANY RELEVANT DATA READ? BEQ 74$ ; IF EQ NO FILE #FROM,#FROMSZ ; PRINT THE DATES FOR THIS PERIOD FILE #TO,#TOSZ ; 74$: CALL ELAPST ; CALCULATE TOTAL ELAPSED CLOCK TIME ADD STABUF+S.ELAP+2,TIMAVL+2 ; ALLOW FOR EXTRA UPDATE ADC TIMAVL ; ADD STABUF+S.ELAP,TIMAVL ; ; ; PRINT THE TOTAL RECORD COUNT ; MOV #TOTRC1,R0 ; GET ADDRESS FOR TOTAL RECORD # MOV NRECT,R1 ; GET TOTAL RECORD COUNTER CALL DE.CML ; FORMAT AS DECIMAL MOVB #'/,(R0)+ ; INSERT A SLASH MOV NRECC,R1 ; GET COUNTED RECORD COUNTER CALL DE.CML ; FORMAT AS ASCII DECIMAL SUB #TOTREC,R0 ; CALCULATE MESSAGE LENGTH FILE #TOTREC,R0 ; WRITE TO OUTPUT FILE ; ; PRINT THE DYNAMIC MEMORY USAGE STATISTICS ; MOV #TOTDY1,R0 ; GET ADDRESS FOR DYNAMIC MEMORY DATA MOV INISIZ,R1 ; GET INITIAL SIZE OF DYNAMIC MEMORY CALL DE.CML ; FORMAT AS ASCII DECIMAL MOVB #'/,(R0)+ ; INSERT A SLASH CALL FRESIZ ; SIZE CURRENT FREE DYNAMIC MEMORY NEG R1 ; COMPUTE AMOUNT USED ADD INISIZ,R1 ; CALL DE.CML ; FORMAT AS ASCII DECIMAL SUB #TOTDYN,R0 ; CALCULATE MESSAGE LENGTH FILE #TOTDYN,R0 ; AND WRITE IT OUT TST NRECC ; DID WE GET ANY DATA? BNE 80$ ; IF NE YES PRINT #ERR7 ; GIVE USER A WARNING MESSAGE JMP EXSUC ; NO, JUST EXIT 80$: ; REF. LABEL ; ; PRINT TOTALS OF TIME RECORDED SO FAR ; CLRB PCNFLG ; DON'T PRINT PERCENTAGE FOR TOTAL TIME MOV #MSTOT1,R0 ; SET MESSAGE PARAMETERS (TOTAL ELAPSED TIME) MOV #MSTOT,R5 ; MOV #TIMAVL,R1 ; CALL OUTTIM ; MOV #MSELP1,R0 ; SET MESSAGE PARAMETERS (TOTAL UPTIME) MOV #MSELP,R5 ; MOV #TOTTIM,R1 ; CALL OUTTIM ; FORMAT AND PRINT THE OUTPUT MOV TIMAVL,R1 ; COMPUTE (AVAILABLE TIME/1000.) FOR % CALCN. MOV TIMAVL+2,R2 ; MOV #1000.,R0 ; CALL $DDIV ; MOV R1,TIMAVL ; OVERWRITE ORIGINAL TIME WITH RESULT MOV R2,TIMAVL+2 ; MOV TOTTIM,R1 ; COMPUTE (TOTAL TIME/1000.) FOR % CALCN. MOV TOTTIM+2,R2 ; MOV #1000.,R0 ; CALL $DDIV ; MOV R1,TIMDIV ; SAVE THE RESULT MOV R2,TIMDIV+2 ; BIS R1,R2 ; WAS IT ZERO (TIME TO SMALL)? BEQ 82$ ; IF EQ YES, DON'T REPORT ANY PERCENTAGES INCB PCNFLG ; PRINT PERCENTAGE FOR FOLLOWING DATA 82$: ; MOV #MSEXE1,R0 ; SET MESSAGE PARAMETERS (TOTAL EXECUTIVE TIME) MOV #MSEXE,R5 ; MOV #TOTEXE,R1 ; CALL OUTTIM ; FORMAT AND PRINT THE OUTPUT MOV #MSIDL1,R0 ; SET MESSAGE PARAMETERS (TOTAL NULL TIME) MOV #MSIDL,R5 ; MOV #TOTIDL,R1 ; CALL OUTTIM ; FORMAT AND PRINT THE OUTPUT MOV #MSUSR1,R0 ; SET MESSAGE PARAMETERS (TOTAL USER TIME) MOV #MSUSR,R5 ; MOV #TOTUSR,R1 ; CALL OUTTIM ; FORMAT AND PRINT THE OUTPUT MOV #MSBAT1,R0 ; SET MESSAGE PARAMETERS (TOTAL BATCH TIME) MOV #MSBAT,R5 ; MOV #TOTBAT,R1 ; CALL OUTTIM ; FORMAT AND PRINT THE OUTPUT MOV #MSAVL1,R0 ; GET BUFFER ADDRESS FOR SYSTEM AVAILABILITY MOV TIMAVL,TIMDIV ; FAKE TOTAL TIME MOV TIMAVL+2,TIMDIV+2 ; MOV #TOTTIM,R1 ; POINT TO TOTAL TIME CALL PERCNT ; CALCULATE AND FORMAT PERCENTAGE MOVB #SPA,(R0)+ ; INSERT " **" MOVB #'*,(R0) ; MOVB (R0)+,(R0)+ ; SUB #MSAVL,R0 ; CALCULATE MESSAGE LENGTH FILE #MSAVL,R0 ; AND WRITE TO OUTPUT FILE ; ; LOOP OVER DATA TABLES AND CALCULATE THE PERCENTAGES. THESE ARE REPRESENTED IN ; THE PLOT BY LETTERS, EG "U" FOR USER PERCENTAGE, "N" FOR NULL (IDLE) PERCEN- ; TAGE, AND SO ON. VERTICAL OFFSET FOR PLOT = PERCENTAGE/2 = 50*TIME/TOTAL. ; 90$: BIT #PLMSK,MASKW ; /PL SWITCH? BNE 92$ ; IF NE YES JMP EXSUC ; ELSE JUST EXIT 92$: MOV #TIMINT,R5 ; SET NUMBER OF TABLE ENTRIES CLR R4 ; SET INITIAL TABLE OFFSET 100$: MOV CPUTOT(R4),R1 ; COMPUTE (TOTAL TIME)/50. FOR % CALCN. MOV CPUTOT+2(R4),R2 ; MOV #50.,R0 ; CALL $DDIV ; MOV R1,CPUTOT(R4) ; SAVE THE RESULT MOV R2,CPUTOT+2(R4) ; BIS R1,R2 ; WAS IT ZERO (TIME TO SMALL)? BEQ 120$ ; IF EQ YES, DON'T PLOT ANYTHING MOVB #'u,R3 ; SET SYMBOL FOR USER TIME PLOT MOV #CPUUSR,R1 ; SET ADDRESS OF USER TIME PLOT CALL SYMPLT ; PLOT USER TIME SYMBOL .IF DF AA$BAT MOVB #'b,R3 ; REPEAT FOR BATCH CPU TIME MOV #CPUBAT,R1 ; CALL SYMPLT ; .ENDC ; DF AA$BAT MOVB #'e,R3 ; REPEAT FOR EXECUTIVE TIME MOV #CPUEXE,R1 ; CALL SYMPLT ; MOVB #'n,R3 ; REPEAT FOR NULL TIME MOV #CPUIDL,R1 ; CALL SYMPLT ; 120$: ADD #4,R4 ; POINT TO NEXT OFFSET DEC R5 ; ANY TABLE ENTRIES LEFT? BGT 100$ ; IF GT YES, LOOP ; ; PRODUCE THE FINAL PLOT ; FILE #FROM,#FROMSZ ; START A NEW PAGE AND WRITE TITLE FILE #TO,#TOSZ ; MOV #1000.,LINES ; SET A LARGE PAGE SIZE MOV #>,R5 ; SET INITIAL OFFSET MOV #HEIGHT,R4 ; AND LINE COUNTER ADD PLTADR,R5 ; SET ADDRESS WITHIN TABLE 160$: PUT$ #OUTFDB,R5,#WIDTH ; DO PUT$ DIRECTLY TO OUTPUT FILE SUB #WIDTH,R5 ; CALCULATE ADDRESS OF NEXT LINE DEC R4 ; ANY MORE LINES TO PRINT? BGT 160$ ; IF GT YES, LOOP BR EXSUC ; EXSEV: DELET$ #OUTFDB ; DELETE OUTPUT FILE MOV #EX$SEV,-(SP) ; PUSH SEVERE ERROR EXIT STATUS BR EXSTAT ; EXSUC: BIT #SPMSK,MASKW ; SPOOL OUTPUT FILE? BEQ 390$ ; IF EQ NO PRINT$ #OUTFDB ; YES, PRINT IT BR 392$ ; 390$: CLOSE$ #OUTFDB ; CLOSE OUTPUT FILE .IFTF 392$: MOV #EX$SUC,-(SP) ; PUSH SUCCESS EXIT STATUS EXSTAT: CALL $SFCLS ; CLOSE DATA FILE (IF OPEN) EXST$S (SP)+ ; EXIT WITH RIGHT STATUS EXIT$S ; JUST IN CASE .IFT ;+ ; *** INIPLT ; ; THIS ROUTINE IS CALLED TO INITIALISE THE ASCII PLOT BUFFER THAT ; IS ALLOCATED FROM DYNAMIC MEMORY. THE BUFFER IS FILLED WITH ; SPACES AND THE AXES ARE INITIALISED. ; ;- INIPLT: MOV #FREEHD,R0 ; GET FREE DYNAMIC MEMORY LISTHEAD MOV #,R1 ; SET SIZE OF BUFFER REQUIRED CALL $RQCB ; REQUEST A CORE BLOCK BCC 10$ ; IF CC GOOD PRINT #ERR3 ; COULD NOT ALLOCATE BUFFER JMP EXSEV ; EXIT WITH SEVERE ERROR 10$: MOV R0,PLTADR ; SAVE ADDRESS OF BUFFER ASR R1 ; CONVERT SIZE TO WORDS 20$: MOV #20040,(R0)+ ; BLANK OUT 2 BYTES DEC R1 ; DONE YET? BGT 20$ ; IF GT NO, LOOP ; ; INITIALISE TOP AND BOTTOM BOX EDGES ; MOV #121.,R2 ; SET COUNTER MOV #<<*WIDTH>+5>,R0 ; INITIALISE TOP EDGE OFFSET MOV #<<2*WIDTH>+5>,R1 ; INITIALISE BOTTOM EDGE OFFSET ADD PLTADR,R0 ; CALCULATE ADDRESSES WITHIN TABLE ADD PLTADR,R1 ; 30$: MOVB #'-,(R0) ; PUT A HYPHEN IN BOTH POSITIONS MOVB (R0)+,(R1)+ ; DEC R2 ; ALL DONE? BGT 30$ ; IF GT NO ; ; LABEL X AXIS ; MOV PLTADR,R0 ; SET ADDRESS FOR X-AXIS TITLE MOVSTR #XAXIS1 ; MOVE IN THE TITLE MOV #/2>>,R0 ; SET X-TITLE LEFT EDGE OFFSET ADD PLTADR,R0 ; CALC. ADDRESS OF X-TITLE MOVSTR #XAXIS0 ; MOVE IT IN ; ; INITIALISE LEFT AND RIGHT EDGES ; MOV #51.,R2 ; SET COUNTER MOV #<<2*WIDTH>+6>,R0 ; INITIALISE LEFT EDGE OFFSET MOV #<<3*WIDTH>-1>,R1 ; INITIALISE RIGHT EDGE OFFSET ADD PLTADR,R0 ; CALCULATE ADDRESSES WITHIN TABLE ADD PLTADR,R1 ; 40$: MOVB #'!,(R0) ; PUT AN EXCLAMATION MARK IN BOTH PLACES MOVB (R0),(R1) ; ADD #WIDTH,R0 ; POINT TO NEXT POSITION ADD #WIDTH,R1 ; DEC R2 ; DONE YET? BGT 40$ ; IF GT NO, LOOP ; ; LABEL Y AXIS ; MOV #<<52.*WIDTH>+2>,R0 ; INSERT 100% MARKER ADD PLTADR,R0 ; MOVAX #YAXIS1 ; MOV #<<42.*WIDTH>+2>,R0 ; INSERT 80% MARKER ADD PLTADR,R0 ; MOVAX #YAXIS2 ; MOV #<<32.*WIDTH>+2>,R0 ; INSERT 60% MARKER ADD PLTADR,R0 ; MOVAX #YAXIS3 ; MOV #<<22.*WIDTH>+2>,R0 ; INSERT 40% MARKER ADD PLTADR,R0 ; MOVAX #YAXIS4 ; MOV #<<12.*WIDTH>+2>,R0 ; INSERT 20% MARKER ADD PLTADR,R0 ; MOVAX #YAXIS5 ; MOV #<<2.*WIDTH>+2>,R0 ; INSERT 0% MARKER ADD PLTADR,R0 ; MOVAX #YAXIS6 ; MOV #</2>,R0 ; SET VERTICAL OFFSET FOR Y-TITLE MOV #WIDTH,R1 ; SET UP TO CALCULATE PLOT BUFFER OFFSET CALL $MUL ; ADD PLTADR,R1 ; CALCULATE ADDRESS OF FIRST CHAR. IN TITLE MOV #YAXIS0,R0 ; GET ADDRESS OF Y-AXIS TITLE 50$: MOVB (R0)+,R2 ; GET NEXT CHARACTER IN TITLE BEQ 60$ ; IF EQ END OF TITLE MOVB R2,(R1) ; INSERT IN PLOT BUFFER ADD #WIDTH,R1 ; POINT TO NEXT POSITION BR 50$ ; LOOP 60$: RETURN ; RETURN TO CALLER ;+ ; *** INPUT ; ; THIS ROUTINE READS A LINE FROM THE INPUT FILE AND APPLIES THE ; /DA, /BE AND /AF SWITCHES IF NECESSARY. RECORDS ARE READ ; UNTIL ONE IS FOUND THAT MATCHES THE SPECIFIES DATE AND/OR UIC ; COMBINATION, OR UNTIL THE END OF FILE IS REACHED. ; ;- INPUT: CALL $SFGET ; READ A LINE OF INPUT BCS 40$ ; IF CS AN ERROR OCCURRED INC NRECT ; SHOW ONE MORE RECORD READ MOV #$SFREC,R3 ; SET UP RECORD POINTER BIT #,MASKW ; ANY DATE SWITCHES? BEQ 30$ ; IF EQ NO, RETURN WITH THIS LINE ; ; PROCESS /DA SWITCH ; BIT #DAMSK,MASKW ; /DA SWITCH SPECIFIED? BEQ 10$ ; IF EQ NO CMP DADAY,S.TIME+G.TIDA(R3) ; RIGHT DAY? BNE INPUT ; IF NE NO, GO FOR ANOTHER ONE CMP DAMON,S.TIME+G.TIMO(R3) ; RIGHT MONTH? BNE INPUT ; IF NE NO CMP DAYR,S.TIME+G.TIYR(R3) ; RIGHT YEAR? BNE INPUT ; IF NE NO BR 30$ ; DATE CHECKS OUT, RETURN ; ; PROCESS /BE SWITCH ; 10$: BIT #BEMSK,MASKW ; /BE SWITCH SPECIFIED? BEQ 20$ ; IF EQ NO CMP BEYR,S.TIME+G.TIYR(R3) ; TRANSACTION <= SPECIFIED YEAR? BLT INPUT ; IF NE NO CMP BEMON,S.TIME+G.TIMO(R3) ; TRANSACTION <= SPECIFIED MONTH? BLT INPUT ; IF NE NO CMP BEDAY,S.TIME+G.TIDA(R3) ; TRANSACTION <= SPECIFIED DAY? BLT INPUT ; IF NE NO ; ; PROCESS /AF SWITCH ; 20$: BIT #AFMSK,MASKW ; /AF SWITCH SPECIFIED? BEQ 30$ ; IF EQ NO CMP AFYR,S.TIME+G.TIYR(R3) ; TRANSACTION >= SPECIFIED YEAR? BGT INPUT ; IF GT NO CMP AFMON,S.TIME+G.TIMO(R3) ; TRANSACTION >= SPECIFIED MONTH? BGT INPUT ; IF GT NO CMP AFDAY,S.TIME+G.TIDA(R3) ; TRANSACTION >= SPECIFIED DAY? BGT INPUT ; IF GT NO 30$: MOV $SFFDB+F.NRBD,R2 ; GET RECORD LENGTH IN BYTES BEQ 40$ ; IF EQ NOTHING WAS READ ASR R2 ; CONVERT TO WORDS MOV #STABUF,R0 ; GET ADDRESS OF BUFFER COPY MOV R3,R1 ; SET ADDRESS OF INPUT BUFFER CALL CO.PYW ; TRANSFER TO LOCAL BUFFER CLC ; OK 40$: RETURN ; RETURN TO CALLER ;+ ; *** DATTIM ; ; THIS ROUTINE IS CALLED TO FORMAT THE DATE AND TIME AS OBTAINED ; FROM A DATA RECORD. FORMAT IS DD-MMM-YY HH:MM:SS. ; ; INPUTS: ; R0 ADDRESS OF OUTPUT BUFFER ; R1 ADDRESS OF BUFFER CONTAINING DATE TIME IN ; STANDARD GTIM$ FORMAT. ; ;- DATTIM: CMP G.TIDA(R1),#10. ; DAY LESS THAN 10.? BGE 10$ ; IF GE NO MOVB #'0,(R0)+ ; YES, INSERT A ZERO CHARACTER 10$: CALL $DAT ; FILL IN THE DATE MOVB #SPA,(R0)+ ; INSERT A SPACE MOV #3,R2 ; SET TIME FORMAT TO HH:MM:SS JMP $TIM ; FILL IN THE TIME AND RETURN TO CALLER ;+ ; *** OUTTIM ; ; THIS ROUTINE FORMATS AND PRINTS A MESSAGE FOR THE TOTAL AMOUNT ; OF TIME USED OVER THE CURRENT STATISTICS PERIOD. THE PERCENTAGE ; OF THE TOTAL TIME IS INCLUDED AS WELL. ; ; INPUTS: ; R0 BUFFER ADDRESS FOR ASCII TIME ; R1 ADDRESS OF 2-WORD TIME FIELD ; R5 ADDRESS OF START OF MESSAGE TEXT ; ;- OUTTIM: MOV R1,-(SP) ; SAVE NUMBER ADDRESS MOV #20.,R2 ; SET FIELD WIDTH MOV #FM.CPU,R3 ; SET ADDRESS OF CONVERSION ROUTINE CALL FM.FFW ; PERFORM PADDED CONVERSION MOV (SP)+,R1 ; RESTORE NUMBER ADDRESS TSTB PCNFLG ; PERCENTAGE REQUIRED? BEQ 10$ ; IF EQ NO MOV #15.,R2 ; SET FIELD WIDTH MOV #PERCNT,R3 ; SET ADDRESS OF CONVERSION ROUTINE CALL FM.FFW ; FORMAT AS A PERCENTAGE 10$: SUB R5,R0 ; CALCULATE MESSAGE LENGTH FILE R5,R0 ; WRITE RESULT TO OUTPUT FILE RETURN ; AND RETURN TO CALLER ;+ ; *** ELAPST ; ; THIS ROUTINE CALCULATES THE TOTAL CLOCK TIME THAT HAS ELAPSED ; SINCE THE BEGINNING OF THE CURRENT RUN AND THE END OF THE ; CURRENT RUN. THIS FIGURE IS USED TO DETERMINE MACHINE ; AVAILABILITY. ; ; INPUT: ; TIM1 8-WORD TIME FIELD, START OF PERIOD ; TIM2 8-WORD TIME FIELD, END OF PERIOD ; ; OUTPUT: ; TIMAVL 2-WORD FIELD CONTAINING ELAPSED TIME (TICKS) ; ;- ELAPST: CLR TIMAVL ; ZERO TOTAL ELAPSED TIME FIELD CLR TIMAVL+2 ; MOV TIM2+G.TIYR,R1 ; GET ENDING YEAR CALL GETYR ; CALCULATE DAYS SINCE 1960 MOV R2,TIMAVL+2 ; SAVE RESULT MOV TIM1+G.TIYR,R1 ; GET STARTING YEAR CALL GETYR ; CALCULATE DAYS SINCE 1960 SUB R2,TIMAVL+2 ; SUBTRACT FROM TOTAL MOV TIM2+G.TIMO,R1 ; GET ENDING MONTH MOV TIM2+G.TIYR,R2 ; AND YEAR CALL GETMON ; CALC. DAYS SINCE START OF YEAR ADD R2,TIMAVL+2 ; ADD IN TO TOTAL MOV TIM1+G.TIMO,R1 ; GET STARTING MONTH MOV TIM1+G.TIYR,R2 ; AND YEAR CALL GETMON ; CALC. DAYS SINCE START OF YEAR SUB R2,TIMAVL+2 ; ADD TIM2+G.TIDA,TIMAVL+2 ; ALLOW FOR DAYS DIFFERENCE SUB TIM1+G.TIDA,TIMAVL+2 ; MOV TIMAVL+2,R0 ; MULTIPLE BY 24 TO GET HOURS MOV #24.,R1 ; CALL $MUL ; ADD TIM2+G.TIHR,R1 ; ADD IN HOURS ADC R0 ; SUB TIM1+G.TIHR,R1 ; SBC R0 ; MOV R1,R3 ; SHIFT FOR $DMUL MOV R0,R2 ; MOV #60.,R0 ; MULTIPLY BY 60 TO GET MINUTES CALL $DMUL ; ADD TIM2+G.TIMI,R1 ; ADD IN MINUTES ADC R0 ; SUB TIM1+G.TIMI,R1 ; ADC R0 ; MOV R1,R3 ; SHIFT FOR $DMUL MOV R0,R2 ; MOV #60.,R0 ; MULTIPLY BY 60. TO GET SECONDS CALL $DMUL ; ADD TIM2+G.TISC,R1 ; ADD IN SECONDS ADC R0 ; SUB TIM1+G.TISC,R1 ; SBC R0 ; MOV R1,R3 ; SHIFT FOR $DMUL MOV R0,R2 ; MOV TIM1+G.TICP,R0 ; MULTIPLY BY TICKS PER SECOND CALL $DMUL ; ADD TIM2+G.TICT,R1 ; ADD IN TICKS ADC R0 ; SUB TIM1+G.TICT,R1 ; SBC R0 ; MOV R0,TIMAVL ; SAVE THE RESULT MOV R1,TIMAVL+2 ; RETURN ; SIMPLE SIN'T IT ;+ ; GETYR -- CALCULATE DAYS (WHOLE YEARS) SINCE 1960 ;- GETYR: SUB #61.,R1 ; YEARS SINCE 1960 (SKIP CURRENT YEAR ALSO) MOV R1,R2 ; COPY TO R2 ASR R2 ; DIVIDE BY 4 TO GET # LEAP YEARS ASR R2 ; MOV #365.,R0 ; SET # DAYS PER YEAR CALL $MUL ; CONVERT TO DAYS ADD R1,R2 ; GET FINAL RESULT IN DAYS RETURN ; ;+ ; GETMON -- CALCULATE DAYS (WHOLE MONTHS) SINCE START OF YEAR ;- GETMON: MOV #NOLEAP-2,R0 ; ASSUME IT WASN'T A LEAP YEAR BIT #3,R2 ; WAS IT A LEAP YEAR? BNE 20$ ; IF NE NO MOV #LEAP-2,R0 ; YES IT WAS 20$: ASL R1 ; INDEX INTO TABLE ADD R1,R0 ; MOV (R0),R2 ; GET RESULT RETURN ; AND RETURN ;+ ; *** PERCNT ; ; THIS ROUTINE FORMATS A PERCENTAGE FOR CPU TIME USE. WE GET ; THE PERCENTAGE*10 ON PERFORMING A DIVIDE. IF THE RESULT AND ; THE REMAINDER FROM THE DIVISION ARE BOTH MULTIPLIED BY TEN, ; PERFORMING ANOTHER DIVISION WILL LEAD TO ANOTHER DECIMAL PLACE ; IN THE FINAL RESULT. THE TOTAL TIME DIVIDED BY 1000. IS ALREADY ; COMPUTED. ; ; INPUTS: ; R0 BUFFER POINTER ; R1 ADDRESS OF 2-WORD TIME FIELD ; TIMDIV (TOTAL TIME)/1000. ; ; OUTPUTS: ; R0 UPDATED ; R1,R2,R5 PRESERVED ; ;- PERCNT: MOV R0,-(SP) ; SAVE R0 MOV 2(R1),R2 ; GET LOW ORDER NUMBER MOV (R1),R1 ; GET HIGH ORDER NUMBER MOV TIMDIV,-(SP) ; PUT HIGH ORDER DIVISOR ON STACK MOV TIMDIV+2,R0 ; AND LOW ORDER IN R0 10$: TST (SP) ; HIGH ORDER DIVISOR ZERO? BNE 20$ ; IF NE NO, CONTINUE TO SHIFT TST R0 ; LOW ORDER DIVISOR STILL SIGNED? BPL 30$ ; IF PL NO 20$: ASR R1 ; DIVIDE DIVIDEND BY 2 ROR R2 ; ASR (SP) ; DIVIDE DIVISOR BY 2 ROR R0 ; BR 10$ ; LOOP 30$: TST (SP)+ ; CLEAN THE STACK MOV R0,-(SP) ; SAVE CURRENT DIVISOR CALL $DDIV ; DO D.P. BY S.P DIVIDE (HIGH ORDER RESULT ; IS ALWAYS ZERO) MOV R0,-(SP) ; SAVE THE REMAINDER ASL R2 ; MULTIPLY RESULT BY 2 MOV R2,-(SP) ; SAVE THE ANSWER (PERCENTAGE*10.) ASL R2 ; *4. ASL R2 ; *8. ADD (SP)+,R2 ; *10. (PERCENTAGE*100.) MOV R2,R4 ; AND SAVE IT IN R4 MOV (SP)+,R0 ; RESTORE THE REMAINDER MOV #10.,R1 ; SET UP TO MULTIPLY BY TEN CALL $MUL ; AND DO IT MOV R1,R2 ; SHIFT RESULTS FOR $DDIV MOV R0,R1 ; MOV (SP)+,R0 ; RESTORE THE DIVISOR CALL $DDIV ; PERFORM THE DIVISION (THE HIGH ORDER RESULT ; WILL ALWAYS BE ZERO) ADD R4,R2 ; COMPUTE FINAL PERCENTAGE*100. MOV R2,R1 ; AND TRANSFER TO R1 MOV (SP)+,R0 ; RESTORE R0 (BUFFER POINTER) CMP R1,#100. ; LESS THAN 1.00 PERCENT? BGE 40$ ; IF GE NO MOVB #'0,(R0)+ ; YES, ADD A SINGLE LEADING ZERO CMP R1,#10. ; LESS THAN 0.10 PERCENT? BGE 40$ ; IF GE NO MOVB #'0,(R0)+ ; YES, PUT IN ANOTHER DIGIT 40$: CALL DE.CML ; FORMAT PERCENTAGE MOVB -(R0),1(R0) ; MOVE OVER LAST DIGIT MOVB -(R0),1(R0) ; AND LAST BUT ONE MOVB #DPT,(R0)+ ; PUT IN DECIMAL POINT ADD #2,R0 ; STEP PAST LAST DIGIT MOVB #'%,(R0)+ ; PUT IN "%" RETURN ; ;+ ; *** SYMPLT ; ; THIS ROUTINE CALCULATES THE POSITION OF A POINT ON THE LOAD PLOT ; AND MAKES AN ENTRY IN THE TABLE. ; ; INPUTS: ; R1 RELEVANT TIME TABLE BASE ADDRESS ; R3 PLOTTING SYMBOL IN LOW BYTE ; R4 TABLE OFFSET ; R5 NUMBER OF ENTRIES LEFT ; ;- SYMPLT: ADD R4,R1 ; SET ADDRESS OF DIVIDEND MOV R4,R0 ; SET ADDRESS OF DIVISOR ADD #CPUTOT,R0 ; CALL DP.DIV ; CALCULATE VERTICAL OFFSET MOV R2,R1 ; CALCULATE TABLE LOCATION ADDRESS ADD #2,R1 ; MOV #WIDTH,R0 ; CALL $MUL ; ADD #WIDTH,R1 ; SUB R5,R1 ; ADD PLTADR,R1 ; MOVB R3,(R1) ; RETURN ; .ENDC ; DF AA$USE & AA$STA .END