From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  3-MAR-1992 21:18:42.56
To:	ARISIA::EVERHART
CC:	
Subj:	MWAIT V1.06, part 2 of 7

From:	RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP@CRDGW2
To:	Everhart@Arisia@MRGATE

Received:  by crdgw1.ge.com (5.57/GE 1.123)
	 id AA15665; Tue, 3 Mar 92 20:38:36 EST
Message-Id:  <9203040138.AA15665@crdgw1.ge.com>
Received: From SUN2.NSFNET-RELAY.AC.UK by CRVAX.SRI.COM with TCP; Tue,  3 MAR 92 17:31:18 PST
Received: from ncdlab.ulcc.ac.uk by sun2.nsfnet-relay.ac.uk via JANET 
          with NIFTP id <3509-4@sun2.nsfnet-relay.ac.uk>;
          Tue, 3 Mar 1992 08:47:12 +0000
Date: Tue, 3 Mar 92 8:25 GMT
From: Nick de Smith <NICK@ncdlab.ulcc.ac.uk>
To: INFO-VAX <@nsfnet-relay.ac.uk:INFO-VAX@KL.SRI.com>
Subject: MWAIT V1.06, part 2 of 7

-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
X$def`09MWAIT_Q_WAITIME`09.blkq`091`09`09; Delta wait time
X$def MWAIT_R_EFNLST`09`09`09`09; $FAOL parameter list
X$def`09MWAIT_L_EFWM`09.blkl`091`09`09; PCB$L_EFWM
X$def`09MWAIT_L_ALL`09.blkl`091`09`09; .TRUE. if waiting on all EFNs
X$def`09MWAIT_L_WEFC`09.blkl`091`09`09; PCB$B_WEFC (0..3)
X$def`09MWAIT_L_WAITIME`09.blkl`091`09`09; => MWAIT_Q_WAITIME
X$def`09MWAIT_L_EFCS`09.blkl`091`09`09; PCB$L_EFCS (0..31)
X$def`09MWAIT_L_EFCU`09.blkl`091`09`09; PCB$L_EFCU (32..63)
X$def MWAIT_K_LENGTH`09`09`09`09; Length of local memory
X$defend`09MWAIT
X`0C
X`09.subtitle`09MWAIT`09`09Determine process wait reasons
X;+
X; MWAIT
X;
X; Description:
X;
X;`09Main entry point for the MWAIT utility.
X;`09Ask for the EPID of the process to examine and call the main code.
X;
X;`09If an explicit PID is given, we examine just that PID. If no PID
X;`09is specified, we scan the entire PCB vector table for all valid PIDs.
X;
X; Inputs:
X;
X;`09Target EPID or 0 from the user.
X;
X; Outputs:
X;
X; Notes:
X;
X;-
X`09.psect`09$CODE`09pic, shr, rd, nowrt, exe, gbl
X
X.entry`09MWAIT,`5Em<>
X
X`09pushab`09EPID_DESC`09`09`09; Where to return PID text
X`09pushab`09PID_PROMPT`09`09`09; Prompt to use for input
X`09pushab`09EPID_DESC`09`09`09; Returned resultant length
X`09calls`09#3, g`5ELIB$GET_FOREIGN`09`09; Get the PID text
X`09blbc`09r0, 05$`09`09`09`09; Check for errors
X
X`09pushab`09EPID`09`09`09`09; Where to return binary PID
X`09pushab`09EPID_DESC`09`09`09; Ascii PID text
X`09calls`09#2, g`5EOTS$CVT_TZ_L`09`09; Convert the PID to binary
X`09blbc`09r0, 05$`09`09`09`09; Check for errors
X
X`09$cmexec_s`09routin=10$,-
X`09`09arglst = E_ARGS`09`09`09; Argument list
X
X05$:`09ret
X
X10$:`09.word`09`5Em<r2,r3,r4,r10>
X`09movab`09g`5EEXE$SIGTORET, SF$A_HANDLER(fp) ; Set up our exception handler
X`09subl`09#MWAIT_K_LENGTH, sp`09`09; Get some space for required data
X`09movl`09sp, r6`09`09`09`09; We will use R6 as or data pointer
X`09movab`09MWAIT_Q_FAODSC(r6), r0`09`09; R0 => FAO descriptor
X`09movab`09MWAIT_T_FAOBUF(r6), DSC$A_POINTER(r0)
X`09movb`09#DSC$K_DTYPE_T, DSC$B_DTYPE(r0)
X`09movb`09#DSC$K_CLASS_S, DSC$B_CLASS(r0)
X`09clrl`09MWAIT_L_FLAGS(r6)`09`09; Say nothing has happened
X
X`09movl`094(ap), r0`09`09`09; R0 = PID to look for
X`09beqlu`0915$`09`09`09`09; No PID, so do the lot.
X
X`09jsb`09g`5EEXE$EPID_TO_PCB`09`09; Convert R0(pid) to R0(PCB)
X`09beqlu`0914$`09`09`09`09; PID is not valid
X`09pushl`09r0`09`09`09`09; Save the PCB address
X`09pushaq`09TITLE`09`09`09`09; Display title
X`09calls`09#1, g`5ELIB$PUT_OUTPUT
X`09blbc`09r0, 100$`09`09`09; Exit if any error
X`09calls`09#1, DISPLAY_PROCESS`09`09; Display this process
X`09ret
X14$:`09movzwl`09#SS$_NONEXPR, r0
X`09ret
X
X15$:`09movl`09#0, r10`09`09`09`09; R10 = Process index
X20$:`09movl`09@SCH$GL_PCBVEC`5Br10`5D, r4`09`09; R4 => Next PCB
X`09cmpl`09r4, g`5ESCH$AR_NULLPCB`09`09; If it is the NULL process...
X`09beqlu`0940$
X
X`09bbss`09#MWAIT_V_TITLE, MWAIT_L_FLAGS(r6), 30$
X`09pushaq`09TITLE`09`09`09`09; Display title
X`09calls`09#1, g`5ELIB$PUT_OUTPUT
X
X30$:`09pushl`09r4`09`09`09`09; Stack the PCB address
X`09calls`09#1, DISPLAY_PROCESS`09`09; Display this process
X`09blbc`09r0, 100$`09`09`09; Exit if any error
X
X40$:`09incl`09r10`09`09`09`09; Move to next table entry
X`09cmpl`09r10, g`5ESCH$GL_MAXPIX`09`09; At the end of the table yet?
X`09blssu`0920$`09`09`09`09; Get next process...
X
X`09movzwl`09#SS$_NORMAL, r0`09`09`09; Return success to caller
X100$:`09ret
X`0C
X`09.subtitle`09DISPLAY_PROCESS`09Display information on one process
X;+
X; DISPLAY_PROCESS
X;
X; Description:
X;
X;`09Display the information that we can given the passed PCB.
X;
X; Inputs:
X;
X;`09R4`09=> PCB of process
X;`09R6`09=> Internal stack
X;
X; Outputs:
X;
X;`09R0`09=  VMS status value
X;
X; Notes:
X;
X;-
X`09.enable`09local_block
X
X.entry`09DISPLAY_PROCESS, `5Em<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
X`09movl`094(ap), r4`09`09`09; R4 => process's PCB
X`09movl`09PCB$L_JIB(r4), r5`09`09; R5 => process's JIB
X`09movl`09PCB$L_EPID(r4), MWAIT_L_EPID(r6)
X`09movl`09#JIB$S_USERNAME, MWAIT_S_USERNAME(r6)
X`09movab`09NULL_USERNAME, MWAIT_T_USERNAME(r6) ; Assume no username
X`09tstl`09r5`09`09`09`09; Any JIB?
X`09beqlu`0910$`09`09`09`09; branch if none
X`09movab`09JIB$T_USERNAME(r5), MWAIT_T_USERNAME(r6) ; Save username
X10$:`09movzbl`09PCB$T_LNAME(r4), MWAIT_S_LNAME(r6)`09; Process name length
X`09movab`09PCB$T_LNAME+1(r4), MWAIT_T_LNAME(r6)`09; Process name
X`09subb3`09PCB$B_PRI(r4), #31, MWAIT_L_PRI(r6)`09; Current priority
X`09subb3`09PCB$B_PRIB(r4), #31, MWAIT_L_PRIB(r6)`09; Base priority
X;
X; Determine the process's state.
X;
X; 1. If the process is NOT in MWAIT, just display the appropriate wait state
X; 2. If it is MWAIT, look at the contents of EFWM...
X;`09a. If EFWM is a small integer, less than RSN$_MAX, display the
X;`09   corresponding resource wait string.
X;`09b. If EFWM contains the address of the JIB, then JIB$B_FLAGS contains
X;`09   bits saying what process resource is being waited for. Display
X;`09   the corresponding string (TQE,BYTCNT or a combination).
X;`09c. Check the table of known MUTEXs to see if we have a match. If
X;`09   one is found (from IDSM table 8.3), then display a nice string.
X;`09d. Display "MWAIT?" - an unknown MWAIT. The mutex address will be
X;`09   shown in the wait mask field.
X;
X`09bicl`09#<MWAIT_M_RWAST!MWAIT_M_RWMBX!MWAIT_M_JIBWAIT>, MWAIT_L_FLAGS(r6)
V ; Say its not waiting (yet)
X`09movzwl`09PCB$W_STATE(r4), r0`09`09; R0 = Process state
X`09cmpl`09r0, #SCH$C_MWAIT`09`09; Is it a mutex wait?
X`09beqlu`0920$`09`09`09`09; Yes!
X`09movl`09SCH_TABLE`5Br0`5D, MWAIT_T_STATE(r6) ; Set the description
X`09brb`0929$
X20$:`09movl`09PCB$L_EFWM(r4), r0`09`09; R0 = resource status
X`09cmpl`09r0, #RSN$_MAX`09`09`09; Is it a resource wait?
X`09bgtru`0922$
X`09movl`09RSN_TABLE`5Br0`5D, MWAIT_T_STATE(r6) ; Set the description
X`09cmpl`09r0, #RSN$_ASTWAIT`09`09; Was it RWAST?
X`09bnequ`0921$`09`09`09`09; Nope
X`09bisl`09#MWAIT_M_RWAST, MWAIT_L_FLAGS(r6) ; Remember this for later
X`09brb`0929$
X21$:`09cmpl`09r0, #RSN$_MAILBOX`09`09; Was it RWMBX?
X`09bnequ`0929$`09`09`09`09; Nope
X`09bisl`09#MWAIT_M_RWMBX, MWAIT_L_FLAGS(r6) ; Remember this for later
X`09brb`0929$
X
X22$:`09cmpl`09r5, r0`09`09`09`09; Is it the JIB address?
X`09bnequ`0924$
X`09bisl`09#MWAIT_M_JIBWAIT, MWAIT_L_FLAGS(r6) ; Remember this for later
X`09movzbl`09JIB$B_FLAGS(r5), r0`09`09; R0 = JIB wait flags...
X`09bicl`09#`5Ec<JIB$M_BYTCNT_WAITERS!JIB$M_TQCNT_WAITERS>, r0
X`09movl`09JIB_TABLE`5Br0`5D, MWAIT_T_STATE(r6) ; Set the description
X`09brb`0929$
X24$:`09moval`09MTX_TABLE, r3`09`09`09; R3 => mutex list table
X25$:`09movq`09(r3)+, r1`09`09`09; R1 = Mutex, R2 => descrip
X`09cmpl`09r1, #-1`09`09`09`09; At the end?
X`09beqlu`0926$`09`09`09`09; Yes
X`09cmpl`09r0, r1`09`09`09`09; Does the mutex match?
X`09bnequ`0925$`09`09`09`09; Try next one if not
X26$:`09movl`09r2, MWAIT_T_STATE(r6)`09`09; Set process state
X29$:
X;
X; Check for terminal name.
X;`09a) If name was returned, use that name
X;`09b) If batch mode then say`09`09-Bat-
X;`09c) If network process then say`09`09-Net-
X;`09d) If process has an owner then say`09-Sub-
X;`09e) If all the above fail, say`09`09-Det-
X;
X`09tstb`09PCB$T_TERMINAL(r4)`09`09; Any terminal name?
X`09beqlu`0930$
X`09movab`09PCB$T_TERMINAL(r4), MWAIT_T_TERMINAL(r6) ; Terminal name
X`09brb`0937$
X30$:`09bbc`09#PCB$V_BATCH, PCB$L_STS(r4), 32$ ; Batch mode?
X`09movab`09BATCH_MODE, MWAIT_T_TERMINAL(r6) ; -Bat-
X`09brb`0937$
X32$:`09bbc`09#PCB$V_NETWRK, PCB$L_STS(r4), 34$ ; Network connect object
X`09movab`09NETWORK_MODE, MWAIT_T_TERMINAL(r6) ; -Net-
X`09brb`0937$
X34$:`09tstl`09PCB$L_OWNER(r4)`09`09`09; If =0 then detached, else sub
X`09bnequ`0936$`09`09`09`09; Branch if subprocess
X`09movab`09DETACH_MODE, MWAIT_T_TERMINAL(r6) ; -Det-
X`09brb`0937$
X36$:`09movab`09SUB_MODE, MWAIT_T_TERMINAL(r6)`09; -Sub-
X37$:
X`09movaq`09FAOCTL, r1`09`09`09; R1 => standard $FAO control string
X`09cmpw`09PCB$W_STATE(r4), #SCH$C_CUR`09; Is this a current process?
X`09bnequ`0939$
X`09bbc`09#SMP$V_ENABLED, g`5ESMP$GL_FLAGS, 39$ ; Is it an SMP system?
X`09movl`09PCB$L_CPU_ID(r4), MWAIT_L_CPU_ID(r6) ; Yes, so save the CPU id
X`09movaq`09FAOCTL_SMP, r1`09`09`09; R1 => SMP $FAO control string
X
X39$:`09movab`09MWAIT_Q_FAODSC(r6), r0`09`09; R0 => FAO descriptor
X`09movw`09#MWAIT_C_FAOBUFLEN, DSC$W_LENGTH(r0)
X`09$FAOL_S`09ctrstr=(r1)`09`09, -
X`09`09outlen=MWAIT_Q_FAODSC(r6), -`09; Format output
X`09`09outbuf=MWAIT_Q_FAODSC(r6), -
X`09`09prmlst=MWAIT_R_PRMLST(r6)
X`09blbcw`09r0, 100$
X
X`09pushaq`09MWAIT_Q_FAODSC(r6)`09`09; Display output
X`09calls`09#1, g`5ELIB$PUT_OUTPUT
X
X; Now handle the event flag clusters and wait masks
X
X`09movl`09PCB$L_EFWM(r4), MWAIT_L_EFWM(r6) ; Event flag wait mask
X`09movzwl`09PCB$W_STATE(r4), r0`09`09; R0 = Process state
X`09cmpw`09r0, #SCH$C_CEF`09`09`09; For EFN waits, negate wait mask
X`09beqlu`0940$
X`09cmpw`09r0, #SCH$C_LEF
X`09beqlu`0940$
X`09cmpw`09r0, #SCH$C_LEFO
X`09bnequ`0945$
X40$:`09mcoml`09MWAIT_L_EFWM(r6), MWAIT_L_EFWM(r6) ; Make mask into set of bi
Vts
X45$:`09extzv`09#PCB$V_WALL, #1, PCB$L_STS(r4), MWAIT_L_ALL(r6) ; .TRUE. if w
Vait is for all
X`09movzbl`09PCB$B_WEFC(r4), MWAIT_L_WEFC(r6)`09; Set the EFN cluster number
X`09movaq`09MWAIT_Q_WAITIME(r6), MWAIT_L_WAITIME(r6) ; Set the time buffer
X`09subl3`09PCB$L_WAITIME(r4), g`5EEXE$GL_ABSTIM_TICS, r0 ; R0 = Waitime in 1
V0ms ticks
X`09emul`09r0, #100000, #0, MWAIT_Q_WAITIME(r6)`09; Make into an ABS time
X`09mcoml`09MWAIT_Q_WAITIME(r6), MWAIT_Q_WAITIME(r6) ; ...and now a DELTA
X`09mcoml`09MWAIT_Q_WAITIME+4(r6), MWAIT_Q_WAITIME+4(r6)
X
X`09movl`09PCB$L_EFCS(r4), MWAIT_L_EFCS(r6) ; 0: System EFN mask
X`09movl`09PCB$L_EFCU(r4), MWAIT_L_EFCU(r6) ; 1: User EFN mask
X
X`09movab`09MWAIT_Q_FAODSC(r6), r0`09`09; R0 => FAO descriptor
X`09movw`09#MWAIT_C_FAOBUFLEN, DSC$W_LENGTH(r0)
X`09$FAOL_S`09ctrstr=EFAOCTL, -
X`09`09outlen=MWAIT_Q_FAODSC(r6), -`09; Format output
X`09`09outbuf=MWAIT_Q_FAODSC(r6), -
X`09`09prmlst=MWAIT_R_EFNLST(r6)
X`09blbcw`09r0, 100$
X`09pushaq`09MWAIT_Q_FAODSC(r6)`09`09; Display output
X`09calls`09#1, g`5ELIB$PUT_OUTPUT
X
X`09movl`09PCB$L_EFC2P(r4), r1`09`09; Is there an EFC #2 ?
X`09beqlu`0950$
X`09movzbl`09CEB$T_EFCNAM(r1), r2
X`09movab`09CEB$T_EFCNAM+1(r1), r3
X`09$printf`09CEFAOCTL, 2, CEB$L_EFC(r1), CEB$L_UIC(r1), r2, r3
X50$:
X`09movl`09PCB$L_EFC3P(r4), r1`09`09; Is there an EFC #3 ?
X`09beqlu`0955$
X`09movzbl`09CEB$T_EFCNAM(r1), r2
X`09movab`09CEB$T_EFCNAM+1(r1), r3
X`09$printf`09CEFAOCTL, 3, CEB$L_EFC(r1), CEB$L_UIC(r1), r2, r3
X55$:
X
X`09bbc`09#PCB$V_PHDRES, PCB$L_STS(r4), 60$ ; Only check PHD if resident
X`09movl`09PCB$L_PHD(r4), r5`09`09; R5 => PHD
X
X`09extzv`09#PSL$V_CURMOD, #PSL$S_CURMOD, PHD$L_PSL(r5), r1`09; R1 = Processo
Vr mode
X`09extzv`09#PSL$V_PRVMOD, #PSL$S_PRVMOD, PHD$L_PSL(r5), r2`09; R2 = Previous
V mode
X`09printf`09<!_Mode: Current: !AC, Previous: !AC>,-
X`09`09MODE_TABLE`5Br1`5D, MODE_TABLE`5Br2`5D
X60$:
X
X`09movzbl`09PCB$B_ASTACT(r4), r1`09`09; R1 = AST active mask
X`09movzbl`09PCB$B_ASTEN(r4), r2`09`09; R2 = AST enabled mask
X`09subl3`09PCB$L_ASTQFL(r4), PCB$L_ASTQBL(r4), r3 ; .TRUE. if ASTs waiting
X`09printf`09<!_AST status: Active: !AC, Enabled: !AC!0UL!0%C!%E, AST(s) wait
Ving!%F>,-
X`09`09AST_TABLE`5Br1`5D, AST_TABLE`5Br2`5D, r3
X
X`09bbc`09#MWAIT_V_RWAST, MWAIT_L_FLAGS(r6), 80$
X`09jsb`09g`5EPROCESS_RWAST`09`09`09; Deal with RWAST states
X80$:
X`09bbc`09#MWAIT_V_RWMBX, MWAIT_L_FLAGS(r6), 85$
X`09jsb`09g`5EPROCESS_RWMBX`09`09`09; Deal with RWMBX states
X85$:
X`09bbc`09#MWAIT_V_JIBWAIT, MWAIT_L_FLAGS(r6), 90$
X`09jsb`09g`5EPROCESS_JIBWAIT`09`09; Deal with JIB wait states
X
X90$:`09movzwl`09#SS$_NORMAL, r0`09`09`09; Return success to caller
X100$:`09ret
X
X`09.disable`09local_block
X`0C
X`09.subtitle`09PROCESS_RWAST`09Analyse RWAST condition
X;+
X; PROCESS_RWAST
X;
X; Description:
X;
X;`09This routine is called when a process that is in RWAST is scanned.
X;`09The code attempts to determine the state of the various critical
X;`09quotas and system flags.
X;
X; Inputs:
X;
X;`09R4`09=> PCB
X;`09R6`09=> Internal stack
X;
X; Outputs:
X;
X;`09R0`09=  VMS status value
X;
X; Notes:
X;
X;-
X`09.enable`09local_block
X
XPROCESS_RWAST:
X`09bbc`09#PCB$V_SSRWAIT, PCB$L_STS(r4), 1$ ;
X`09print`09<`09Process resource wait is DISABLED.>
X1$:
X`09bbs`09#PCB$V_SSRWAIT, PCB$L_STS(r4), 2$ ;
X`09print`09<`09Process resource wait is ENABLED.>
X2$:
X`09bbc`09#PCB$V_DELPEN, PCB$L_STS(r4), 3$ ; Process being deleted?
X`09print`09<`09Process is marked for deletion.>
X3$:
X`09tstw`09PCB$W_DIOCNT(r4)`09`09; Any DIO left?
X`09bnequ`0910$
X`09print`09<`09Process has no DIO left (DIOCNT zero).>
X10$:
X`09tstw`09PCB$W_BIOCNT(r4)`09`09; Any BIO left?
X`09bnequ`0920$
X`09print`09<`09Process has no BIO left (BIOCNT zero).>
X20$:
X`09subw3`09PCB$W_DIOCNT(r4), PCB$W_DIOLM(r4), r1 ; Any DIO outstanding?
X`09beqlu`0930$
X`09printf`09<!_Process has !UW. outstanding DIO operation!%S (DIOCNT: !UW.,
V DIOLM: !UW.)>,-
X`09`09r1, PCB$W_DIOCNT(r4), PCB$W_DIOLM(r4)
X30$:
X`09subw3`09PCB$W_BIOCNT(r4), PCB$W_BIOLM(r4), r1 ; Any BIO outstanding?
X`09beqlu`0940$
X`09printf`09<!_Process has !UW. outstanding BIO operation!%S (BIOCNT: !UW.,
V BIOLM: !UW.)>,-
X`09`09r1, PCB$W_BIOCNT(r4), PCB$W_BIOLM(r4)
X40$:
X`09tstw`09PCB$W_PRCCNT(r4)`09`09; Any sub-processes?
X`09beqlu`0950$
X`09printf`09<!_Process has !UW. live sub-process!-!0UW!1%C!%Ees!%F>,-
X`09`09PCB$W_PRCCNT(r4)
X50$:
X`09tstb`09PCB$B_DPC(r4)`09`09`09; Any delete pending count?
X`09beqlu`0960$
X`09printf`09<!_Process has !UB. outstanding XQP event!%S.>,-
X`09`09PCB$B_DPC(r4)
X60$:
X`09tstw`09PCB$W_ASTCNT(r4)`09`09; Any ASTs left?
X`09bnequ`0970$
X`09print`09<`09Process has no AST entries left (ASTCNT zero).>
X70$:
X;
X; If the process header is resident, we can check the PHD$W_ASTLM (initial
X; AST count) field to see if there are outstanding ASTs.
X; We can also dump the saved registers, and therefore get the saved PC from
X; the process. With that, we can attempt to locate the routine in the execut
Vive
X; that started the wait.
X;
X`09bbs`09#PCB$V_PHDRES, PCB$L_STS(r4), 75$ ; Only check PHD if resident
X`09print`09<`09Process header is not resident.>
X`09brw`09100$
X75$:`09movl`09PCB$L_PHD(r4), r5`09`09; R5 => PHD
X
X`09subw3`09PCB$W_ASTCNT(r4), PHD$W_ASTLM(r5), r1 ; Any ASTs outstanding?
X`09beqlu`0980$
X`09printf`09<!_Process has !UW. outstanding AST!%S active (ASTCNT: !UW. ASTL
VM: !UW.)>,-
+-+-+-+-+-+-+-+-  END  OF PART 2 +-+-+-+-+-+-+-+-

