.TITLE PCB_MUTEX_COUNT_SCANNER .SUBTITLE System macros and macro definitions ; ; Program to scan all PCB's in all queues for ; MUTEX count .NE. 0 ; PCB's in MWAIT state ; all known MUTEX's ; ; Program requires the following privs:CMKRNL,PSWAPM ; ; Rebuild MUTEX.EXE with each update of VMS ; ; ; Written by ; ; Michael N. LeVine ; Code 3514 ; Naval Weapons Center ; China Lake ; Ca 93555 ; ; (619)939-2465 ; avn 437-2465 ; .LIBRARY /SYS$LIBRARY:LIB.MLB/ .ENABLE DEBUG $PCBDEF $MTXDEF MAX_PCB=100 ;MAX NUMBER OF PCB'S THAT CAN BE REPORTED CR=13 LF=10 ; ; RETURN DATA TABLE OFFSET INTO EACH ENTRY ; TABLE_L_MTXCNT=0 ;MUTEX COUNT TABLE_L_MTXADDR=0 ;MUTEX ADDRESS TABLE_L_EPID=4 ;EXTERNAL PID TABLE_T_LNAME=8 ;PROCESS NAME K_ENTRY_LEN=4+4+PCB$S_LNAME ;LENGTH OF ENTRY IN TABLE ;LONGWORD EPID=4BYTES ;MUTEX COUNT=4BYTES ;PROCESS NAME=PCB$S_LNAME BYTES .PAGE .SUBTITLE LOCAL DATA AREA .PSECT LOCAL_DATA,RD,WRT,NOEXE,GBL,CON,LONG .ALIGN LONG ; ; working set lock down boundry pointers ; START_LOCK: .ADDRESS START_KERNEL,END_KERNEL LOCKED: .LONG 0,0 ; ACTUALLY LOCKED ; ; headers for each section of output ; M_NOTHING: .ASCID /No PCB's found with non-zero MUTEX count/ M_SOMETHING: .ASCID /The following PCB's have a non-zero MUTEX count/ M_KNOWN: .ASCID /List of known MUTEX's and their current state/ W_NOTHING: .ASCID /No PCB's found in MWAIT queue/ W_SOMETHING: .ASCID /The following PCB's are in MWAIT queue/ ; ; FAO formatting strings ; FAO_PROCESS: .ASCID /MUTEX count=!ZL EPID=!XL Process name=!AS/ FAO_WAITA: .ASCID /MUTEX address=!XL EPID=!XL Process name=!AS/ FAO_WAITN: .ASCID /MUTEX name=!AS EPID=!XL Process name=!AS/ FAO_MUTEX: .ASCID /MUTEX !AS Owner count=!SW !AS/ ; ; mutex status strings copied by FAO ; M_LOCKED: .ASCID /is locked for write/ M_UNLOCKED: .ASCID /is unlocked/ .ALIGN LONG ; ; descripter for FAO output and output line generated ; OUTPUT_STRING: .LONG 80 .ADDRESS OUTPUT_LINE OUTPUT_LINE: .BLKB 80 DESCRIPTER: .LONG 0,0 ; DESCRIPTER TO BUILD LINE FOR OUTPUT OUTPUT_LEN: .LONG 0 ; OUTPUT LINE LENGTH AND DESCRIPTER .ADDRESS OUTPUT_LINE ; ; build list of names and addresses of known MUTEX's ; .PSECT MUTEX_NAME,RD,NOWRT,NOEXE,GBL,CON ; ; MUTEX names go in seperate PSECT .ASCID ; .PSECT LOCAL_DATA KNOWN_MUTEX_COUNT=0 KNOWN_MUTEX_LIST: ; ; macro invoked to define an entry for each known MUTEX ; ; each entry is 2 long-words, the first is the address in memory ; of the MUTEX and the second is the address of the descripter ; of the string containing the name of the MUTEX. ; This macro also defines the string in a seperate PSECT ; .MACRO DEFINE_MUTEX NAME KNOWN_MUTEX_COUNT=KNOWN_MUTEX_COUNT+1 ;bump known mutex count .ADDRESS 'NAME' ;address of mutex .ADDRESS NM'NAME ;address of MUTEX name string .PSECT MUTEX_NAME ;shift PSECT's NM'NAME': .ASCID /'NAME'/ ;build MUTEX name string .PSECT LOCAL_DATA ;return to orig PSECT .ENDM DEFINE_MUTEX ; ; define known MUTEX's ; note that the order must be the same as that used to get the current ; MUTEX value in the KERNEL mode code ; DEFINE_MUTEX CIA$GL_MUTEX DEFINE_MUTEX IOC$GL_MUTEX DEFINE_MUTEX LNM$AL_MUTEX DEFINE_MUTEX EXE$GL_ACLMTX DEFINE_MUTEX EXE$GL_CEBMTX DEFINE_MUTEX EXE$GL_ENQMTX DEFINE_MUTEX EXE$GL_GSDMTX DEFINE_MUTEX EXE$GL_PGDYNMTX DEFINE_MUTEX EXE$GL_SHMGSMTX DEFINE_MUTEX EXE$GL_SHMMBMTX .PAGE .SUBTITLE Main line code .PSECT CODE,RD,NOWRT,EXE,GBL,CON START: $SETSWM_S #1 ;Set process noswap BLBS R0,1$ ;Check for error $EXIT_S R0 1$: $LCKPAG_S START_LOCK,LOCKED ;Lock pages used in KERNEL mode BLBS R0,2$ ;Check for error $EXIT_S R0 2$: $CMKRNL_S GATHER_DATA ;Execute KERNEL mode code BLBS R0,3$ ;Check for error $EXIT_S R0 3$: MOVAL K_TABLE,R11 ;Set up pointer to top of returned data table TSTL K_M_COUNT ;See if any mutex users found BNEQ 4$ ;Yes-skip short exit code PUSHAL M_NOTHING ;Tell user no non-zero MUTEX counts found CALLS #1,G^LIB$PUT_OUTPUT ;Say nothing BRW 6$ 4$: PUSHAL M_SOMETHING ;Say something CALLS #1,G^LIB$PUT_OUTPUT ; ; Output info on processes with non zero MUTEX counts ; 5$: MOVAL TABLE_T_LNAME+1(R11),DESCRIPTER+4 ;Load descripter to point MOVZBL TABLE_T_LNAME(R11),DESCRIPTER ;to process name $FAO_S FAO_PROCESS,OUTPUT_LEN,OUTPUT_STRING,TABLE_L_MTXCNT(R11),- TABLE_L_EPID(R11),#DESCRIPTER ;Generate line describeing proc PUSHAL OUTPUT_LEN ;Output line CALLS #1,G^LIB$PUT_OUTPUT ADDL2 #K_ENTRY_LEN,R11 ;Bump table pointer to next entry DECL K_M_COUNT ;Dec counter BGTR 5$ ;If more non zero MUTEX count-loop back 6$: TSTL K_W_COUNT ;Check for entries in MWAIT queue BGTR 7$ ;If some-skip to print out code PUSHAL W_NOTHING ;None-say none found CALLS #1,G^LIB$PUT_OUTPUT BRW 9$ 7$: PUSHAL W_SOMETHING ;Say some found in MWAIT queue CALLS #1,G^LIB$PUT_OUTPUT 8$: MOVAL TABLE_T_LNAME+1(R11),DESCRIPTER+4 ;Load desc. to pt to proc name MOVZBL TABLE_T_LNAME(R11),DESCRIPTER ;to process name ; ; SEE IF THE MUTEX IS KNOWN ; MOVAL KNOWN_MUTEX_LIST,R9 ;Check address of MUTEX aginst list of MOVL #KNOWN_MUTEX_COUNT,R8 ;known MUTEX's 10$: CMPL TABLE_L_MTXADDR(R11),(R9);MUTEX addr match ? BEQL 11$ ;Yes ADDL #8,R9 ;No-skip to next MUTEX descripter block DECL R8 ;dec counter BGTR 10$ ;If more MUTEX's left-check them ; MUTEX is not known-use address form of MUTEX wait output to build line $FAO_S FAO_WAITA,OUTPUT_LEN,OUTPUT_STRING,TABLE_L_MTXADDR(R11),- TABLE_L_EPID(R11),#DESCRIPTER BRW 12$ ; MUTEX is known-use name form of MUTEX wait output to build line 11$: $FAO_S FAO_WAITN,OUTPUT_LEN,OUTPUT_STRING,4(R9),- TABLE_L_EPID(R11),#DESCRIPTER ; output line describeing PCB in MWAIT state 12$: PUSHAL OUTPUT_LEN CALLS #1,G^LIB$PUT_OUTPUT ADDL2 #K_ENTRY_LEN,R11 ;Bump pointer to next entry in table DECL K_W_COUNT ;Dec counter BLEQ 9$ ;If none left go to next section BRW 8$ ;Loop back for next PCB ; ; list values of all known MUTEX's ; 9$: PUSHAL M_KNOWN ;Print out header CALLS #1,G^LIB$PUT_OUTPUT MOVAL MUTEX_VALUES,R11 ;Pointer to MUTEX value returned table MOVAL KNOWN_MUTEX_LIST,R10 ;Point to known MUTEX table MOVL #KNOWN_MUTEX_COUNT,R9 ;Count of known MUTEX's 13$: BBS #MTX$V_WRT,(R11),14$ ;Write locked?? ; MUTEX not write locked-build line with unlocked string $FAO_S FAO_MUTEX,OUTPUT_LEN,OUTPUT_STRING,4(R10),(R11),#M_UNLOCKED BRB 15$ ; MUTEX write locked-build line with locked string 14$: $FAO_S FAO_MUTEX,OUTPUT_LEN,OUTPUT_STRING,4(R10),(R11),#M_LOCKED ; output describing line 15$: PUSHAL OUTPUT_LEN CALLS #1,G^LIB$PUT_OUTPUT ADDL2 #4,R11 ;Bump MUTEX value table pointer ADDL2 #8,R10 ;Bump MUTEX descripter table pointer DECL R9 ;Dec MUTEX counter BGTR 13$ ;If more loop back $EXIT_S ;All done-quit .PAGE .SUBTITLE KERNEL MODE CODE AND DATA .PSECT KERNEL_MODE,RD,WRT,EXE,GBL,CON,PAGE .ALIGN PAGE START_KERNEL: .ENTRY GATHER_DATA,^M MOVZWL G^SGN$GW_MAXPRCCT,K_MAXCOUNT ;Get max no processes MOVL G^SCH$GL_PCBVEC,R11 ;Get top of PCB vec MOVL (R11),R10 ;Save address of NULL PCB CLRL R9 ;Clear counter MOVAL K_TABLE,R7 ;Get pointer to table 1$: MOVL (R11)+,R8 ;Get pointer to next PCB CMPL R8,R10 ;See if pointer to NULL job BEQL 2$ ;Yes-skip it TSTW PCB$W_MTXCNT(R8) ;See if MUTEX count is zero BEQL 2$ ;If zero-skip to end ; ; Process has non-zero MUTEX count-save data for user mode code to ; output-put in table ; MOVZWL PCB$W_MTXCNT(R8),TABLE_L_MTXCNT(R7) ;Save MUTEX count MOVL PCB$L_EPID(R8),TABLE_L_EPID(R7) ;Save EPID MOVC3 #PCB$S_LNAME,PCB$T_LNAME(R8),TABLE_T_LNAME(R7);Save process name ADDL2 #K_ENTRY_LEN,R7 ;Update table pointer INCL K_M_COUNT ;Bump found counter CMPL K_M_COUNT,#MAX_PCB ;See if table full BGEQ 10$ ;Yes-quit here 2$: INCL R9 ;Inc count of PCB's CMPL R9,K_MAXCOUNT ;See if end of vector BLSS 1$ ;No-get next PCB ptr ; ; Check MWAIT queue and report on each entry ; MOVAL SCH$GQ_MWAIT,R11 ;Save address of header MOVL R11,R10 ;Use copy to scan queue MOVL K_M_COUNT,R8 3$: MOVL (R10),R10 ;Get next MWAIT entry CMPL R10,R11 ;See if done BEQL 10$ ;If yes-skip to next MOVL PCB$L_EFWM(R10),TABLE_L_MTXADDR(R7) ;Save addr of MUTEX MOVL PCB$L_EPID(R10),TABLE_L_EPID(R7) ;Save process EPID MOVC3 #PCB$S_LNAME,PCB$T_LNAME(R10),TABLE_T_LNAME(R7);Process name ADDL2 #K_ENTRY_LEN,R7 ;Bump table pointer INCL K_W_COUNT ;Count of MWAIT entries INCL R8 ;In table count CMPL R8,#MAX_PCB ;See if table full BGEQ 10$ ;Yes-quit here BRB 3$ 10$: ; ; Copy MUTEX values-must be in same order as definition table ; in data area ; MOVAL MUTEX_VALUES,R11 ;Load address of start of value table MOVL G^CIA$GL_MUTEX,(R11)+ ;Load MUTEX values in value table MOVL G^IOC$GL_MUTEX,(R11)+ MOVL G^LNM$AL_MUTEX,(R11)+ MOVL G^EXE$GL_ACLMTX,(R11)+ MOVL G^EXE$GL_CEBMTX,(R11)+ MOVL G^EXE$GL_ENQMTX,(R11)+ MOVL G^EXE$GL_GSDMTX,(R11)+ MOVL G^EXE$GL_PGDYNMTX,(R11)+ MOVL G^EXE$GL_SHMGSMTX,(R11)+ MOVL G^EXE$GL_SHMMBMTX,(R11)+ MOVL #1,R0 ;Return successful status RET ;Done ; ; Data area ; K_M_COUNT: .LONG 0 ;Number non zero MUTEX count PCB's found K_W_COUNT: .LONG 0 ;Number of PCB's in MWAIT queue K_MAXCOUNT: .LONG 0 ;Value of SYSGEN parameter "MAXPROCESSCNT" K_TABLE: .BLKB ;PCB table-MWAIT or count.ne.0 MUTEX_VALUES: .BLKL KNOWN_MUTEX_COUNT ;Copy of MUTEX values END_KERNEL: .END START