.TITLE TSF .IDENT /V7.12/ ;**************************************************************************** ; ; TSF.TSK THIS TASK IMPLEMENTS THE TSF COMMAND IN VERSION 7 OF THE ; ACCOUNTING PACKAGE. THIS COMMAND ENABLES A USER TO FIND OUT ; DETAILS OF HIS CPU OR I/O USE DURING THE CURRENT TERMINAL ; SESSION. ; THE FORMAT OF THIS COMMAND IS: ; (1) TSF /RU[NNING] ; RETURN CPU TIME USED BY ALL TASKS CURRENTLY RUNNING ; AT THE ISSUING TERMINAL. ; (2) TSF /FI[NISHED] ; RETURN CPU TIME USED BY ALL TASKS THAT HAVE ALREADY ; FINISHED IN THE CURRENT TERMINAL SESSION. ; (3) TSF ; SAME AS BOTH (1) AND (2) IE. TSF /RU/FI ; (4) TSF TTN:/RU[NNING] ; A PRIVILEGED OPTION WHICH ALLOWS A USER TO FIND OUT ; INFORMATION FOR OTHER TERMINALS. THIS OPTION IS ; NON-PRIVILEGED ONLY IF TTN: IS EITHER "TI:" OR IS THE ; DEVICE SPECIFICATION OF THE ISSUING TERMINAL, OR ; THE SPECIFIED TERMINAL HAS THE SAME LOGON UIC AS THE ; ISSUING TERMINAL. IF ACCOUNTING IS BY GROUP CODE, THE ; LOGON UIC OF THE SPECIFIED TERMINAL MAY DIFFER IN ; MEMBER CODE (GROUP CODES THE SAME). ; (5) TSF TTN:/FI[NISHED] ; FOLLOWS SIMILAR PATTERN TO ABOVE. ; (6) TSF TTN: OR TSF TTN:/RU/FI (THESE ARE EQUIVALENT) ; ; IF /FI IS SPECIFIED OR IMPLIED, THE CONNECT TIME IS DISPLAYED. ; IF BOTH /FI AND /RU ARE SPECIFIED OR IMPLIED, THE PERCENTAGE ; OF THE AVAILABLE CPU USED SINCE LOGON IS DISPLAYED. ; ; VERSION: V6 FEBRUARY 1980 ; VERSION: V7 JANUARY 1981 ; ; STEVE THOMPSON SCHOOL OF CHEMICAL ENGINEERING ; OLIN HALL ; CORNELL UNIVERSITY ; ITHACA NY 14853 ; ; REVISION HISTORY ; ---------------- ; ; SMT718 20 JULY 1981 ADDED INTERFACE TO SPOOLER LPP SO THAT ; TSF /FI RECORDS PAGES PRINTED ; ; SMT753 7 OCT 1981 CHANGED NAMES OF CONDITIONAL ASSEMBLY ; PARAMETERS; SEE THE FILES MODIFY.TXT AND ; CONDEF.MAC FOR DETAILS. ; ; SMT772 16-OCT-81 CORRECTED A BUG WHICH CAUSED TSF TO EXIT ; WITH AN ODD ADDRESS TRAP IF THE COMMAND ; NAME CONTAINED AN EVEN NUMBER OF CHARACTERS ; AND THE REMAINING COMMAND LINE WAS NOT NULL. ; ; SMT789 13-NOV-81 LET GMCR$ ERROR ACT AS TSF TI:/RU/FI ; ; SMT798 9-JAN-82 ALLOW SWITCH TO COME AFTER COMMAND NAME ; WITHOUT AN INTERVENING SPACE. ; ; SMT814 12-APR-82 ADDED RSX-11M V4.0 SUPPORT (MESSAGE TEXT) ; ; SMT821 23-APR-82 CHANGED ENTRY POINT NAMES OF ACCOUNTING ; SUPPORT ROUTINES (SEE MODIFY.TXT) ; ; SMT828 27-JUL-82 REPLACED "$FMTDV" BY "FM.DEV". ; REPLACED "$GNBLK" BY "GT.NXT". ; ;*********************************************************************** .MCALL GMCR$,CSI$,CSI$SW,CSI$ND,CSI$1,CSI$2 .MCALL EXIT$S,QIOW$,DIR$,ALUN$ .MCALL EXST$ ACCDF$ ; DEFINE CONTROL BLOCK OFFSETS BITDF$ ; AND BIT DEFINITIONS CSI$ ; DEFINE CSI OFFSETS LUN1 = 1 ; COMMAND I/O LUN LUN2 = 2 ; TARGET DEVICE LUN EFN1 = 1 ; EVENT FLAG FOR ALL I/O CR = 15 ; CARRIAGE RETURN SPA = 40 ; SPACE HT = 11 ; HORIZONTAL TAB ; ; MACROS ; .MACRO PRINT MSG,MSGSZ MOV MSG,IODPB+Q.IOPL .IF B MSGSZ MOV MSG'SZ,IODPB+Q.IOPL+2 .IFF MOV MSGSZ,IODPB+Q.IOPL+2 .ENDC DIR$ #IODPB .ENDM ; ; LOCAL STORAGE ; CSIBLK: .BLKB C.SIZE .EVEN GMCR: GMCR$ BUF = GMCR+2 ; ; SWITCH MASK TABLE ; RUMASK = 1 ; /RU[NNING] FIMASK = 2 ; /FI[NISHED] MASKW: .WORD 0 ; SWITCH MASK WORD ; ; SWITCH DESCRIPTOR TABLES ; SWITCH: CSI$SW RU,RUMASK,MASKW,,,,LONG CSI$SW FI,FIMASK,MASKW,,,,LONG CSI$ND ; ; ERROR MESSAGES ; RSX-11M V3.2 --> UPPER CASE ; RSX-11M V4.0 --> LOWER CASE ; .NLIST BEX .IIF DF AA$V40, .ENABL LC .IF DF AA$TSF .IFF ERR1: .ASCII /TSF -- Feature not supported/ ERR1SZ=.-ERR1 .IFTF ERR2: .ASCII /TSF -- Syntax error/ ERR2SZ=.-ERR2 ERR3: .ASCII /TSF -- Illegal device or unit/ ERR3SZ=.-ERR3 ERR4: .ASCII /TSF -- Device is not a terminal/ ERR4SZ=.-ERR4 ERR5: .ASCII /TSF -- Privilege violation/ ERR5SZ=.-ERR5 ERR6: .ASCII /TSF -- Terminal is not logged in/ ERR6SZ=.-ERR6 .IFT ERR7: .ASCII /TSF -- Logging task not installed/ ERR7SZ=.-ERR7 ERR8: .ASCII /TSF -- Logging task not active/ ERR8SZ=.-ERR8 ERR9: .ASCII /TSF -- Memory allocation failure/ ERR9SZ=.-ERR9 ; ; TEXT MESSAGES ; .ENABL LC MSG1: .BYTE CR ; MESSAGE BUFFER, STARTING WITH CARRIAGE RETURN .BLKB 80. MSG2: .ASCIZ / Tasks, CPU=/ .IF DF AA$QIO & AA$TCQ MSG3: .ASCIZ %, I/O requests=% .ENDC ; DF AA$QIO & AA$TCQ MSG4: .ASCIZ / Connect time = / MSG5: .ASCIZ / CPU Utilization = / MSG6: .ASCIZ / Pages printed = / .EVEN LOGNAM: .RAD50 /LOG.../ ; LOGGING TASK NAME FLAG: .WORD ; DEFAULT IS BOTH RUNNING AND STOPPED TASKS UCB: .WORD 0 ; UCB ADDRESS OF TARGET TERMINAL .IFTF IODPB: QIOW$ IO.WVB,LUN1,EFN1,,,,<0,0,40> ALUN: ALUN$ LUN2,TI,0 ; DPB FOR ASSIGN LUN2 EXST: EXST$ EX$SUC ; DPB FOR EXIT WITH STATUS .PAGE $TSFEP: ; ENTRY POINT .IFT MOV $TKTCB,R0 ; GET OUR TCB ADDRESS MOV T.UCB(R0),UCB ; SAVE OUR TI: UCB ADDRESS .IFTF DIR$ #GMCR ; GET MCR COMMAND LINE BCS 151$ ; IF CS NONE, DO TSF TI:/RU/FI MOV #BUF,R0 ; SET ADDRESS OF COMMAND LINE 15$: CALL GT.NXT ; GET NEXT NON-BLANK BCC 16$ ; IF CC OK 151$: JMP 105$ ; END OF LINE MEANS TSF TI:/RUN/FIN 16$: CMPB R2,#'/ ; SWITCH COMING BEFORE SPACE? BEQ 17$ ; IF EQ YES TST R1 ; ANY BLANKS? BEQ 15$ ; IF EQ NO, TRY AGAIN 17$: DEC R0 ; STEP BACK TO BEGINNING OF COMMAND MOV $DSW,R1 ; GET LENGTH OF COMMAND LINE ADD #BUF,R1 ; POINT TO LAST CHARACTER SUB R0,R1 ; CALCULATE COMMAND LINE LENGTH MOV R0,CSIBLK+C.CMLD+2 ; SET UP COMMAND LINE ADDRESS MOV R1,CSIBLK+C.CMLD ; AND COMMAND LINE LENGTH CSI$1 #CSIBLK ; CHECK COMMAND LINE SYNTAX BCC 25$ ; IF CC SYNTAX IS OK 20$: PRINT #ERR2 ; SYNTAX ERROR MOV #EX$SEV,EXST+E.XSTS ; SET SEVERE EXIT STATUS JMP EXIT ; SO EXIT 25$: CSI$2 #CSIBLK,OUTPUT,#SWITCH ; PARSE COMMAND LINE BCS 20$ ; IF CS THEN AN ERROR BITB #,CSIBLK+C.STAT ; IF ANY OF THESE BITS ARE SET THEN WE HAVE ; AND ILLEGAL COMMAND LINE BNE 20$ ; SO TELL THE USER ABOUT IT .IFT TST MASKW ; ANY SWITCHES PRESENT? BEQ 70$ ; IF EQ NO, USE /RUN/FIN BIT #RUMASK,MASKW ; /RUN PRESENT? BNE 60$ ; IF NE YES, LEAVE MASK SETTING BIC #AC.RUN,FLAG ; NO, CLEAR RELEVANT MASK BIT 60$: BIT #FIMASK,MASKW ; /FIN PRESENT? BNE 70$ ; IF NE YES, LEAVE MASK SETTING BIC #AC.STP,FLAG ; NO, CLEAR MASK .IFTF 70$: BITB #CS.DVF,CSIBLK+C.STAT ; DEVICE SPECIFIED? BEQ 100$ ; IF EQ NO, IT MUST BE TI: THEN MOV #ALUN,R4 ; GET ADDRESS OF ASSIGN LUN DPB MOV CSIBLK+C.DEVD+2,R0 ; GET ADDRESS OF DEVICE DESCRIPTOR MOVB (R0)+,A.LUNA(R4) ; STORE DEVICE NAME MOVB (R0)+,A.LUNA+1(R4) ; CALL $GTNUM ; GET DEVICE NUMBER MOV R1,A.LUNU(R4) ; STORE DEVICE NUMBER DIR$ R4 ; ASSIGN THE LUN BCC 80$ ; IF CC ASSIGN WORKED OK 75$: PRINT #ERR3 ; MUST HAVE BEEN AN ILLEGAL DEVICE MOV #EX$SEV,EXST+E.XSTS ; SET SEVERE EXIT STATUS JMP EXIT ; SO EXIT 80$: MOV $HEADR,R1 ; GET OUR HEADER ADDRESS MOV H.LUN+<4*>(R1),R1 ; GET UCB ADDRESS OF TARGET DEVICE MOV U.DCB(R1),R2 ; POINT TO DEVICE CONTROL BLOCK CMP D.NAM(R2),#"TI ; WAS TI: EXPLICITLY SPECIFIED? BEQ 100$ ; IF EQ YES, BYPASS DEVICE CHECKS MOV UCB,R0 ; GET TI: UCB ADDRESS CMP R0,R1 ; WAS TI: SPECIFIED AS TTN:? BEQ 100$ ; IF EQ YES, BYPASS DEVICE CHECKS MOV R1,UCB ; SET TARGET TERMINAL UCB ADDRESS BIT #DV.TTY,U.CW1(R1) ; IS IT A TERMINAL DEVICE? BNE 90$ ; IF NE YES PRINT #ERR4 ; NO IS ERROR MOV #EX$SEV,EXST+E.XSTS ; SET SEVERE EXIT STATUS JMP EXIT ; SO EXIT 90$: BIT #U2.PRV,U.CW2(R0) ; ARE WE PRIVILEGED? BNE 100$ ; IF NE YES, BYPASS PRIVILEGE CHECK .IF DF AA$GRP CMPB U.LUIC+1(R0),U.LUIC+1(R1) ; GROUP CODES THE SAME? .IFF CMP U.LUIC(R0),U.LUIC(R1) ; ARE LOGON UICS THE SAME? .ENDC ; DF AA$GRP BEQ 100$ ; IF EQ YES, OK TO PROCEED PRINT #ERR5 ; NO, PRIVILEGE VIOLATION MOV #EX$SEV,EXST+E.XSTS ; SET SEVERE EXIT STATUS JMP EXIT ; SO EXIT 100$: MOV UCB,R1 ; ENSURE THAT WE HAVE THE RIGHT DEVICE BIT #U2.LOG,U.CW2(R1) ; IS THE TERMINAL LOGGED ON? BEQ 105$ ; IF EQ YES PRINT #ERR6 ; NO CAN DO MOV #EX$WAR,EXST+E.XSTS ; SET WARNING EXIT STATUS JMP EXIT ; SO EXIT 105$: ; REF. LABEL .IFF PRINT #ERR1 ; FEATURE NOT SUPPORTED .IFT ; ; DETERMINE WHETHER LOG... IS INSTALLED AND ACTIVE OR NOT ; MOV #LOGNAM,R3 ; POINT R3 TO LOGGING TASK NAME CALL $SRSTD ; LOOK IN THE STD FOR IT BCC 110$ ; GOOD, IT WAS INSTALLED PRINT #ERR7 ; ERROR IF NOT INSTALLED MOV #EX$WAR,EXST+E.XSTS ; SET WARNING STATUS JMP EXIT ; 110$: BIT #TS.EXE,T.STAT(R0) ; WAS IT ACTIVE? BEQ 120$ ; IF EQ YES PRINT #ERR8 ; NO IS ERROR MOV #EX$WAR,EXST+E.XSTS ; SET WARNING STATUS JMP EXIT ; ; ; SEND REQUEST TO LOG... ; 120$: MOV R0,BUF+2 ; SAVE LOG...'S TCB ADDRESS CALL $SWSTK,140$ ; SWITCH STACKS CLR BUF ;; ZERO ADDRESS OF DSR PACKET MOV #B.LTSF,R1 ;; GET LENGTH OF CONTROL BLOCK TO ALLOCATE CALL $ALOCB ;; GET A BLOCK BCS 130$ ;; IF CS THEN ALLOCATION FAILURE MOV R0,BUF ;; SAVE ADDRESS OF CONTROL BLOCK MOV #,B.MASK(R0) ;; SET COMMAND MASK MOV $TKTCB,B.TTCB(R0) ;; INSERT OUR TCB ADDRESS MOV FLAG,B.TTYP(R0) ;; AND REQUEST BIT MASK MOV UCB,B.UCB(R0) ;; SET UCB ADDRESS OF TARGET TERMINAL MOV R0,R1 ;; COPY PACKET ADDRESS TO R1 MOV BUF+2,R0 ;; GET LOG...'S TCB ADDRESS CALL $EXRQF ;; QUEUE PACKET AND START LOG... CALLR $STPCT ;; STOP US UNTIL WE GET A REPLY 130$: RETURN ;; RETURN TO USER LEVEL 140$: MOV BUF,R5 ; GET ADDRESS OF DSR PACKET BNE 150$ ; IF NE THEN WE GOT ONE PRINT #ERR9 ; MEMORY ALLOCATION FAILURE MOV #EX$SEV,EXST+E.XSTS ; SET SEVERE ERROR STATUS JMP EXIT ; SO EXIT ; ; PRINT OUT DEVICE, LOGON UIC, NUMBER OF TASKS, CPU TIME AND I/O REQUESTS ; 150$: MOV #MSG1+1,R0 ; GET MESSAGE ADDRESS MOV B.UCB(R5),R3 ; GET UCB ADDRESS OF QUERIED TT: CALL FM.DEV ; FORMAT THE DEVICE NAME MOV UCB,R3 ; GET UCB ADDRESS MOV U.LUIC(R3),R3 ; GET LOGON UIC CALL FM.UIC ; AND FORMAT IT MOVB #SPA,(R0)+ ; INSERT A SPACE MOVB #SPA,(R0)+ ; AND ANOTHER ONE MOV B.TTCB(R5),R1 ; GET NUMBER OF TASKS CALL DE.CML ; FORMAT AS DECIMAL MOVSTR #MSG2 ; INSERT MESSAGE TEXT MOV R5,R1 ; POINT R1 TO CPU TIME ADD #B.CSF,R1 ; CALL FM.CPU ; FORMAT THE TIME .IF DF AA$QIO & AA$TCQ MOVSTR #MSG3 ; INSERT MESSAGE TEXT MOV R5,R1 ; POINT R1 TO I/O REQUESTS ADD #B.ISF,R1 ; CALL FM.QIO ; FORMAT AS ASCII DECIMAL .ENDC ; DF AA$QIO & AA$TCQ SUB #MSG1,R0 ; CALCULATE LINE LENGTH PRINT #MSG1,R0 ; AND TYPE IT OUT ; ; PRINT OUT CONNECT TIME (IF /FI WAS SPECIFIED OR IMPLIED) ; BIT #AC.STP,FLAG ; /FI SPECIFIED? BEQ 159$ ; IF EQ NO, WE MUST EXIT NOW MOV #MSG1+1,R0 ; GET BUFFER ADDRESS FOR MESSAGE MOVSTR #MSG4 ; INSERT "CONNECT TIME" TEXT MOV R5,R1 ; POINT R1 TO CONNECT TIME ADD #B.TCON,R1 ; CALL FM.CON ; FORMAT CONNECT TIME (NH NM NS) ; ; PRINT OUT CPU UTILISATION IF /FI AND /RU BOTH SPECIFIED OR IMPLIED ; THE CPU PERCENTAGE IS FOUND FROM 100*(CPU TIME)/(CONNECT TIME) ; BIT #AC.RUN,FLAG ; /RU SPECIFIED? MUST ALSO BE /FI TO GET HERE BEQ 158$ ; IF EQ NO, PRINT MESSAGE MOV R0,-(SP) ; SAVE BUFFER POINTER MOV B.CSF(R5),R2 ; GET HIGH ORDER CPU TIME MOV B.CSF+2(R5),R3 ; AND LOW ORDER CPU TIME MOV #1000.,R0 ; SET MULTIPLIER (% TIMES 10) CALL $DMUL ; MULTIPLY CPU TIME BY 1000. MOV R0,B.CSF(R5) ; REPLACE HIGH ORDER RESULT MOV R1,B.CSF+2(R5) ; AND LOW ORDER RESULT MOV R5,R0 ; SET DIVISOR ADDRESS FOR DP.DIV ADD #B.TCON,R0 ; MOV R5,R1 ; SET DIVIDEND ADDRESS FOR DP.DIV ADD #B.CSF,R1 ; CALL DP.DIV ; CALCULATE USAGE PERCENTAGE ; (RESULT IN R2) MOV (SP)+,R0 ; RESTORE BUFFER POINTER MOVSTR #MSG5 ; INSERT "CPU UTILISATION" TEXT CMP R2,#10. ; IS CPU USE LESS THAN 1 PERCENT? BGE 157$ ; IF GE NO MOVB #'0,(R0)+ ; MAKE IT "0.N%" RATHER THAN ".N%" 157$: MOV R2,R1 ; COPY PERCENTAGE TO R1 CLR R2 ; SET NO LEADING ZEROES CALL $CBDMG ; FORMAT AS ASCII DECIMAL MOVB -(R0),1(R0) ; MOVE OVER LAST DIGIT MOVB #'.,(R0)+ ; INSERT A DECIMAL POINT INC R0 ; POINT PAST LAST DIGIT MOVB #'%,(R0)+ ; INSERT A PERCENTAGE SIGN SUB #MSG1,R0 ; CALCULATE MESSAGE LENGTH PRINT #MSG1,R0 ; AND PRINT IT ; ; PRINT PAGE COUNT IF /FI AND /RU BOTH SPECIFIED ; MOV #MSG1+1,R0 ; GET OUTPUT BUFFER ADDRESS MOVSTR #MSG6 ; INSERT PAGES PRINTED CODE MOV B.PSF(R5),R1 ; GET PAGE COUNT CALL DE.CML ; FORMAT AS DECIMAL ASCII 158$: SUB #MSG1,R0 ; CALCULATE LINE LENGTH PRINT #MSG1,R0 ; AND PRINT IT OUT ; ; DEALLOCATE THE DATA PACKET BACK TO THE DYNAMIC STORAGE REGION ; 159$: CALL $SWSTK,EXIT ; SWITCH STACKS AGAIN MOV R5,R0 ;; COPY PACKET ADDRESS TO R0 MOV #B.LTSF,R1 ;; GET CONTROL BLOCK LENGTH CALLR $DEACB ;; RETURN IT TO POOL AND BACK TO USER STATE .ENDC ; DF AA$TSF EXIT: DIR$ #EXST ; EXIT WITH STATUS .END $TSFEP