.TITLE POOL .IDENT /X01.6/ ; ; COPYRIGHT (C) 1978 ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A ; SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH THE ; INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE, OR ; ANY OTHER COPIES THEREOF, MAY NOT BE PROVIDED OR OTHERWISE ; MADE AVAILABLE TO ANY OTHER PERSON EXCEPT FOR USE ON SUCH ; SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE TERMS. TITLE ; TO AND OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES REMAIN ; IN DEC. ; ; THE INFORMATION IN THIS DOCUMENT IS SUBJECT TO CHANGE WITHOUT ; NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL ; EQUIPMENT CORPORATION. ; ; DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ; ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC. ; ; VERSION: 01 ; BY: DALE R. DONCHIN ; DATE: 03-AUG-78 ; ; MODIFIED: ; J. DOWNWARD JGD 16-AUG-79 POOL TURNS OUT TO BE A CONVENIENT ; PROGRAM TO ALSO LET MONITOR THE STATUS ; OF THE ACT CACHE/45 CACHE MEMORY. ; ; J. DOWNWARD JGD1 09-JUN-80 PRINT OUT A LIST OF ACTIVE TASKS IN ; GEN BEFORE PROMPTING FOR TASKS TO ; ABORT. ; ; ;+ ; ; THIS TASK CHECKS THE AMOUNT OF FREE POOL AND THE SIZE OF ; THE LARGEST FRAGMENT OF POOL EVERY "SECNDS" SECONDS. ; IF EITHER OF THESE SIZES FALL BELOW GIVEN VALUES, A ; WARNING IS SENT TO ALL LOGGED-ON USERS. POOL STATISTICS ; ARE SLSO PRINTED OUT ON THE CONSOLE TERMINAL. ; IF THE SIZE OF THE LARGEST FRAGMENT FALLS BELOW 84. BYTES, A ; TASK NAME IS ACCEPTED VIA THE CONSOLE TERMINAL AND THEN ABORTED. ; ;- ; ;************************************************************* ;****** NOTE THIS TASK USES STSE$S (STOP FOR 1 EFN) ***** ;****** CHANGE THIS TO WTSE$S IF YOUR SYSTEM DOES NOT ***** ;****** HAVE STOP BIT DIRECTIVES ***** ;************************************************************* .MCALL DIR$,QIOW$,GTIM$,MRKT$,STSE$S,WTLO$S,CMKT$S,QIO$ .MCALL DCBDF$,HDRDF$,UCBDF$,ABRT$ .MCALL TCBDF$,PCBDF$ ; JGD1 ; .MCALL EXIT$S ; ***DEBUG*** TCBDF$ ; JGD1 PCBDF$ ; JGD1 DCBDF$ HDRDF$ UCBDF$ CSHERR: .WORD 0 ; FLAG SO ONLY PRINT WARNING MESSAGE 1 TIME. ;CSHCSR=165006 ; STANDARD CSR FOR ACT CACHE/45 ; ; POOL SIZE LIMITS ARE DEFINED HERE ; OR IF COMMENTED OUT SHOULD BE DEFINED BY GLOBAL DEFINITIONS ; AT TASK BUILD TIME ; ;TOTLMT = 500. ; WARN IF FREE POOL FALLS BELOW THIS ;LGELMT = 200. ; WARN IF LARGEST FRAG. FALLS BELOW THIS ; ; LOCAL ASSIGNMENTS ; LUN1 =1 ; USE LUN1 FOR CONSOLE I/O LUN2 =2 ; USE LUN2 FOR USER TERMINAL I/O LUN3 =3 ; USE LUN3 FOR CACHE FAILURE MESSAGE TO CO: EFN1 =1 ; USE EFN1 FOR ALL I/O EFN2 =2 ; USE EFN2 FOR MARK TIME SECNDS =20. ; # SECONDS BETWEEN CHECKS TTISTA =177560 ; CONSOLE TERMINAL INPUT STATUS TTIBUF =177562 ; CONSOLE TERMINAL INPUT BUFFER TTOSTA =177564 ; CONSOLE TERMINAL OUTPUT STATUS TTOBUF =177566 ; CONSOLE OUTPUT BUFFER TSKNAM =ABOTSK+A.BTTN ; TASK NAME TO ABORT CVTPRM =24012 ; CONVERSION PARAMETERS FOR $CBTA ; (RADIX 10., FIELD WITDTH 5) ; ; DATA STRUCTURES ; TIMDPB: MRKT$ EFN2,SECNDS,2 ; DPB FOR MARK TIME TT0DPB: QIOW$ IO.WBT,LUN1,EFN1,,,, ; TTY DPB BRODPB: QIO$ IO.WBT,LUN2,EFN1,,,, ; BROADCAST DPB CSHDPB: QIOW$ IO.WBT,LUN3,EFN1,,,, ; CACHE MEMORY ERROR DPB ABOTSK: ABRT$ ; ABORT TASK DPB FSTIMR: MRKT$ EFN2,10.,2 ; DPB FOR SHORT WAIT MARK TIME DATDPB: GTIM$ DATBUF ; DPB FOR OBTAINING THE CURRENT TIME ; ; LOCAL VARIABLES ; DATBUF: .BLKW 8. ; BUFFER AREA FOR DATE AND TIME SAVER1: .WORD 0 ; SAVE REG 1 HERE WHEN SWITCHING STATES SAVER3: .WORD 0 ; SAVE REG 3 HERE WHEN SWITCHING STATES SAVER4: .WORD 0 ; SAVE REG 4 HERE WHEN SWITCHING STATES TOTSIZ: .WORD 0 ; TOTAL AMOUNT OF FREE POOL LGESIZ: .WORD 0 ; SIZE OF LARGEST POOL FRAGMENT INBUF: .BLKB 10. ; INPUT BUFFER FOR ENTERING TASK NAME ; ; ASCII TEXT ; .NLIST BEX TT0MSG: MSGHED: .BYTE 7,15,12,12 ; BELL, CR,LF,LF DATE: .BLKB 9. .BYTE 40 TIME: .BLKB 8. .BYTE 40 HEDLEN =.-MSGHED .ASCII /-- WARNING -- POOL IS CRITICALLY LOW/<15><12> .ASCII /TOTAL FREE POOL = / FREE: .BLKB 5 .ASCII /. WORDS/<15><12> .ASCII /LARGEST FRAGMENT IS / FRAG: .BLKB 5 .ASCII /. WORDS/<15><12><12> MSGLEN =.-TT0MSG WARN: .BLKB HEDLEN .ASCII /-- POOL IS VERY LOW. / .ASCII /PLEASE EXIT FROM YOUR ACTIVE TASKS./<15><12><12><7> WARNLN= .-WARN CRLF: .BYTE 15,12,0 CSHMSG: .ASCII <5><12><7>/-- WARNING -- CACHE MEMORY IS DISABLED/<7><15><12> CSHLEN =.-CSHMSG ACTMSG: .ASCIZ <15><12>/TASKS ACTIVE IN GEN ARE:/ ; JGD1 BUF: .ASCIZ <15><15>/ ABCDEF/ ; JGD1 ABOMSG: .BYTE 7,15,12,12 .BLKB 9. .BYTE 40 .BLKB 8. .BYTE 40 .ASCII /POOL -- WARNING -- FREE POOL EXHAUSTED/ .ASCIZ <15><12><7>/ENTER A TASK TO ABORT: /<7> INVNAM: .ASCIZ <177><177>/POOL -- INVALID TASKNAME, TRY AGAIN: / NOTABO: .ASCIZ <177><177>/POOL -- TASK NOT ABORTED, TRY AGAIN: / .EVEN .LIST BEX ; ; MAIN CODE ; POOL: TST #CSHCSR ; SEE IF WE ARE TASKBUILT TO MONITOR CACHE BEQ 5$ ; IF EQ 0,(NO CSR) WE ARE NOT TST @#CSHCSR ; SEE IF OFF LINE BIT(ONLY BIT) IS SET BNE 2$ ; IF NE WE HAVE HAD A CHACHE ERROR CLR CSHERR ; BE SURE TO RESET ERROR FLAG BR 5$ ; GO CHECK POOL 2$: CMP CSHERR,#4 ; IF NE 0, WE ALREADY HAVE HAD A CACHE ERROR BGT 5$ ; ONLY WARN TT0: 5 TIMES INC CSHERR ; SHOW WE HAVE AN ERROR DIR$ #CSHDPB ; ELSE WARN USER OF ERROR 5$: ; REF LABLE CLR R1 ; CLEAR SUM OF FREE POOL CLR R2 ; INITIALIZE SIZE OF LARGEST FRAGMENT CALL $SWSTK,30$ ; SWITCH TO SYSTEM STATE MOV #$CRAVL,R0 ;; GET ADDRESS OF POOL LIST-HEAD 10$: MOV 2(R0),R3 ;; PICKUP THE FRAGMENT SIZE CLC ;; CONVERT SIZE FROM BYTES TO WORDS ROR R3 ;; DON'T USE ASR SINCE IT RUINS THE MSB ADD R3,R1 ;; ADD ITS SIZE TO OUR SUBTOTAL CMP R3,R2 ;; IS THIS THE LARGEST FRAGMENT? BLO 20$ ;; N - JUMP MOV R3,R2 ;; Y - RECORD ITS SIZE 20$: MOV (R0),R0 ;; GET LINK TO NEXT FRAGMENT BNE 10$ ;; LOOP IF NOT THE DUMMY PACKET MOV R1,TOTSIZ ;; SAVE TOTAL POOL SIZE MOV R2,LGESIZ ;; ALSO SAVE LARGEST FRAGMENT SIZE RETURN ;; RETURN TO USER STATE ; ; CHECK POOL STATISTICS AGAINST PREDEFINED LIMITS. ; ISSUE WARNING IF LIMITS HAVE BEEN EXCEEDED. ; 30$: CMP LGESIZ,#42. ; AT LEAST ONE MCR BUFER AVAILABLE? BLT 120$ ; N - TAKE DRASTIC ACTION CMP TOTSIZ,#TOTLMT ; CHECK AGAINST TOTAL FREE LIMIT BLO 40$ ; BRANCH IF LIMIT HAS BEEN SURPASSED CMP LGESIZ,#LGELMT ; CHECK AGAINST LARGEST FRAG. LIMIT BHIS 110$ ; BRANCH IF NOT OVER LIMIT ; ; FORMAT AND PRINT WARNING TO CONSOLE TERMINAL ; 40$: MOV #DATE,R3 ; GET ADDRESS OF ACII DATE IN TT0MSG CALL DATSUB ; CONVERT AND PUT RESULTANT DATE THERE MOV #FREE+5,R0 ; GET ADDRESS OF FREE SIZE FILED MOV TOTSIZ,R1 ; GET BINARY FREE SIZE VALUE CALL CONVRT ; CONVERT FROM BINARY TO ASCII MOV #FRAG+5,R0 ; DO THE SAME THING FOR THE FRAGMENT SIZE MOV LGESIZ,R1 ; GET BINARY LARGEST FRAGMENT SIZE VALUE CALL CONVRT ; PUT ASCII EQUIVALENT IN MESSAGE DIR$ #TT0DPB ; RECORD STATISTICS ON CONSOLE ; ; COPY DATE INTO WARNING MESSAGE, THEN ; SWITCH BACK TO SYSTEM STATE TO SCAN DCB LIST. ; SEND A WARNING TO EACH LOGGED ON TERMINAL WE FIND. ; MOV #MSGHED,R0 ; GET ADDRESS OF DATE HEADER MOV #WARN,R1 ; GET ADDRESS OF WARNING MESSAGE MOV #HEDLEN,R2 ; GET LENGTH OF DATE HEADER 45$: MOVB (R0)+,(R1)+ ; COPY DATE FROM HEADER INTO MESSAGE DEC R2 ; DONE? BNE 45$ ; NO, LOOP MOV $HEADR,R2 ; GET THE ADDRESS OF OUR TASK HEADER ADD #H.LUN+4,R2 ; POINT TO THE SECOND ENTRY IN LUT MOV $DEVHD,R1 ; GET POINTER TO LIST OF DCB'S CALL $SWSTK,100$ ; SWITCH TO SYSTEM STATE 50$: CMP D.NAM(R1),#"TT ;; IS THIS A TERMINAL DCB? BNE 80$ ;; N - GO ON TO THE NEXT DCB MOVB D.UNIT(R1),R3 ;; Y - GET THE LOW UNIT # MOVB D.UNIT+1(R1),R4 ;; AND GET THE HIGH UNIT NUMBER SUB R3,R4 ;; FIND OUT HOW MANY UNITS THERE ARE INC R4 ;; +1 TO GET CORRECT AMMOUNT MOV D.UCB(R1),R3 ;; SET UP ADDRESS OF TERMINAL UCB 60$: BIT #U2.LOG,U.CW2(R3) ;; IS THERE SOMEONE LOGGED ON BEQ 90$ ;; Y - SEND A MESSAGE TO HIM/HER 70$: ADD D.UCBL(R1),R3 ;; N - SKIP TO NEXT UCB SOB R4,60$ ;; LOOP FOR EACH UCB PER DCB 80$: MOV D.LNK(R1),R1 ;; POINT TO NEXT DCB IN LIST BNE 50$ ;; IF THERE IS ONE, GO THRU ITS UCB'S 90$: MOV R1,SAVER1 ;; SAVE ALL PERTINENT REGISTERS MOV R3,SAVER3 ;; MOV R4,SAVER4 ;; RETURN ; RETURN TO USER STATE ; ; BACK IN USER STATE -- IF R1 IS NONZERO THEN BROADCAST A MESSAGE. ; GIVE THE BROADCAST 10 SECONDS TO COMPLETE BEFORE KILLING IT, ; THEN LOOP BACK TO FIND THE NEXT TERMINAL TO SEND TO. ; 100$: MOV SAVER3,R3 ; RESTORE REGS MOV SAVER4,R4 MOV SAVER1,R1 ; BEQ 110$ ; BRANCH IF NO MORE TERMINALS MOV R3,(R2) ; ASSIGN A LUN THE DIRTY WAY DIR$ #BRODPB ; BROADCAST A WARNING DIR$ #FSTIMR ; AND WAIT FOR QIO AND TIMER WTLO$S 0,#3 ; WAIT FOR QIO AND TIMER CMKT$S ; CACEL MARK TIME CALL $SWSTK,100$ ; GO BACK TO SYSTEM STATE BR 70$ ; LOOP BACK TO FIND THE NEXT TERMINATOR. ; ; AT THIS POINT, EACH LOGGED ON USER HAS RECEIVED THE POOL WARNING. ; LAY BACK FOR A SHORT WHIL, THEN CHECK ON POOL AGAIN. ; 110$: DIR$ #TIMDPB ; MARK TIME FOR A LITTLE WHILE STSE$S #EFN2 ; WAIT FOR TIME TO EXPIRE JMP POOL ; WHEN TIME ELAPSES, GO CHECK POOL ; ; NOT ENOUGH FREE POOL TO QUEUE A LINE TO MCR ; TAKE OVER THE SYSTEM, AND ASK TO ABORT TASKS UNTIL POOL RETURNS. ; 120$: MOV #ABOMSG+4,R3 ; GET ADDRESS OF DATE FILED IN ABOMSG CALL DATSUB ; PUT CURRENT ASCII DATE THERE CALL $SWSTK,160$ ;; SWITCH TO SYSTEM STATE MOV @#TTISTA,-(SP) ;; SAVE TERMINAL INPUT STATUS MOV @#TTOSTA,-(SP) ;; SAVE TERMINAL OUTPUT STATUS CLR @#TTISTA ;; CLEAR INPUT STATUS CLR @#TTOSTA ;; CLEAR OUTPUT STATUS CALL ATL ;; PRINT ATL LIST MOV #ABOMSG,R0 ;; GET ADDRESS OF ABORT MESSAGE CALL TTYOUT ;; PRINT IT 130$: CALL TTYIN ;; READ REPLY CLR TSKNAM ;; SET NAME BUFFER TO ALL BLANKS CLR TSKNAM+2 ;; TST R1 ;; DID WE SEE ONLY A DELIMITER? BEQ 140$ ;; Y - CONSIDER THAT TO BE AN ERROR CMP R1,#6 ;; HOW MANY CHARACTERS WERE TYPED IN? BGT 150$ ;; MORE THAN 6 CHARACTERS IS AN ERROR MOV #1,R1 ;; TREAT PERIODS AS ACCEPTABLE INPUT CALL $CAT5B ;; CONVERT FROM ASCII TO RAD 50 BCS 140$ ;; BRANCH IF DETECT AN ILLEGAL CHARACTER MOV R1,TSKNAM ;; SAVE FIRST THREE RAD 50 CHARACTERS MOV #1,R1 ;; RESET PERIOD INDICATOR CALL $CAT5B ;; CONVERT LAST THREE CHARACTERS BCC 150$ ;; THIS TIME BRANCH IF GOOD 140$: MOV #INVNAM,R0 ;; CONVERSION ROUTINE WAS NOT HAPPY CALL TTYOUT ;; ISSUE A WARNING BR 130$ ;; ASK FOR TASK NAME AGAIN 150$: MOV R1,TSKNAM+2 ;; SAVE LAST THREE RAD 50 CHARACTERS MOV (SP)+,@#TTOSTA ;; RESTORE TERMINAL OUTPUT STATUS MOV (SP)+,@#TTISTA ;; RESTORE TERMINAL INPUT STATUS RETURN ;; EXIT SYSTEM STATE ; ;NOW THAT WE ARE IN USER STATE, WE CAN CALL THE EXEC TO ABORT THE TASK. ; ABORTING THE TASK SHOULD RELEASE SOME POOL. ; 160$: DIR$ #ABOTSK ; ISSUE THE ABORT DIRECTIVE BCC 170$ ; BRANCH IF THE DIRECTIVE SUCCEEDED ; ; FOR SOME REASON THE EXEC RETURNED AN ERROR CONDITION. ; TELL THE USER AND ASK FOR ANOTHER TASK NAME. ; CALL $SWSTK,160$ ; SWITCH BACK TO SYSTEM STATE MOV @#TTISTA,-(SP) ;; SAVE THE TERMINAL INPUT STATUS MOV @#TTOSTA,-(SP) ;; SAVE THE TERMINAL OUTPUT STATUS CLR @#TTISTA ;; DISABLE TERMINAL INPUT INTERRUPTS CLR @#TTOSTA ;; MOV #NOTABO,R0 ;; GET ADDRESS OF WARNING MESSAGE CALL TTYOUT ;; PRINT THAT WARNING BR 130$ ;; RE-ASK TASK NAME ; ; WE HAVE JUST ABORTED A TASK, WHICH HOPEFULLY WILL RETURN SOME POOL. ; LOOP BACK AND CHECK POOL AGAIN. ; 170$: DIR$ #FSTIMR ; GIVE TIME FOR THE TASK TO BE ABORTED STSE$S EFN2 ; JMP POOL ; CHECK THE POOL AGAIN ATL: MOV #ACTMSG,R0 ; CALL TTYOUT ; MOV @#$ACTHD,R3 ;; BEGIN WITH THE LOADER + 1 LOOP: MOV T.ACTL(R3),R3 ;; GET THE NEXT ACTIVE TASK BEQ RET ;; IF EQ, WE'RE ALL DONE SEARCHING TST T.STAT(R3) ;; IS TASK ALREADY BLOCKED? BNE LOOP ;; IF NE, YES, SKIP IT MOV T.PCB(R3),R2 ;; GET PCB FOR TASK CMP P.NAM(R2),#^RGEN;; IS THE PARTITION NAME 'GEN' BNE LOOP ;; IF NE, NO, LOOK AGAIN MOV T.NAM(R3),R1 ;; GET FIRST PART OF TASK NAME MOV #BUF+5,R0 ;; GET TASKNAME BUFFER CALL $C5TA ;; CONVERT TO ASCII MOV T.NAM+2(R3),R1 ;; GET SECOND HALF OF TASK NAME CALL $C5TA ;; CONVERT TO RAD50 MOV #BUF,R0 ;; SET BUFFER ADDRESS FOR TYPING CALL TTYOUT ;; WRITE OUT NAME BR LOOP ;; WHO ELSE GETS THE AX RET: RETURN ; THE END ; ; ; DATSUB - OBTAIN THE CURRENT DATE AND TIME, AND CONVERT TO ASCII ; DATSUB: DIR$ #DATDPB ; GET THE CURRENT DATE AND TIME MOV R3,R0 ; COPY ADDRESS OF ASCII OUTPUT FIELD MOV #DATBUF,R1 ; GET ADDRESS OF BINARY DATE CALL $DAT ; CONVERT DATE TO ASCII CMPB (R0),#40 ; IF WE HAVE A ONE-DIGIT DAY... BEQ 10$ ; ...THEN WE END ONE CHAR TOO SOON... MOVB #177,(R0) ; ...SO ADD A RUBOUT TO EVEN IT UP 10$: MOV R3,R0 ; COPY ADDRESS AGAIN ADD #TIME-DATE,R0 ; POINT TO ASCII TIME OUTPUT FIELD MOV #DATBUF+G.TIHR,R1 ; GET ADDRESS OF BINARY TIME MOV #3,R2 ; SPECIFY HH:MM:SS FORMAT CALLR $TIM ; CONVERT TIME TO ASCII ; ; CONVRT - CONVERT BINARY TO ASCII (BASE 10). PADDING WITH NULLS ; CONVRT: MOV #5,R2 ; GET FIELD WIDTH TO PAD 10$: CLRB -(R0) ; PAD WITH NULLS DEC R2 ; DONE? BNE 10$ ; NO, LOOP MOV #CVTPRM,R2 ; GET CONVERSION PARAMETERS CALLR $CBTA ; CONVERT FROM BINARY TO ASCII ; ; TTYIN - INPUT A CHARACTER STRING FROM THE CONSOLE TERMINAL ; TTYIN: MOV #INBUF,R0 ;; GET ADDRESS OF BUFFER TO READ INTO MOV #6,R1 ;; SET LARGEST VALID CHARACTER COUNT 10$: MOVB #40,(R0)+ ;; PRESET BUFFER TO ALL BLANKS SOB R1,10$ ;; MOV #INBUF,R0 ;; POINT AGAIN TO TOP OF BUFFER 20$: TSTB @#TTISTA ;; WAIT FOR A CHARACTER TO BE TYPED BPL 20$ ;; NOT YET, CHECK AGAIN MOVB @#TTIBUF,R2 ;; READ A CHARACTER MOVB R2,@#TTOBUF ;; ECHO IT BICB #200,R2 ;; CONVERT TO SEVEN-BIT CMPB R2,#40 ;; CONTROL CHARACTER? BLE 40$ ;; YES, JUMP CMPB R2,#140 ;; LOWER CASE? BLE 30$ ;; NO, JUMP SUB #40,R2 ;; YES, CONVERT TO UPPER-CASE 30$: MOVB R2,(R0)+ ;; INSERT CHARACTER INTO BUFFER INC R1 ;; UPDATE CHARACTER COUNT CMP R1,#6 ;; BUFFER LENGTH EXCEEDED? BLE 20$ ;; N - LOOP BACK TO GET MORE INPUT 40$: MOV #INBUF,R0 ;; ONCE AGAIN RESET BUFFER POINTER RETURN ; ; TTYOUT - OUTPUT A CHARACTER STRING TO THE CONSOLE TERMINAL ; TTYOUT: MOV #CRLF,R1 ;; GET THE ADDRESS OF A CR-LF CALL 10$ ;; OUTPUT THAT FIRST MOV R0,R1 ;; GET ADDRESS OF THE STRING TO OUTPUT 10$: MOVB (R1)+,@#TTOBUF ;; OUTPUT A CHARACTER BEQ 30$ ;; RETURN WHEN FIND A NULL 20$: TSTB @#TTOSTA ;; WAIT UNTIL TERMINAL IS READY BPL 20$ ;; NOT YET, KEEP WAITING BR 10$ ;; OUTPUT THE NEXT CHARACTER 30$: RETURN ;; ; .END POOL