.TITLE ACNODE .IDENT /V7.17/ ;***************************************************************************** ; ; ACCOUNTING SYSTEM TASK ACNODE. ; TO BE RUN ON RSX11-M V3.2, RSX-11M V4.0 OR RSX-11M V4.1 ONLY. ; ; THIS TASK IS RESPONSIBLE FOR INSERTING INTERCEPTS INTO THE ; EXECUTIVE WHEN THE ACCOUNTING SYSTEM IS STARTED, ACCORDING TO ; THE OPTIONS SELECTED WHEN THE ACCOUNTING SYSTEM WAS GENERATED. ; IT ALLOCATES A PACKET FROM THE DYNAMIC STORAGE REGION AND WRITES ; INTO IT THE NECESSARY ACCOUNTING CODE. JSR INSTRUCTIONS ARE ; INSERTED IN THE EXECUTIVE AT THE APPROPRIATE POINTS. THIS CODE ; RESULTS IN THE TRANSMISSION OF ACCOUNTING INFORMATION TO THE ; TASK LOG... EVERY TIME A TASK EXITS. ; ; VERSION: V6 OCT 79 ; VERSION: V7 JAN 81 ; ; STEVE THOMPSON ; SCHOOL OF CHEMICAL ENGINEERING ; OLIN HALL ; CORNELL UNIVERSITY ; ITHACA NY 14853 ; ; REVISION HISTORY ; ---------------- ; ; SMT708 7-JUL-81 ACNODE NOW SEARCHES FOR THE BINARY VALUE OF TWO ; INSTRUCTIONS WITHIN THE EXECUTIVE TO DETERMINE ; THE PLACE TO INSERT THE CONTEXT SWITCH INTER- ; CEPT. THIS MAKES ACNODE COMPATIBLE WITH ALL ; VERSIONS OF THE AUTOPATCHED EXECUTIVE. ; ; SMT735 5-AUG-81 ADDED TRANSMISSION OF EXIT STATUS TO LOG... ; IF CPU REPORTING IS SUPPORTED. ; ; SMT741 27-AUG-81 ACNODE NOW SEARCHES FOR THE LOCATION OF THE ; TASK START INTERCEPT. THIS PATCH IS OF A ; SIMILAR NATURE TO PATCH SMT708. ; ; SMT753 7-OCT-81 CHANGED NAMES OF CONDITIONAL ASSEMBLY ; PARAMETERS; SEE THE FILES MODIFY.TXT AND ; CONDEF.MAC FOR DETAILS. THE CODE IN THE ; NODE IS NOW DELIMITED BY DOUBLE SEMICOLONS ; TO EMPHASISE THAT IT IS AT SYSTEM STATE. ; ; SMT757 7-OCT-81 ADDED CODE FOR MEMORY USAGE ACCOUNTING. ; ; SMT762 9-OCT-81 ADDED CODE TO SUPPORT BATCH V3 ; ; SMT795 24-NOV-81 FIXED A BUG IN THE ALGORITHM THAT LINKS ; THE ACCOUNTING LIST IN PRIORITY ORDER. ; ; SMT799 12-JAN-82 REMOVED CALLS TO $LOCKL/$UNLKL ; ; SMT814 12-APR-82 ADDED RSX-11M V4.0 SUPPORT ; ; SMT815 12-APR-82 MADE PRIORITY LINK A STANDARD FEATURE ; ; SMT821 23-APR-82 CHANGED ENTRY POINT NAMES OF ACCOUNTING ; SUPPORT ROUTINES (SEE MODIFY.TXT) ; ; SMT830 2-AUG-82 MAKE "EXCLUDE SYSTEM TASKS" OPTION APPLY ; TO CO: RATHER THAN TT0: ; ; SMT842 13-APR-83 ADDED MORE BATCH SYSTEM VERSION 3 SUPPORT. ; ; SMT844 27-APR-83 FIXED ONE REFERENCE TO $COPT (TO @#$COPT) ; ; SMT851 22-JUL-83 ADDED RSX-11M V4.1 SUPPORT ; ;***************************************************************************** .MCALL QIOW$,DIR$,EXIT$S .MCALL PKTDF$,TCBDF$,HWDDF$ .MCALL EXST$ PKTDF$ ; DEFINE PACKET OFFSETS TCBDF$ <:>,<=> ; DEFINE TCB OFFSETS HWDDF$ ; DEFINE HARDWARE ACCDF$ ; DEFINE A/C PACKET OFFSETS (V7 MACRO) BITDF$ ; DEFINE ACCOUNTING BITS (V7 MACRO) ; ; LOCAL DATA ; LUN=1 ; LUN FOR TI: I/O EFN=1 ; EFN FOR TI: I/O LOGNAM: .RAD50 /LOG.../ ; NAME OF LOGGING TASK LOGTCB=LOGNAM ; LOG...'S TCB ADDRESS CDNODE=LOGNAM+2 ; CODE NODE ADDRESS ; ; MACRO DEFINITIONS ; .MACRO PRINT MSG,MSGSZ MOV MSG,QIODPB+Q.IOPL .IF B MSGSZ MOV MSG'SZ,QIODPB+Q.IOPL+2 .IFF MOV MSGSZ,QIODPB+Q.IOPL+2 .ENDC ; B MSGSZ DIR$ #QIODPB .ENDM .MACRO PUSHRG REG MOV REG,-(SP) .ENDM .MACRO POPREG REG MOV (SP)+,REG .ENDM .PAGE ; ; ERROR MESSAGES ; .NLIST BEX .IIF DF AA$V40 ! AA$V41, .ENABL LC ERR1: .ASCII /ACNODE -- "LOG..." not installed/ ERR1SZ=.-ERR1 ERR2: .ASCII /ACNODE -- "LOG..." not active/ ERR2SZ=.-ERR2 ERR3: .ASCII /ACNODE -- Memory allocation failure/ ERR3SZ=.-ERR3 ERR4: .ASCII /ACNODE -- Exiting with errors/ ERR4SZ=.-ERR4 ERR5: .ASCII /ACNODE -- Failed to send node parameters/ ERR5SZ=.-ERR5 ERR6: .ASCII /ACNODE -- Node already active/ ERR6SZ=.-ERR6 ; ; TEXT MESSAGES ; .ENABL LC MSG1: .ASCII /ACNODE -- Node Address / MSG1A: .ASCII /000000 (Size / MSG1B: .ASCII /00000/ WORD: .ASCIZ / words)/ ; ; DIRECTIVE PARAMETER BLOCKS ; .EVEN QIODPB: QIOW$ IO.WVB,LUN,EFN,,,,<0,0,40> EXST: EXST$ EX$SUC .PAGE .SBTTL ACCOUNTING INITIALISATION CODE $ACCEP: ; PROGRAM XFR ADDRESS ; ; VERIFY THAT LOGGING TASK IS INSTALLED AND ACTIVE ; MOV #LOGNAM,R3 ; GET NAME OF LOGGING TASK CALL $SRSTD ; LOOK IN SYSTEM TASK DIRECTORY FOR IT ; IT'S NOT REALLY NECESSARY TO SWITCH TO ; THE SYSTEM STACK FOR THIS SEARCH. BCC 10$ ; OK PRINT #ERR1 ; ERROR - NOT INSTALLED BR 15$ ; EXIT 10$: BIT #TS.EXE,T.STAT(R0) ; IS IT ACTIVE? BEQ 20$ ; IF EQ YES PRINT #ERR2 ; NO IS ERROR 15$: JMP 70$ ; EXIT 20$: MOV R0,LOGTCB ; SAVE LOG...'S TCB ADDRESS ; ; SEARCH FOR LOCATION OF CONTEXT SWITCHING INTERCEPT. THIS IS THE ; 2-WORD INSTRUCTION IN MODULE "SYSXT" THAT READS ; MOV R5,$TKTCB ; THE INTERCEPT IS THE SAME FOR BOTH RSX-11M V3.2 AND V4.0 ; THE NEAREST GLOBAL SYMBOL AT LOWER ADDRESS IS $NONSI, SO WE SEARCH FOR ; THE BINARY VALUE OF THE INSTRUCTION STARTING THERE. ; THE SECOND WORD OF THE INSTRUCTION WE HAVE TO SEARCH FOR WILL BE EQUAL ; TO THE VALUE OF "$TKTCB" MINUS THE ADDRESS OF THE LOCATION MINUS 2 SINCE ; ADDRESSING IS RELATIVE TO PC. ; MOV #$NONSI,R0 ; SET ADDRESS FOR START OF SEARCH 23$: CMP (R0)+,#10567 ; "MOV R5," PART MATCHES? BNE 23$ ; IF NE NO, KEEP LOOKING MOV #$TKTCB,R1 ; GET THE ADDRESS WHERE THE CURRENT TCB SITS SUB R0,R1 ; SUBTRACT CURRENT "PC" SUB #2,R1 ; WE ARE AT THE BEGINNING OF THE INSTRUCTION CMP (R0)+,R1 ; ",$TKTCB" PART MATCHES? BNE 23$ ; IF NE NO CMP -(R0),-(R0) ; YES, POINT TO START OF INSTRUCTION MOV R0,CSOFF ; SAVE IN INTERCEPT ADDRESS TABLE ; ; SEARCH FOR LOCATION OF TASK START INTERCEPT. THIS IS 2 ONE-WORD INSTRUCTIONS ; IN MODULE "REQSB" WHICH READ ; BIC (SP),(R3)+ ; BINARY VALUE 041623 ; CLR (SP) ; BINARY VALUE 005016 ; THIS INTERCEPT IS THE SAME FOR BOTH RSX-11M V3.2 AND V4.0 ; THE NEAREST GLOBAL SYMBOL IS $TSKRT, SO WE SEARCH FROM THERE ONWARDS. THERE ; IS NO RELOCATION COMPUTATION NECESSARY AS FOR THE CONTEXT SWITCHING ; INTERCEPT. ; MOV #$TSKRT,R0 ; SET ADDRESS FOR START OF SEARCH 24$: CMP (R0)+,#41623 ; FOUND FIRST INSTRUCTION? BNE 24$ ; IF NE NO, KEEP LOOKING CMP (R0)+,#5016 ; FOUND BOTH INSTRUCTIONS? BNE 24$ ; IF NE NO, LOOP CMP -(R0),-(R0) ; POINT TO START OF INSTRUCTION PAIR MOV R0,STOFF ; SAVE IN INTERCEPT ADDRESS TABLE ; ; MAKE SURE THAT THE ACCOUNTING NODE IS NOT ALREADY ACTIVE ; CMP @ADDTAB,#4737 ; JSR INSTRUCTION IN FIRST INTERCEPT? BNE 22$ ; IF NE NO, OK TO CONTINUE PRINT #ERR6 ; NODE ALREADY ACTIVE, GIVE ERROR MESSAGE JMP 70$ ; AND EXIT WITH ERROR 22$: ; REF. LABEL ; ; ALLOCATE NODE FROM DYNAMIC STORAGE REGION ; CLR CDNODE ; CLEAR FLAG TO STORE CODE NODE ADDRESS MOV #CDSIZE,R1 ; GET CODE NODE SIZE CALL $SWSTK,30$ ; SWITCH TO SYSTEM STATE CALL $ALOCB ;; ALLOCATE THE CODE BLOCK FROM DSR BCS 25$ ;; IF UNABLE THEN LEAVE FLAG ZERO MOV R0,CDNODE ;; STORE NODE ADDRESS 25$: RETURN ;; EXIT FROM SYSTEM STATE 30$: MOV CDNODE,R5 ; GET NODE ADDRESS ; R5 IS NEEDED IN SEVERAL PLACES FROM HERE ; ON SO DON'T CHANGE IT BNE 35$ ; IF NON-ZERO THEN WE GOT ONE JMP 65$ ; ALLOCATION FAILURE 35$: MOV #CDSIZE,R1 ; GET TOTAL CODE SIZE INC R1 ; MAKE SURE WE DON'T LOSE A BYTE ASR R1 ; CONVERT TO WORDS ; ; TYPE OUT LOCATION AND SIZE OF ACCOUNTING CODE ; PUSHRG R1 ; SAVE R1 ON STACK MOV #MSG1A,R0 ; GET ADDRESS FOR NODE ADDR. MESSAGE MOV CDNODE,R1 ; GET NODE ADDRESS MOV PC,R2 ; WE DO WANT LEADING ZEROES CALL $CBOMG ; CONVERT TO OCTAL MOV #MSG1B,R0 ; GET BUFFER ADDRESS FOR CODE SIZE MOV (SP),R1 ; GET CODE SIZE CALL DE.CML ; CONVERT TO ASCII DECIMAL MOVSTR #WORD ; INSERT TRAILING TEXT SUB #MSG1,R0 ; CALCULATE MESSAGE SIZE PRINT #MSG1,R0 ; TYPE IT OUT POPREG R1 ; RESTORE R1 ; ; FILL NODE WITH ACCOUNTING CODE. THIS CODE EFFECTIVELY BECOMES ; PART OF THE EXECUTIVE. ; MOV R5,R0 ; GET NODE ADDRESS MOV #CDSTRT,R2 ; GET CODE STARTING ADDRESS 40$: MOV (R2)+,(R0)+ ; STORE WORD DEC R1 ; ANY MORE TO TRANSFER BNE 40$ ; IF NE YES. CONTINUE MOV LOGTCB,LOGPTR-CDSTRT(R5) ; SAVE LOG... TCB ADDRESS ; ; TELL LOG... ABOUT NODE PARAMETERS. ; MOV #B.NLEN,R1 ; GET LENGTH OF REQUIRED DSR PACKET CALL $SWSTK,50$ ; SWITCH STACKS CALL $ALOCB ;; GET THE BUFFER BCS 45$ ;; ERROR MOV R0,R1 ;; SAVE PACKET ADDRESS MOV #,B.MASK(R0) ;; FILL IN COMMAND MASK MOV CDNODE,B.NADD(R0) ;; ENTER NODE LOCATION MOV #CDSIZE,B.NSIZ(R0) ;; AND ITS SIZE MOV CDNODE,B.NAHD(R0) ;; SET UP TO POINT TO... ADD #$ACCHD-CDSTRT,B.NAHD(R0) ;; ACCOUNTING LISTHEAD MOV LOGTCB,R0 ;; GET LOG...'S TCB ADDRESS CALLR $EXRQF ;; QUEUE PACKET AND START LOG... 45$: CLR LOGTCB ;; CLEAR FLAG TO SHOW AN ERROR RETURN ;; GO BACK TO USER LEVEL 50$: TST LOGTCB ; WAS THERE AN ERROR? BNE 55$ ; IF NE NO PRINT #ERR5 ; YES, SAY SO (BUT LEAVE NODE ACTIVE) 55$: ; ; ; SET UP NEW CLOCK INTERRUPT VECTOR ; MTPS #PR7 ; LOCK OUT INTERRUPTS MOV R5,@#AA$VEC ;;; STORE NODE ADDRESS IN VECTOR ADD #TIMISR-CDSTRT,@#AA$VEC ;;; ADD OFFSET TO TIME ;;; INTERRUPT SERVICE ROUTINE MOV #PR7,@#AA$VEC+2 ;;; SET NEW HARDWARE PRIORITY BIS #1,@#AA$VEC+2 ;;; AND SET CARRY BIT MTPS #0 ;;; ALLOW INTERRUPTS ; ; INSERT INTERCEPTS INTO THE EXECUTIVE ; MOV #ADDTAB,R1 ; GET ADDRESS OF INTERCEPT ADDRESS TABLE MOV #OFFTAB,R2 ; GET NODE OFFSETS TABLE ADDRESS MOV #NUMINT,R3 ; GET NUMBER OF INTERCEPTS CALL $SWSTK,EXIT ; SWITCH TO SYSTEM STATE 60$: MOV (R1)+,R0 ;; GET INTERCEPT ADDRESS MOV #4737,(R0)+ ;; PUT A "JSR PC" THERE MOV R5,(R0) ;; PLACE NODE ADDRESS IN AFTER JSR PC ADD (R2)+,(R0) ;; ADD OFFSET INTO NODE DEC R3 ;; ARE WE DONE YET? BNE 60$ ;; IF NE NO, CONTINUE ADD #$ACCHD-CDSTRT,R5 ;; POINT R5 TO ACCOUNT LISTHEAD MOV R5,2(R5) ;; SET UP LISTHEAD ADDRESS RETURN ;; EXIT FROM SYSTEM STATE ; ; WORK DONE, NOW EXIT ; 65$: PRINT #ERR3 ; MEMORY ALLOCATION FAILURE 70$: PRINT #ERR4 ; TASK EXITING MOV #EX$SEV,EXST+E.XSTS ; SET SEVERE ERROR STATUS EXIT: DIR$ #EXST ; EXIT WITH STATUS EXIT$S ; JUST IN CASE .PAGE .SBTTL INTERCEPT ADDRESS TABLE ; ; INTERCEPT ADDRESS TABLE ; ; THIS TABLE RECORDS THE ADDRESSES WITHIN THE EXECUTIVE ; WHERE 2 WORDS ARE OVERWRITTEN WITH "JSR PC,X" INSTRUCTIONS ; BY THE ACCOUNTING SYSTEM. ; ADDTAB: ; STOFF: .WORD 0 ; START TASK TIME INTERCEPT .IF DF AA$V40 ! AA$V41 .IF DF G$$EFN .WORD $DREX1 ; TASK EXIT INTERCEPT (V4.0 ONLY) .IFF ; G$$EFN .IF DF D$$PAR .WORD $DREX1+2 ; TASK EXIT INTERCEPT (V4.0 ONLY) .IFF ; D$$PAR .WORD $DREX1 ; TASK EXIT INTERCEPT (V4.0 ONLY) .ENDC ; DF D$$PAR .ENDC ; DF G$$EFN .IFF ; AA$V40 ! AA$V41 .WORD $CEXIT ; TASK EXIT INTERCEPT (V3.2 ONLY) .ENDC ; DF AA$V40 ! AA$V41 CSOFF: .WORD 0 ; CONTEXT SWITCH INTERCEPT .IF DF AA$QIO .WORD $IOFIN ; I/O COUNT INTERCEPT .ENDC ; DF AA$QIO .IF DF AA$LDR & AA$USE .WORD $LOADT ; LOADER REQUEST INTERCEPT .ENDC ; DF AA$LDR & AA$USE NUMINT=<<.-ADDTAB>/2> .PAGE .SBTTL CODE OFFSETS ; ; CODE OFFSETS ; ; THIS TABLE RECORDS THE OFFSETS WITHIN THE ACCOUNTING NODE ; WHICH FORM THE "X" PART OF THE JSR INSTRUCTIONS DESCRIBED ; ABOVE. ; OFFTAB: .WORD TSKREQ-CDSTRT ; START TASK INTERCEPT .WORD TSKEXT-CDSTRT ; STOP TASK INTERCEPT .WORD CONSWT-CDSTRT ; CONTEXT SWITCH INTERCEPT .IF DF AA$QIO .WORD CNTQIO-CDSTRT ; COUNT QIO'S INTERCEPT .ENDC ; DF AA$QIO .IF DF AA$LDR & AA$USE .WORD LOADR-CDSTRT ; LOADER REQUEST INTERCEPT .ENDC ; DF AA$LDR & AA$USE NUMOFF=<<.-OFFTAB>/2> .IF NZ NUMINT-NUMOFF .ERROR NUMINT-NUMOFF ; INVALID TABLE LENGTH (OFFTAB) .ENDC ; NZ NUMINT-NUMOFF .PAGE .SBTTL INTERCEPT CODE ; ; START OF INTERCEPT CODE ; CDSTRT=. ; ; THE NEXT SECTION OF CODE INTERCEPTS A TASK REQUEST. JUST BEFORE THE ; EXECUTIVE IS ABOUT TO DECLARE A TASK ACTIVE (IN MODULE "REQSB"), THE ; ACCOUNTING SYSTEM'S JSR PC INSTRUCTION FORCES A CALL TO THIS SECTION ; OF CODE. THE FOLLOWING THINGS ARE THEN DONE: ; (1) SAVE NEEDED REGISTERS AND ALLOCATE A BUFFER FROM THE ; DYNAMIC STORAGE REGION IN WHICH TO STORE ACCOUNTING ; INFORMATION FOR THE TASK. IF THE BUFFER ALLOCATION ; FAILS, THE TASK IS NOT ACCOUNTED. ; (2) THE ACCOUNTING PACKET IS LINKED INTO THE ACCOUNTING ; LIST AT THE APPROPRIATE POINT. ; (3) THE PACKET IS FILLED IN WITH THE TCB ADDRESS OF THE TASK, ; THE UCB ADDRESS OF THE TASK'S TI:, THE LOGON UIC OF ; THE TERMINAL FROM WHICH THE TASK WAS ACTIVATED, AND THE ; VARIOUS RUNNING SUMS ARE CLEARED. THE START TIME IS SET. ; (4) THE SAVED REGISTERS ARE RESTORED, THE INTERCEPTED EXEC- ; UTIVE INSTRUCTIONS ARE EXECUTED, AND A RETURN IS MADE ; BACK TO NORMAL EXECUTIVE CODE. ; ; NOTE THAT IF VERSION 3 OF THE BATCH SYSTEM IS SUPPORTED, THERE ; IS NO NEED TO TREAT THE BATCH PROCESSOR SPECIALLY, SINCE IT SCANS ; THE ACCOUNTING LIST AND REMOVES ITS ACCOUNTING BLOCK ENTRY ; DURING ITS INITIALIZATION PROCESSING. HENCE THERE IS BATCH-SPECIFIC ; CODE IN THE NODE ONLY FOR VERSION 2 OF THE BATCH SYSTEM. ; .ENABL LSB TSKREQ: ;; .IF DF AA$SYS CMP R1,@#$SYUIC ;; IS THIS A SYSTEM TASK? BNE TSKR1 ;; IF NE NO CMP @#$COPT,R2 ;; YES, IS IT ON CO:? BEQ OUT2 ;; IF EQ YES, FORGET IT TSKR1: ;; REF. LABEL .ENDC ;; DF AA$SYS .IF DF D$$SHF CMP R0,@#$SHFPT ;; SHUFFLER? BEQ OUT2 ;; IF EQ YES, FORGET IT .ENDC ;; DF D$$SHF PUSHRG R0 ;; SAVE R0 (CONTAINS TCB ADDRESS) PUSHRG R1 ;; SAVE R1 (CONTAINS REQUEST UIC) PUSHRG R2 ;; SAVE R2 (CONTAINS TASK'S TI: UCB ADDRESS) MOV #B.LGTH,R1 ;; GET SIZE OF BUFFER TO ALLOCATE CALL @#$ALOCB ;; ALLOCATE IT BCS OUT1 ;; ERROR, FORGET THIS TASK MOV R0,R1 ;; PUT BLOCK ADDRESS IN R1 RLAB: MOV PC,R0 ;; GET CURRENT PC (WE ARE PIC) ADD #$ACCHD-RLAB-2,R0 ;; POINT TO ACCOUNTING LISTHEAD MOV 4(SP),R2 ;; RESTORE TASK'S TCB ADDRESS .IF DF AA$BAT .IF NDF AA$BV3 CMP T.NAM+2(R2),INDNAM ;; INDIRECT FILE PROCESSOR? BEQ 10$ ;; IF EQ YES CMP T.NAM(R2),INDNAM ;; MAYBE BNE 20$ ;; IF NE NO, LINK NORMALLY 10$: CLRB B.PRI(R1) ;; INDIRECT, SO SET PRIORITY FLAG CALL @#$QINSF ;; LINK ONTO END OF ACCOUNTING LIST BR 60$ ;; THAT'S IT .ENDC ;; NDF AA$BV3 .ENDC ;; DF AA$BAT 20$: MOVB T.DPRI(R2),B.PRI(R1) ;; GET TASK'S PRIORITY FOR LINKING ;; ALGORITHM PUSHRG R3 ;; SAVE R3 CALL @#$QINSP ;; INSERT BY PRIO. TO ACCOUNTING LIST POPREG R3 ;; RESTORE R3 60$: MOV 4(SP),R2 ;; RESTORE TCB ADDRESS MOV R2,B.TCB(R1) ;; PUT TCB ADDRESS IN PACKET .IF DF AA$MEM MTPS #PR7 ;; LOCK OUT INTERRUPTS MOV TOTTIM,B.ELPT(R1) ;;; SET HIGH ORDER TIME MOV TOTTIM+2,B.ELPT+2(R1) ;;; SET LOW ORDER TIME MTPS #0 ;;; DROP PRIORITY TO 0 MOV T.MXSZ(R2),B.CORE(R1) ;; SAVE SIZE OF TASK CLRB B.CKP(R1) ;; ASSUME TASK IS CHECKPOINTABLE BIT #T2.CHK,T.ST2(R2) ;; IS IT? BEQ 70$ ;; IF EQ IT IS INCB B.CKP(R1) ;; TASK NOT CHECKPOINTABLE 70$: ;; REF. LABEL .ENDC ;; DF AA$MEM PUSHRG R1 ;; SAVE R1 ON THE STACK ADD #B.STRT,R1 ;; POINT TO PACKET PORTION TO ZERO OUT ;; ** NOTE ** ;; THE SUCCESS OF THE FOLLOWING CODE DEPENDS ;; ON THE STORAGE ALLOCATIONS MADE BY THE ;; ACCDF$ MACRO. CLR (R1)+ ;; CLEAR THE START TIME FIELD CLR (R1)+ ;; CLR (R1)+ ;; CLEAR CPU TIME FIELD CLR (R1)+ ;; .IF DF AA$QIO & AA$TCQ CLR (R1)+ ;; CLEAR NUMBER OF I/O REQUESTS CLR (R1)+ ;; .ENDC ;; DF AA$QIO & AA$TCQ .IF DF AA$FPR .IF DF A$$PRI CLR (R1)+ ;; CLEAR NUMBER OF REQUESTS CLR (R1)+ ;; CLR (R1)+ ;; CLEAR PRIORITY SUM CLR (R1)+ ;; .IFF MOVB T.DPRI(R2),(R1)+ ;; SET PRIO. SUM TO DEFAULT PRIORITY ;; (THIS LEAVES R1 ODD) .ENDC ;; DF A$$PRI .ENDC ;; DF AA$FPR POPREG R1 ;; RESTORE PACKET POINTER FROM STACK MOV (SP),R0 ;; RETRIEVE TASK'S TI: UCB ADDRESS MOV R0,B.UCB(R1) ;; PUT IT IN THE PACKET MOV U.LUIC(R0),B.UIC(R1) ;; WITH THE LOGON UIC OUT1: POPREG R2 ;; RESTORE R2 POPREG R1 ;; RESTORE R1 POPREG R0 ;; RESTORE R0 OUT2: BIC 2(SP),(R3)+ ;;* INTERCEPTED INSTRUCTION CLR 2(SP) ;;* INTERCEPTED INSTRUCTION RETURN ;; RETURN TO NORMAL EXECUTIVE CODE .DSABL LSB .PAGE ; ; THE NEXT SECTION OF CODE INTERCEPTS THE EXIT OF A TASK. ; IN RSX-11M V3.2, ON ENTRY TO THE ROUTINE $CEXIT IN MODULE ; "DREIF", A JSR INSTRUCTION CAUSES A JUMP TO THIS BLOCK OF CODE. ; FOR RSX-11M V4.0, THE INTERCEPT IS AT $DREX1 OR $DREX1+2 ; (DEPENDING ON EXECUTIVE ASSEMBLY OPTIONS) RATHER THAN AT ; $CEXIT (WHICH DOESN'T EXIST AS SUCH IN V4.0). ; ; THE FOLLOWING THINGS ARE DONE: ; (1) THE ACCOUNTING LIST IS SEARCHED TO SEE IF THE TASK ; IS IN IT. IF NOT, A RETURN IS MADE. ; (2) THE REMAINING CPU TIME IS CALCULATED AND ADDED ; INTO THE RUNNING TOTAL. THE TOTAL RUN TIME IS ; THEN FILLED INTO THE PACKET. ; (3) THE ACCOUNTING PACKET IS REMOVED FROM THE LIST ; AND QUEUED TO THE TASK LOG... WHICH PROCESSES THE ; INFORMATION IN IT. ; (4) THE INTERCEPTED INSTRUCTION IS EXECUTED AND A RETURN ; IS MADE BACK TO NORMAL EXECUTIVE CODE. ; TSKEXT: MOV R5,R0 ;; COPY TCB ADDRESS CALL LOCTAB ;; IS THE TASK IN THE ACCOUNTING LIST? BEQ 20$ ;; IF EQ NO, FORGET IT. CALL ADDCPU ;; YES, ADD IN REMAINING CPU TIME .IF DF AA$CPU MOV T.EFLG+2(R5),B.EXST(R1) ;; RETURN TASK'S EXIT STATUS .ENDC ;; DF AA$CPU .IF DF AA$CPU ! AA$ALT MOV T.NAM(R5),B.TNAM(R1) ;; SAVE TASK NAME, 1ST HALF MOV T.NAM+2(R5),B.TNAM+2(R1) ;; AND 2ND HALF ;; THE TASK NAME IS PLACED INTO THE ;; LOCATION IN THE ACCOUNTING PACKET ;; WHERE THE START TIME WAS PLACED ;; I.E. B.TNAM=B.STRT .ENDC ;; DF AA$CPU ! AA$ALT .IF DF AA$MEM ADD T.MXSZ(R5),B.CORE(R1) ;; ADD IN FINAL SIZE BIT #T2.CHK,T.ST2(R5) ;; TASK CHECKPOINTABLE? BEQ 5$ ;; IF EQ NO INCB B.CKP(R1) ;; YES IT IS, SHOW IT IN FIELD 5$: MTPS #PR7 ;; RAISE PRIORITY TO 7 MOV TOTTIM,-(SP) ;;; SAVE HIGH ORDER TIME MOV TOTTIM+2,R0 ;;; PICK UP LOW ORDER TIME MTPS #0 ;;; AND ENABLE INTERRUPTS ADD #B.ELPT+2,R1 ;; POINT TO ELAPSED TIME (LOW ORDER WORD) SUB (R1),R0 ;; SUBTRACT LOW ORDER TIME SBC (SP) ;; AND DON'T FORGET THE CARRY SUB -(R1),(SP) ;; MOV (SP)+,(R1)+ ;; STORE FINAL TIME (HIGH ORDER) MOV R0,(R1) ;; (LOW ORDER) SUB #B.ELPT+2,R1 ;; RESTORE R1 TO PREVIOUS STATE .ENDC ;; DF AA$MEM MOV (R1),(R2) ;; CLOSE UP LIST (REMOVE PACKET) BNE 10$ ;; IF NOT AT END THEN CONTINUE MOV R2,$ACCHD+2 ;; AT END OF LIST SO CORRECT ;; ACCOUNTING LISTHEAD 10$: MOV LOGPTR,R0 ;; GET LOG... TCB ADDRESS CALL @#$EXRQF ;; QUEUE NODE AND START LOG... 20$: ;; REF. LABEL .IF DF AA$V40 ! AA$V41 .IF DF G$$EFN MOV @#$HEADR,R4 ;;* INTERCEPTED INSTRUCTION RETURN ;; GO BACK TO NORMAL EXECUTIVE CODE .IFF ; G$$EFN .IF DF D$$PAR ; (EXECUTIVE COMMON SUPPORT) CALLR @#$CLRMV ;;* INTERCEPTED INSTRUCTION .IFF ; D$$PAR CALLR @#$DRCMT ;;* INTERCEPTED INSTRUCTION .ENDC ; DF D$$PAR .ENDC ; DF G$$EFN .IFF ; AA$V40 ! AA$V41 CALLR @#$DRCMT ;;* INTERCEPTED INSTRUCTION .ENDC ; DF AA$V40 ! AA$V41 .PAGE ; ; THE NEXT SECTION OF CODE IS ENTERED FROM MODULE "SYSXT" ; AT EVERY CONTEXT SWITCH. NOTE THAT IN RSX11M V3.1 AND LATER ; THERE IS NO CONTEXT SWITCH AT EITHER END OF THE NULL TASK ; (AS THERE WAS IN RSX11M V3.0) SO SPECIAL PROVISION HAS TO ; BE MADE FOR THIS IN THE CLOCK INTERRUPT SERVICE ROUTINE. ; HERE, THE FOLLOWING THINGS ARE DONE: ; (1) THE ACCOUNTING LIST IS SEARCHED FOR THE OLD ; TASK. IF IT IS FOUND, THE REMAINING CPU TIME ; IS CALCULATED AND ADDED IN TO THE TASK'S TOTAL. ; (2) THE ACCOUNTING LIST IS SEARCHED FOR THE NEW ; TASK. IF IT IS FOUND, THE START TIME IS PUT INTO ; THE ACCOUNTING PACKET. IF REQUIRED, THE COUNTERS ; ASSOCIATED WITH THE TASK'S MEAN PRIORITY ARE ; UPDATED. ; (3) THE INTERCEPTED INSTRUCTION IS EXECUTED AND A ; RETURN IS MADE BACK TO NORMAL EXECUTIVE CODE. ; CONSWT: PUSHRG R0 ;; SAVE R0 .IF DF AA$USE & AA$CSW ADD #1,SWTTOT+2 ;; UPDATE CONTEXT SWITCH TOTAL ADC SWTTOT ;; .ENDC ;; DF AA$USE & AA$CSW MOV @#$TKTCB,R0 ;; GET CURRENT TCB ADDRESS CALL LOCTAB ;; IS IT IN THE ACCOUNTING LIST? BEQ CONT1 ;; IF EQ NO, SO TRY THE NEW TASK CALL ADDCPU ;; ADD IN CPU TIME ; ; NOW CHECK THE NEW TASK FOR A MATCH ; CONT1: MOV R5,R0 ;; COPY NEW TCB ADDRESS TO R0 CALL LOCTAB ;; IS IT IN THE ACCOUNTING LIST? BEQ CONT2 ;; IF EQ NO, OH WELL. MTPS #PR7 ;; RAISE PRIORITY TO 7 MOV TIME,B.STRT(R1) ;;; STORE HIGH ORDER TIME MOV TIME+2,B.STRT+2(R1) ;;; AND LOW ORDER TIME MTPS #0 ;;; ENABLE INTERRUPTS. .IF DF AA$FPR & A$$PRI CLR R2 ;; CLEAR REGISTER READY FOR TASK PRIORITY BISB T.PRI(R0),R2 ;; GET THE PRIORITY ADD #B.SPRI+2,R1 ;; POINT TO LOW ORDER PRIORITY SUM ;; (THIS BIT OF CODE WORKS BECAUSE ;; THE 2 WORDS AT B.NREQ PRECEDE THE ;; 2 WORDS AT B.SPRI) ADD R2,(R1) ;; ADD PRIORITY TO RUNNING SUM ADC -(R1) ;; ADD #1,-(R1) ;; INCREMENT NUMBER OF REQUESTS ADC -(R1) ;; (USE ADD BECAUSE OF C-BIT) .ENDC ;; DF AA$FPR & A$$PRI CONT2: POPREG R0 ;; RESTORE R0 MOV R5,@#$TKTCB ;;* INTERCEPTED INSTRUCTION RETURN ;; GO BACK TO NORMAL EXECUTIVE ; ; THIS ROUTINE CALCULATES THE ELAPSED CPU TIME AND ADDS IT TO ; THE TASK'S RUNNING TOTAL ; ADDCPU: MTPS #PR7 ;; SET PRIORITY TO 7 MOV TIME,-(SP) ;;; STORE HIGH ORDER TIME MOV TIME+2,R0 ;;; AND GET LOW ORDER MTPS #0 ;;; ENABLE INTERRUPTS SUB B.STRT+2(R1),R0 ;; CALCULATE ELAPSED CPU TIME (LOW) SBC (SP) ;; AND REMEMBER THE CARRY SUB B.STRT(R1),(SP) ;; ADD R0,B.CPU+2(R1) ;; ADD IT TO THE TOTAL ADC B.CPU(R1) ;; AND THE CARRY ADD (SP)+,B.CPU(R1) ;; ADD IN THE HIGH ORDER RETURN ;; AND RETURN .PAGE ; ; THE NEXT SECTION OF CODE IS ENTERED JUST BEFORE $IOFIN. ; THE QIO THAT JUST COMPLETED IS COUNTED TOWARDS THE ISSUING ; TASK'S TOTAL. IN DETAIL: ; (1) IF THE "USE" COMMAND IS IN USE, THE SYSTEM-WIDE ; TOTAL OF QIOS ISSUED IS UPDATED. ; (2) IF AA$TCQ IS NOT DEFINED, TASKS WILL BE EXEMPT FROM I/O ; CHARGE, AND SO NO MORE CODE IS ASSEMBLED. ; (3) IF AA$TCQ IS DEFINED, THE ACCOUNTING LIST IS ; SEARCHED FOR THE RELEVANT TASK. IF IT IS FOUND, THE ; QIO IS COUNTED TOWARD'S THE TASKS' TOTAL. A RETURN ; TO THE EXECUTIVE IS THEN MADE. ; ; .IF DF AA$QIO CNTQIO: .IF DF AA$USE ADD #1,QIOCNT+2 ;; UPDATE COUNT OF ALL QIOS ADC QIOCNT ;; .ENDC ;; DF AA$USE .IF DF AA$TCQ PUSHRG R0 ;; SAVE R0 ON STACK PUSHRG R1 ;; SAVE R1 ON STACK MOV I.TCB(R3),R0 ;; PICK UP TCB ADDRESS FROM I/O PACKET CALL LOCTAB ;; IS IT IN THE LIST? BEQ QIO1 ;; IF EQ NO, CONTINUE NORMALLY ADD #1,B.QIO+2(R1) ;; NO, INCREMENT TASKS' I/O COUNT ADC B.QIO(R1) ;; NOT FORGETTING THE CARRY QIO1: POPREG R1 ;; RESTORE R1 POPREG R0 ;; RESTORE R0 .ENDC ;; DF AA$TCQ MOV I.IOSB+4(R3),R2 ;;* INTERCEPTED INSTRUCTION RETURN ;; AND BACK TO NORMAL CODE .ENDC ; DF AA$QIO .PAGE ; ; THIS ROUTINE INTERCEPTS THE LOADER AND UPDATES THE COUNT ; ; EVERY TIME THE EXECUTIVE CALLS THE LOADER WITH AN INITIAL LOAD ; OR CHECKPOINT REQUEST, THIS ROUTINE IS ENTERED. IT ADDS ONE ; TO THE COUNT OF TOTAL LOADER REQUESTS. ; .IF DF AA$LDR & AA$USE LOADR: ADD #1,LOADER+2 ;; UPDATE LOADER COUNT ADC LOADER ;; MOV @#$LDRPT,R0 ;;* INTERCEPTED INSTRUCTION RETURN ;; BACK TO NORMAL CODE .ENDC ;; DF AA$LDR & AA$USE .PAGE ; ; THIS IS THE CLOCK INTERRUPT SERVICE ROUTINE. ; ; THIS ROUTINE IS ENTERED AT HARDWARE PRIORITY 7 WITH THE CARRY ; BIT SET AT EVERY CLOCK INTERRUPT. AFTER TAKING CARE OF THE ; ACCOUNTING SYSTEM, A JUMP IS MADE THE THE EXECUTIVE'S NORMAL ; CLOCK INTERRUPT SERVICE ROUTINE IN THE MODULE "TDSCH". ; TIMISR: ;;; .IF DF AA$USE ! AA$BAT ADC TOTTIM+2 ;;; UPDATE TOTAL TIME COUNT (C BIT SET) ADC TOTTIM ;;; DON'T FORGET THE CARRY BIT #PMODE,@#PS ;;; DID WE COME FROM THE EXEC? BNE CLOCK1 ;;; IF EQ NO CMP #$HEADR,@#$RQSCH ;;; YES,IDLE TIME? BEQ 10$ ;;; IF EQ YES ADD #1,KNLTIM+2 ;;; UPDATE COUNT OF EXEC TIME ADC KNLTIM ;;; BR CLOCK1 ;;; UPDATE COUNT OF NON-NULL TIME 10$: ADD #1,NULTIM+2 ;;; YES, UPDATE COUNT OF NULL TIME ADC NULTIM ;;; BR CLOCK ;;; CLOCK1: ADD #1,TIME+2 ;;; INCREMENT NON-NULL TIME COUNTER ADC TIME ;;; .IFF ;;; DF AA$USE ! AA$BAT ADC TOTTIM+2 ;;; UPDATE TOTAL TIME COUNT (C BIT SET) ADC TOTTIM ;;; BIT #PMODE,@#PS ;;; WAS IT EXEC TIME? BNE CLOCK1 ;;; IF EQ NO CMP #$HEADR,@#$RQSCH ;;; YES, IDLE LOOP? BEQ CLOCK ;;; IF EQ YES CLOCK1: ADD #1,TIME+2 ;;; NO, UPDATE COUNT OF NON-NULL TIME ADC TIME ;;; .ENDC ; DF AA$USE ! AA$BAT CLOCK: JMP @#$CKINT ;;; JUMP TO CLOCK ISR IN MODULE "TDSCH" .PAGE ; ; LOCTAB LOCATE TASK ACCOUNTING BLOCK. ; THIS ROUTINE SEARCHES THE ACCOUNTING LIST FOR A TASK ; ACCOUNTING BLOCK THAT MATCHES THE SPECIFIED TCB ; ADDRESS. ; IT DEPENDS ON THE OFFSET B.LNK BEING ZERO. ; ; INPUTS: ; ; R0 -- CONTAINS TCB ADDRESS TO SCAN FOR ; ; OUTPUTS: ; ; Z=0 -- TASK NOT IN ACCOUNTING LIST ; ; Z=1 -- FOUND ENTRY ; R0 -- TCB ADDRESS ; R1 -- ACCOUNTING BLOCK ADDRESS ; R2 -- PREVIOUS ENTRY IN LIST ; LOCTAB: MOV PC,R2 ;; GET CURRENT PC (BECAUSE WE ARE PIC CODE) ADD #$ACCHD-LOCTAB-2,R2 ;; CALCULATE ACTUAL ADDRESS 80$: MOV (R2),R1 ;; GET NEXT ENTRY ADDRESS BEQ 90$ ;; IF = 0, THEN NO MATCH (END OF LIST) CMP R0,B.TCB(R1) ;; DOES THIS TCB MATCH? BEQ 85$ ;; IF EQ YES, GIVE IT BACK TO USER MOV R1,R2 ;; NO, CONTINUE LOOKING BR 80$ ;; TRY AGAIN 85$: CLZ ;; LET USER KNOW THAT WE GOT ONE 90$: RETURN ;; AND RETURN .PAGE ; ; STATIC DATA BASES ; ; ****** W A R N I N G ****** ; ; THE ORDER OF THESE STORAGE ALLOCATIONS IS KNOWN TO LOG... ; AND MUST NOT BE ALTERED. ; $ACCHD: .WORD 0 ; ACCOUNTING LISTHEAD .WORD .-2 LOGPTR: .WORD 0 ; LOG... TCB ADDRESS TOTTIM: .WORD 0,0 ; TIME FROM START OF ACNODE .IF DF AA$USE ! AA$BAT KNLTIM: .WORD 0,0 ; EXEC TIME NULTIM: .WORD 0,0 ; NULL TIME .ENDC ; AA$USE ! AA$BAT .IF DF AA$LDR & AA$USE ! AA$BAT LOADER: .WORD 0,0 ; TOTAL LOADER REQUESTS .ENDC ; DF AA$LDR & AA$USE ! AA$BAT .IF DF AA$QIO & AA$USE ! AA$BAT QIOCNT: .WORD 0,0 ; TOTAL QIOS COUNTER .ENDC ; DF AA$QIO & AA$USE ! AA$BAT .IF DF AA$CSW & AA$USE ! AA$BAT SWTTOT: .WORD 0,0 ; TOTAL CONTEXT SWITCHES COUNTER .ENDC ; DF AA$CSW & AA$USE ! AA$BAT TIME: .WORD 0,0 ; COUNT OF NON-NULL TIME .IF DF AA$BAT .IF NDF AA$BV3 INDNAM: .RAD50 /AT./ ; INDIRECT RUNS BATCH JOBS IN BATCH V2 .ENDC ; NDF AA$BV3 .ENDC ; DF AA$BAT ; ; END OF CODE (IN NODE) ; CDEND=. ; ; SIZE OF ALL CODE IN NODE ; CDSIZE=CDEND-CDSTRT .END $ACCEP