.TITLE ..TMON TASK MONITOR PROGRAM .IDENT /3X A00/ ; .MCALL QIOW$S,MRKT$S,WTSE$,EXIT$S,VRCX$ .MCALL SRDA$,ASTX$S,VRCD$,DIR$,GTIM$ .MCALL .INH0,.ENB0 ; ;*********** NOTE *********** ; THIS TASK MUST RUN AT A HIGHER PRIORITY THAN THE ; TASK IT IS MONITORING. ; ; AUTHOR V.J.PHELPS BOEING - IGDA 4-7-80 ; BASED ON PROGRAM ..UMON WRITTEN BY R. STODOLA ; ; ; ..TMON RECORDS ACTIVITY INFORMATION ON A SELECTED TASK. THE RECORDED ; DATA IS CONVERTED TO TASK ACTIVITY HISTOGRAM INFORMATION BY THE ; TASK 'REPORT.FTN'. SINGLE AND MULTIPLE SEGMENT (OVERLAY) TASKS CAN ; BE MONITORED. OVERLAYED TASKS REQUIRE MORE INFORMATION TO BE SUPPLIED ; TO THE MONITOR THAN A NON-OVERLAY TASK. TASK MUST HAVE LESS THAN 7 OVERLAY ; LEVELS 0-6 (ROOT IS LEVEL 0). ; ; 1. TO MONITOR THE CALLING TASK: ; SEND A PACKET TO ..TMON VIA RESUME OR REQUEST RECEIVER CONTAINING: ; NTICKS,0,0,0,0,LENHDR,SGD1,NSEG,MODE ; WHERE: ; NTICKS=SAMPLING RATE IN CLOCK TICKS (DEFAULT=1). ; LENHDR,SGD1,NSEG ARE 0 FOR A NON-OVERLAY TASK,OR FOR OVERLAYED TASK: ; LENHDR=NUMBER OF DECIMAL WORDS IN HEADER (FROM MAP). ; SGD1=VIRTUAL ADDRESS OF $$$SGD1 (FROM MAP). ; NSEG=NUMBER OF OVERLAYS NOT COUNTING ROOT. ; MODE=IF NONNEG, INDEX OF SINGLE SEGMENT TO MONITOR (ROOT=0). ; ; 2. TO MONITOR ANOTHER TASK: ; SEND A PACKET TO ..TMON VIA RESUME OR REQUEST RECEIVER CONTAINING: ; NTICKS,TASNAM1,TASNAM2,TTDEV,TTUNIT,LENHDR,SGD1,NSEG,MODE ; WHERE: ; NTICKS,LENHDR,SGD1,NSEG ARE AS IN 1. AND: ; TASNAM1=1ST THREE CHARACTERS OF TASK NAME IN RAD50. ; TASNAM2=2ND THREE CHARACTERS OF TASK NAME IN RAD50. ; TTDEV=TT DEVICE NAME ASSOCIATED WITH TASK. ; TTUNIT=TT DEVICE UNIT NUMBER. ; ; ALL NINE WORDS MUST BE SUPPLIED IN ALL CALLS. FOR OVERLAYED TASKS, ; A CURRENT MAP LISTING MUST BE PLACED ; ON UIC [1,1] PRIOR TO ACTIVATING THE MONITOR. ; ; ********************************************************************** ; ; ; LOCAL DATA SECTION ; BUF: .BLKW 13 ;RECEIVER BUFFER ; NTICKS=BUF+4 ;NO. OF TICKS TSKNAM=BUF+6 ;1ST WORD OF TASK NAME DEV=BUF+12 ;TT DEVICE UNIT=BUF+14 ;TT UNIT LENHDR=BUF+16 ;HEADER LENGTH IN WORDS SGD1=BUF+20 ;SEGMENT TABLE START ADDR NSEG=BUF+22 ;NO. OF SEGMENTS LESS ROOT MODE=BUF+24 ;(IF NONNEG) INDEX OF SEGMENT TO MONITOR ; TIPUD: .WORD 0 ;TI PUD ADDR FOR MONITORED TASK BUFX: .BLKW 7 ;SCRATCH BUFFER TIPUDX: .WORD 0 ASTFLG: .WORD 0 ;AST FLG NBAST: .WORD 0 ;NO. OF BLKS ABOVE SEG TBL DELTA: .WORD 0 ;DELTA OF 1ST SEG PAST ROOT PCNTR: .WORD 0 ;TASK PROG CNTR ; TABLE: .WORD TS.WF0 .WORD TS.WF1 .WORD TS.WF2 .WORD TS.WF3 .WORD TS.WF4 .WORD TS.ST0 .WORD TS.ST1 .WORD TS.ST2 .WORD TS.ST3 .WORD TS.ST4 .WORD TS.STP .WORD TS.MRL .WORD TS.MRR .WORD TS.SUS .WORD -1 ; ; ; MACROS ; .MACRO TYPE,ADDR,LEN QIOW$S #IO.WLB,#5,#1,,,, .ENDM ; .NLIST BEX ; MES1: .ASCII <15><12>/TASK MONITOR ON/<15><12> LMES1=.-MES1 .EVEN MES2: .ASCII <15><12>/TASK MONITOR OFF/<15><12> LMES2=.-MES2 .EVEN MES3: .ASCII <15><12>/..TMON EXIT ON OVERFLOW/<15><12> LMES3=.-MES3 .EVEN MES4: .ASCII <15><12>/..TMON .MAP FILE OPENING ERROR/<15><12> LMES4=.-MES4 .EVEN MES5: .ASCII <15><12>/..TMON PROCESS ERROR/<15><12> LMES5=.-MES5 .EVEN ; ; ; DIRECTIVE PARAMETER BLOCKS ; RECREQ: VRCX$ ,BUF,11,TIPUD RECAST: SRDA$ AST RECDAT: VRCD$ ,BUFX,5,TIPUDX WAIT: WTSE$ 1 GETST: GTIM$ BUF1 GETET: GTIM$ BUF2 ; ; ; ; START OF PROGRAM ; START: DIR$ #RECREQ ;RECEIVE REQUEST OR EXIT TSTB @#$DSW ;RECEIVE OK? BGE CONT ;IF GE YES - CONTINUE EXIT: EXIT$S ; CONT: TST TSKNAM ;NEW TASK? BEQ GETTI ;IF EQ NO - MONITOR CALLING TASK MOV TSKNAM,TASK ;YES - GET NEW INFO MOV TSKNAM+2,TASK+2 MOV DEV,TI MOV UNIT,TI+2 BR GOTTI ; GETTI: MOV TIPUD,R0 ;PUD PNTR IN R0 MOV U.DN(R0),TI ;GET DEVICE NAME MOVB U.UN(R0),TI+2 ;GET DEVICE NO. MOV BUF,TASK ;GET TASK NAME MOV BUF+2,TASK+2 ; ; CLEAR TASK FREQUENCY TABLES AND LISTS ; GOTTI: MOV #SLI,R1 MOV #1847.,R0 ;NO. OF WORDS IN MONCOM SGA LOOPC: CLR (R1)+ SOB R0,LOOPC ; DIR$ #RECAST ;SETUP RECEIVE AST TYPE #MES1,#LMES1 ;REPORT MONITOR ON TST NTICKS ;MAKE SURE VALID NO. OF TICKS BGT 1$ MOV #1,NTICKS ;DEFAULT=1 TICK 1$: MOV NTICKS,DTIC ;RECORD NO. OF TICKS IN SGA DIR$ #GETST ;PUT START TIME PARAMS IN SGA TST NSEG ;OVERLAYED TASK? BEQ LOOP ;IF EQ NO ; ; OVERLAYED TASK ; MOV NSEG,R5 ;GET NO. OF SEGMENTS CALL RDMAP ;FILL-IN SEGMENT LENGTH LIST MOV LENHDR,R0 ;GET HEADER LENGTH ASL R0 ;CONVERT TO BYTES ASH #-6,R0 ;COMPUTE NO. OF BLKS IN R0 MOV SGD1,R1 ;SEG TBL VIRT ADDR MOV R1,R2 ;SAVE IN R2 ASH #-6,R1 ;COMPUTE NO. OF BLKS ABOVE SEG TBL TO HDR ADD R1,R0 ;NO. OF BLKS ABOVE SEG TBL IN R0 MOV R0,NBAST ;SAVE FOR FUTURE USE ASH #6,R1 SUB R1,R2 ;DELTA TO START OF SEG TBL IN R2 ADD #14,R2 ;DELTA TO 1ST SEG PAST ROOT IN R2 MOV R2,DELTA ;SAVE FOR FUTURE USE MOV #10000,R4 ;SET UP O/L STATUS MASK IN R4 ; ; REGISTER CONTENTS: ; ; R0=NO. OF BLKS ABOVE SEG TBL ; R2=OFFSET TO 1ST SEG PAST ROOT ; R4=O/L STATUS MASK ; R5=NO. OF SEGMENTS NOT COUNTING ROOT ; LOOP: TST ASTFLG ;AST DECLARED? BEQ 10$ ;IF EQ NO CLR ASTFLG ;CLEAR FLG DIR$ #RECDAT ;RECEIVE THE DATA CMP TIPUDX,TIPUD ;SAME TI? BNE 10$ ;IF NE - NO IGNOR TST BUFX+4 ;TURN MONITOR OFF? (0 TICKS) BNE 10$ ;IF NE NO JMP EXIT1 ;YES ; 10$: MRKT$S #1,NTICKS,#1 ;SET MARK TIME... DIR$ #WAIT ;...AND WAIT NTICKS ; .INH0 ;INHIBIT TASKS SWITCHING ; MOV @#.CRTSK,R1 ;;BEGIN SEARCH AFTER THIS TASK ATL NODE LOOP1: MOV (R1),R1 ;;GET NEXT ATL ENTRY CMP R1,#.ATLLH ;;IF END OF LIST - QUIT BNE 1$ .ENB0 ;ENABLE TASK SWITCHING JMP LOOP ;GO BACK AND WAIT FOR IT ; 1$: MOV A.TD(R1),R3 ;;GET STD ENTRY CMP S.TN(R3),TASK ;;MONITORED TASK? BNE LOOP1 ;;NO CMP S.TN+2(R3),TASK+2 ;;MAYBE BNE LOOP1 ;;NO CMPB A.TS(R1),#TS.RUN ;;FOUND TASK - IS IT RUNNING? BNE INACT ;;IF NE NO MOV #2002,-(SP) ;;SETUP PDR MOV A.HA(R1),-(SP) ;;SETUP PAR CALL ..SPD3 ;;MAP APR3 OVER TASK HDR MOV 60000+H.TPC,PCNTR ;;GET TASK PC CALL ..SPD3 ;;RESTORE APR3 TST NSEG ;;OVERLAYED TASK? BNE ACTIVO ;;IF NE YES JMP ACTIV ACTIVO: ADD (SP)+,R0 ;;BLK NO. WHERE SEG TBL STARTS MOV #77402,(SP) ;;SETUP PDR MOV R0,-(SP) ;;SETUP PAR CALL ..SPD3 ;;MAP APR3 OVER TASK SEG TBL ADD #60000,R2 ;;S/A OF 1ST SEG IN TBL MOV #SLI+2,R1 ;;SLI POINTER MOV #2,R0 ;;SETUP INDEX MOV #14,R3 ;;SETUP SEG TBL INCREMENT ; ; REGISTER CONTENTS: ; ; R0=SEG TBL INDEX ; R1=SLI POINTER ; R2=SEG TBL POINTER ; R3=SEG TBL INCREMENT ; R4=O/L STATUS MASK ; R5=NO. OF SEGMENTS ; ; SCAN TASK SEGMENT TABLE: ; SCANST: BIT R4,(R2) ;;SEG LOADED? BEQ 1$ ;;IF EQ YES CLR SLFLG(R0) ;;NO - CLR LOAD FLG BR 3$ 1$: TST SLFLG(R0) ;;PREV LOADED? BNE 2$ ;;IF NE YES INC SLCNT(R0) ;;NO - INC LOAD CNT INC SLFLG(R0) ;;SET LOAD FLG 2$: MOV 2(R2),14(R1) ;;SAVE SEG BASE ADDR IN SLB MOV R0,(R1)+ ;;SAVE INDEX IN SLI 3$: ADD R3,R2 ;;MOVE TO NEXT SEG TBL ENTRY TST (R0)+ ;;INCREMENT INDEX SOB R5,SCANST ; CALL ..SPD3 ;;RESTORE APR3 CMP (SP)+,(SP)+ ;;CLEAN UP STACK ; .ENB0 ;ENABLE TASK SWITCHING ; ; ; MARK LOADED SEGMENTS: ; MLS: MOV -(R1),R2 ;GET SEG INDEX INC SLF(R2) ;RECORD SEG AS LOADED CMP SLF(R2),#-1 ;OVERFLOW PENDING? BNE 1$ ;IF NE NO JMP EXIT2 1$: TST R2 ;END OF LIST? BNE MLS ;IF NE NO ; ; MARK RELATIVE POSITION OF PC IN ACTIVE SEGMENT ; MAS: CLR R0 ;ROOT INDEX IS 0 MOV PCNTR,R5 ;GET TASK PC MOV #SLB+2,R3 ;SLB POINTER IN R3 MOV SLL,R4 ;ROOT LENGTH IN R4 CMP R5,R4 ;PC IN ROOT? BLO MRKSEG ;IF LT YES LOOP2: CMP #0,(R3) ;BASE ADDR=0? BNE 1$ ;IF NE NO MOV #OUTC,R2 ;YES - PC OUT OF ADDR SPACE BR TBL1 1$: CMP R5,(R3)+ ;PC < SEG BASE? BLO LOOP2 ;IF LT YES TST -(R3) ;BACK UP SLB PNTR MOV -14(R3),R0 ;GET SEGMENT INDEX MOV SLL(R0),R2 ;GET SEGMENT LENGTH ADD (R3)+,R2 ;GET SEG TOP CMP R5,R2 ;PC <= SEG TOP? BHI LOOP2 ;IF GT NO - CHK NXT LEVEL MRKSEG: TST MODE ;MONITOR SINGLE SEG OR TASK? BGE ONESEG ;IF GE THEN SINGLE SEG SUB -(R3),R5 ;PC-BASE ADDR CLR R4 ASHC #3,R4 ;MPY BY 10 DIV SLL(R0),R4 ;COMPUTE SEG OFFSET ASL R4 ;CONVERT TO BYTES MOV #20,R1 ;TABLE INCREMENT MOV #SFT,R2 ;SFT POINTER IN R2 ASR R0 ;CONVERT TO WORD INDEX TFL: TST R0 ;ZERO INDEX? BEQ TBL ;IF EQ YES ADD R1,R2 ;POINT TO NXT TBL DEC R0 ;DECREMENT INDEX BR TFL TBL: ADD R4,R2 TBL1: INC (R2) ;MARK SEGMENT CMP (R2),#-1 ;OVERFLOW PENDING? BNE RESTOR ;IF NE NO JMP EXIT2 ; ; ; ; INACTIVE STATUS PROCESSING: ; COMMON FOR BOTH O/L AND NON-O/L TASKS ; INACT: MOVB A.TS(R1),R0 ;;GET TASK STATUS ; .ENB0 ;ENABLE TASK SWITCHING ; MOV #WAITFR,R2 ;RECORD LIST PNTR IN R2 MOV #TABLE,R1 ;ADDR OF TBL TO SEARCH 1$: CMP R0,(R1) ;MATCH? BEQ MARK ;IF EQ YES TST (R1)+ ;BUMP TBL PNTR BMI MARK ;IF END OF TBL MARK OTHER TST (R2)+ ;BUMP RECORD LIST PNTR BR 1$ MARK: INC (R2) ;MARK REASON FOR WAIT CMP (R2),#-1 ;OVERFLOW PENDING? BEQ EXIT2 ;IF EQ YES TST NSEG ;OVERLAYED TASK? BNE 1$ ;IF NE YES JMP LOOP 1$: JMP RESTOR ; ONESEG: MOV MODE,R4 ;GET INDEX OF SEG TO MON ASL R4 ;CONVERT TO BYTE INDEX CMP R0,R4 ;IS IT ACTIVE SEG? BNE RESTOR ;IF NE NO MOV #MW,R2 ;YES - GET START OF TBL SUB -(R3),R5 ;PC-BASE MOV R5,R4 CMP SLL(R0),#2400. ;CMP TBL LEN TO SEG LEN BLOS TBL ;IF LE THEN SET TBL LEN=SEG LEN CLR R4 ASHC #12,R4 ;MPY BY 1024. (LEN OF TBL) DIV SLL(R0),R4 ;COMPUTE OFFSET INTO TBL ASL R4 ;CONVERT TO BYTE OFFSET JMP TBL ; ; ACTIVE NON-OVERLAYED TASK ; ACTIV: CMP (SP)+,(SP)+ ;;CLEAN UP STACK .ENB0 ;ENABLE TASK SWITCHING ; INC SLF ;RECORD THIS SCAN MOV PCNTR,R5 ;GET TASK PC MOV BUF+16,R3 ;GET TASK LENGTH (WORDS) MOV R3,SLL ;RECORD LENGTH IN SGA FOR REPORT MOV R3,R2 ;MAKE A COPY ASL R2 ;CONVERT TO BYTES CMP R5,R2 ;CHK FOR OUT-OF-BOUNDS PC BLO 1$ ;IF LO THEN OK MOV #OUTC,R2 ;SET UP TO REPORT O-O-B PC JMP TBL1 1$: MOV #MW,R2 ;GET START OF TBL MOV R5,R4 CMP R3,#1200. ;CMP TASK LEN TO TBL LEN BLOS TBL ;IF LE THEN SET TBL LEN=TASK LEN CLR R4 ;SET UP FOR MPY ASHC #11,R4 ;MPY BY 1024./2 (LEN OF TBL/2) DIV R3,R4 ;COMPUTE OFFSET INTO TBL ASL R4 ;CONVERT TO BYTE OFFSET JMP TBL ;FINISH UP IN TBL ; ; PREPARE FOR NEXT LOOP ; RESTOR: MOV NBAST,R0 MOV DELTA,R2 MOV #10000,R4 MOV NSEG,R5 JMP LOOP ; ; EOLX: .ENB0 EXIT1: TYPE #MES2,#LMES2 BR EXITX EXIT2: TYPE #MES3,#LMES3 BR EXITX EXIT3: TYPE #MES4,#LMES4 BR EXITX EXIT4: TYPE #MES5,#LMES5 EXITX: DIR$ #GETET ;PUT END TIME PARAMS IN SGA EXIT$S ; ; ; AST SERVICE ROUTINE ; AST: INC ASTFLG ;SET AST FLG ASTX$S ;EXIT AST ; ; SUBROUTINE FOR READING .MAP FILE TO FILL IN SEGMENT LENGTH LIST (SLL) ; ; REGISTERS ON ENTRY: ; R5 NUMBER OF SEGMENTS LESS ROOT ; .MCALL FINIT$,OPEN$R,GET$,CLOSE$ .MCALL FSRSZ$,FDBDF$,FDRC$A,FDOP$A,NMBLK$ ; RDMAP: FINIT$ MOV #DFNB,R0 ;POINT TO DFNB MOV TSKNAM,N.FNAM(R0) ;GET TASK NAME IN DFNB MOV TSKNAM+2,N.FNAM+2(R0) MOV #SLL,R3 ;SEG LENGTH LIST PNTR MOV R5,R4 ;GET NO. OF SEG-ROOT INC R4 ;NO. OF SEGMENTS (INCL ROOT) OPEN$R #FDB ;OPEN FILE BCC SEARCH ;IF ALL OK - CONT JMP EXIT3 ;ERROR ON FILE OPEN ATTEMPT SEARCH: GET$ R0 ;GET A RECORD CMP RECBUF,#30060 ;IS IT '00'? BNE SEARCH ;IF NE NO LDLOOP: MOV #RECBUF+LENOS,R0 ;POINT TO 1ST BYTE IN LENGTH CALL $COTB ;CONVERT TO BIN MOV R1,(R3)+ ;STORE IN SLL DEC R4 BEQ DONE GETREC: GET$ #FDB ;GET NEXT RECORD CMPB RECBUF,#60 ;MAKE SURE RECORD STARTS WITH 0 OR 1 BLT GETREC CMPB RECBUF,#61 BGT GETREC BR LDLOOP DONE: CLOSE$ #FDB ;CLOSE FILE RETURN ; ;FDB AND BUFFERS: ; LENOS=20 ;FILE RECORD OFFSET TO SEG LENGTH FSRSZ$ 1 FDB: FDBDF$ FDRC$A ,RECBUF,112. FDOP$A 1,DSD,DFNB,FO.RD DFNB: NMBLK$ ,MAP,,DB,0 DSD: .WORD 0,0 ;DATA SET DESCRIP .WORD LDIRNM,DIRNM ;DEFINE DIRECTORY ; RECBUF: .BLKB 112. ;160 OCTAL BYTES ; DIRNM: .ASCII /[200,200]/ LDIRNM=.-DIRNM .EVEN ; .END START