From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  3-MAR-1992 23:00:23.63
To:	ARISIA::EVERHART
CC:	
Subj:	MWAIT V1.06, part 3 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 AA19333; Tue, 3 Mar 92 22:10:40 EST
Message-Id:  <9203040310.AA19333@crdgw1.ge.com>
Received: From SUN2.NSFNET-RELAY.AC.UK by CRVAX.SRI.COM with TCP; Tue,  3 MAR 92 17:31:32 PST
Received: from ncdlab.ulcc.ac.uk by sun2.nsfnet-relay.ac.uk via JANET 
          with NIFTP id <3509-5@sun2.nsfnet-relay.ac.uk>;
          Tue, 3 Mar 1992 08:47:46 +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 3 of 7

-+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+
X`09`09r1, PCB$W_ASTCNT(r4), PHD$W_ASTLM(r5)
X80$:
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=PHDCTL, -
X`09`09outlen=MWAIT_Q_FAODSC(r6), -`09; Format output
X`09`09outbuf=MWAIT_Q_FAODSC(r6), -
X`09`09prmlst=PHD$L_R0(r5)
X`09; Assumption here is that all registers in the PHD are contiguous
X`09blbcw`09r0, 100$
X`09pushaq`09MWAIT_Q_FAODSC(r6)`09`09; Display output
X`09calls`09#1, g`5ELIB$PUT_OUTPUT`09`09; Print the register dump
X`09blbcw`09r0, 100$
X;
X; Attempt to locate the change mode (CHMx) vectors inside of VMS
X;
X`09bbs`09#MWAIT_V_CMVECT, MWAIT_L_FLAGS(r6), 85$
X`09jsb`09g`5ELOCATE_CMVECT`09`09`09; Find the change mode vectors
X85$:
X;
X; Scan the table of places in the executive where RSN$_ASTWAIT can be genera
Vted.
X; We check a range of addresses from a table of the form:
X;
X;`09.address`09descriptive-text
X;`09.long`09`09EXE$xxxx`09; Base address
X;`09.long`09`09value`09`09; Offset within which RWAST will occur
X;`09.long`09`09backoff`09`09; Offset before base address to allow
X;`09.long`09`09action`09`09; Action routine number
X;`09...
X;`09.address`09text`09`09; Default text to use for PC evaluation
X;`09.long`09`090, 0`09`09; End of table
X;
X`09moval`09RWAST_TABLE, r0`09`09`09; R0 => start of RWAST PC table
X90$:`09movl`09(r0)+, r3`09`09`09; R3 => text string
X`09movq`09(r0)+, r1`09`09`09; R1 = start, R2 = end
X`09movq`09(r0)+, r7`09`09`09; R7 = backoff, R8 = action number
X`09tstl`09r1`09`09`09`09; Any start address?
X`09beqluw`0998$`09`09`09`09; Check for end of table
X;
X; Now we have to decode the real address of the selected code path in the
X; executive.
X; There are 4 forms we check for (as all code is vectored):
X;
X; 1.`09Ordinary (base image vectored) system routine.
X;`09Format:`09jmp @#address
X;`09We check for this first as "@#" has a value of `5Ex9F, which
X;`09is an illegal value for an entry mask (for which <13:12> must be zero).
X;
X; 2.`09Base vectored system service routine.
X;`09Format:`09.word`09`5Em<>`09; Entry mask
X;`09`09jmp`09@#address
X;
X; 3./4.`09Change mode entries (system services).
X;`09Format:`09.word`09`5Em<>`09; Entry mask
X;`09`09chme/k`09#index
X;
X`09cmpw`09(r1), #OP$_JMP!<`5Ex9F00>`09`09; Check for JMP @#
X`09bnequ`0991$`09`09`09`09; Branch if not this
X`09movl`092(r1), r1`09`09`09; R1 = real routine address (skip JMP @#)
X`09brw`0997$
X91$:`09cmpw`092(r1), #OP$_JMP!<`5Ex9F00>`09; Check for entry mask + JMP @#
X`09bnequ`0992$`09`09`09`09; Branch if not this
X`09movl`094(r1), r1`09`09`09; R1 = real routine address (skip JMP @#)
X`09brw`0997$
X;
X; Can't do CHMx vector resolution without the vectors.
X;
X92$:`09cmpw`092(r1), #OP$_CHME!<`5Ex8F00>`09; Check for entry mask + CHME #n
Vnnn
X`09bnequ`0994$`09`09`09`09; Branch if not this
X`09bbs`09#MWAIT_V_CHME, MWAIT_L_FLAGS(r6), 93$
X`09brb`0990$
X93$:`09movzwl`094(r1), r1`09`09`09; R1 = CHME code
X`09movaq`09@CMOD$AR_EXEC_DISPATCH_VECTOR`5Br1`5D, r1 ; R1 => dispatch vector
V for real code
X`09movl`09DISP_A_SERVICE_ROUTINE(r1), r1`09; R1 => Real routine address
X`09brb`0997$
X
X94$:`09cmpw`092(r1), #OP$_CHMK!<`5Ex8F00>`09; Check for entry mask + CHMK #n
Vnnn
X`09bnequ`0996$`09`09`09`09; Branch if not this
X`09bbs`09#MWAIT_V_CHMK, MWAIT_L_FLAGS(r6), 95$
X`09brb`0990$
X95$:`09movzwl`094(r1), r1`09`09`09; R1 = CHME code
X`09movaq`09@CMOD$AR_KERNEL_DISPATCH_VECTOR`5Br1`5D, r1 ; R1 => dispatch vect
Vor for real code
X`09movl`09DISP_A_SERVICE_ROUTINE(r1), r1`09; R1 => Real routine address
X`09brb`0997$
X96$:`09printf`09<%MWAIT-W, Illegal vector (not known format) !XL:!/!_'!AS'>,
V-
X`09`09(r1), r3
X`09brw`0990$
X
X97$:
X;printf`09<Vector for '!AS' is !XL>, r3, r1
X`09addl2`09r1, r2`09`09`09`09; R2 = real end address
X`09subl2`09r7, r1`09`09`09`09; Allow backoff if required
X;printf`09< Range is !XL - !XL>, r1, r2
X`09cmpl`09PHD$L_PC(r5), r1`09`09; In range?
X`09blssuw`0990$`09`09`09`09; Branch if not
X`09cmpl`09PHD$L_PC(r5), r2`09`09; In range?
X`09bgtruw`0990$`09`09`09`09; Branch if not
X
X98$:`09tstl`09r1`09`09`09`09; Was any address actually found?
X`09bnequ`0999$`09`09`09`09; Yes, so display it
X`09jsb`09CHECK_DRIVERS`09`09`09; Check for code being in a driver
X;
X; Now add in detail of the states to save some work with SDA.
X;
X99$:`09case`09r8, <1000$,1010$,1020$,1030$,1040$,1050$>
X; Action 0 - do nothing
X1000$:`09$printf`09(r3)`09`09`09`09; Print the message
X`09brw`09100$
X
X; Action 1 - R5 = UCB, R6 = CCB, R7 = channel
X1010$:
X`09mnegw`09PHD$L_R7(r5), r7`09`09; R7 = Real channel number
X`09movl`09PHD$L_R5(r5), r5`09`09; R5 => device UCB
X `09movl`09UCB$L_DDB(r5), r2`09`09; R2 => device DDB
X`09movab`09DDB$T_NAME(r2), r2`09`09; R2 => device name string
X`09$printf`09(r3), r2, UCB$W_UNIT(r5), r7`09; Display formatted details
X`09brw`09100$
X
X; Action 2 - R5 = channel, R6 = CCB
X1020$:
X`09movzwl`09PHD$L_R5(r5), R7`09`09; R7<0:15> = Channel number
X`09$printf`09(r3), r7`09`09`09; Display formatted details
X`09brw`09100$
X
X; Action 3 - R4 = PCB, R5 = UCB, R7 = CCB
X1030$:
X`09movl`09PHD$L_R5(r5), r5`09`09; R5 => device UCB
X `09movl`09UCB$L_DDB(r5), r2`09`09; R2 => device DDB
X`09movab`09DDB$T_NAME(r2), r2`09`09; R2 => device name string
X`09$printf`09(r3), r2, UCB$W_UNIT(r5)`09; Display formatted details
X`09brw`09100$
X
X; Action 4 - R1 = quantity, R2 = address, R3 = width(bits)
X1040$:
X`09movl`09PHD$L_R2(r5), r2`09`09; R2 => Quota field
X`09extzv`09#0, PHD$L_R3(r5), (r2), r1`09; R1 = Current quota value
X`09$printf`09(r3), PHD$L_R1(r5), r1`09`09; Display formatted details
X;
X; Check for a few common addresses to isolate the problem
X;
X`09movaw`09PCB$W_DIOCNT(r4), r1`09`09; R1 => DIO count field
X`09cmpl`09PHD$L_R2(r5), r1`09`09; Is this the one?
X`09bnequ`091042$`09`09`09`09; No, its not
X`09printf`09<!_Quota wait on: Direct I/Os remaining count (DIOCNT: !UW.)>,-
X`09`09PCB$W_DIOCNT(r4)
X`09brw`09100$`09`09`09`09; Exit
X1042$:
X`09movaw`09PCB$W_BIOCNT(r4), r1`09`09; R1 => BIO count field
X`09cmpl`09PHD$L_R2(r5), r1`09`09; Is this the one?
X`09bnequ`091044$`09`09`09`09; No, its not
X`09printf`09<!_Quota wait on: Buffered I/Os remaining count (BIOCNT: !UW.)>,
V-
X`09`09PCB$W_BIOCNT(r4)
X`09brw`09100$`09`09`09`09; Exit
X1044$:
X`09movaw`09PCB$W_ASTCNT(r4), r1`09`09; R1 => AST count field
X`09cmpl`09PHD$L_R2(r5), r1`09`09; Is this the one?
X`09bnequ`091046$`09`09`09`09; No, its not
X`09printf`09<!_Quota wait on: ASTs remaining count (ASTCNT: !UW.)>,-
X`09`09PCB$W_ASTCNT(r4)
X`09brb`09100$`09`09`09`09; Exit
X1046$:
X`09brb`09100$
X
X; Action 5 - Identified driver, R1 => DPT
X1050$:`09subl3`09r1, PHD$L_PC(r5), r2`09`09; R2 = offset within driver
X`09movab`09DPT$T_NAME(r1), r1`09`09; R1 => driver name string
X`09printf <!_PC is at !AC+!XW>, r1, r2
X;`09brb`09100$
X
X100$:`09rsb
X
X`09.disable`09local_block
X`0C
X`09.subtitle`09CHECK_DRIVERS`09Check if PC lies in a driver
X;+
X; CHECK_DRIVERS
X;
X; Description:
X;
X;`09This routine scans the table of device drivers to see if the PC
X;`09we want to match lies in the driver.
X;
X; Inputs:
X;
X;`09R3`09=> Default text
X;`09R4`09=> PCB of process
X;`09R5`09=> PHD of process
X;`09R6`09=> Internal stack
X;
X; Outputs:
X;
X;`09R1/R2`09trashed
X;`09R3`09=> Default text
X;`09R4`09=> PCB of process
X;`09R5`09=> PHD of process
X;`09R6`09=> Internal stack
X;`09R8`09=  0 (no driver match found)
X;`09`09=  5 (match found...)
X;`09`09   R1 => DPT of located driver
X;
X; Notes:
X;
X;-
X`09.enable`09local_block
X
XCHECK_DRIVERS:
X`09clrl`09r8`09`09`09`09; Assume nothing found
X`09movl`09g`5EIOC$GL_DPTLIST, r1`09`09; R1 => first driver DPT
X10$:`09movzwl`09DPT$W_SIZE(r1), r2`09`09; R2 = length of driver
X`09addl2`09r1, r2`09`09`09`09; R2 => end of driver
X;movab`09DPT$T_NAME(r1), r7
X;printf`09<!_!40AC Start: !XL, End: !XL>, r7, r1, r2
X`09cmpl`09PHD$L_PC(r5), r1`09`09; In range?
X`09blssu`0920$`09`09`09`09; Branch if not
X`09cmpl`09PHD$L_PC(r5), r2`09`09; In range?
X`09bgequ`0920$`09`09`09`09; Branch if not
X`09movl`09#5, r8`09`09`09`09; R8 = DPT format index
X`09brb`09100$`09`09`09`09; ...and exit
X
X20$:`09movl`09DPT$L_FLINK(r1), r1`09`09; R1 => next DPT in list
X`09cmpl`09r1, #IOC$GL_DPTLIST`09`09; At end yet?
X`09bnequ`0910$`09`09`09`09; Go round if not at end
X
X100$:`09rsb
X
X`09.disable`09local_block
X`0C
X`09.subtitle`09PROCESS_RWMBX`09Analyse RWMBX condition
X;+
X; PROCESS_RWMBX
X;
X; Description:
X;
X;`09This routine is called when a process that is in RWMBX is scanned.
X;`09The code attempts to determine the identification of the mailbox
X;`09or device causing the problem.
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_RWMBX:
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`09movl`09PCB$L_PHD(r4), r0`09`09; R0 => PHD
X`09movl`09PHD$L_R3(r0), r3`09`09; R3 => IRP for write request
X`09movl`09PHD$L_R5(r0), r5`09`09; R5 => UCB for mailbox
X`09movl`09UCB$L_DDB(r5), r2`09`09; R2 => device DDB
X`09movab`09DDB$T_NAME(r2), r2`09`09; R2 => device name string
X`09mnegw`09IRP$W_CHAN(r3), r1`09`09; R1 =  Channel number
X`09printf`09<!_Attempting to write !UW. byte!%S to !AC!UW: on channel !XW (h
Vex)>,-
X`09`09IRP$W_BCNT(r3), r2, UCB$W_UNIT(r5), r1
X`09printf`09<!_!0UWMessage!%S: !-!UW., Quota (bytes): Initial = !UW., Remain
Ving = !UW.>,-
X`09`09UCB$W_MSGCNT(r5), UCB$W_INIQUO(r5), UCB$W_BUFQUO(r5)
X100$:`09rsb
X`09.disable`09local_block
X`0C
X`09.subtitle`09PROCESS_JIBWAIT`09Analyse a JIB wait condition
X;+
X; PROCESS_JIBWAIT
X;
X; Description:
X;
X;`09This routine is called when a process that is in a JIB quota related
X;`09wait 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_JIBWAIT:
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`09movl`09PCB$L_JIB(r4), r3`09`09; R3 => JIB
X`09beqluw`09100$`09`09`09`09; Paranoia!
X
X`09bbc`09#JIB$V_BYTCNT_WAITERS, JIB$B_FLAGS(r3), 10$
X`09print`09<`09Job buffered I/O count exhausted>
X`09clrl`09r1`09`09`09`09; Assume we cannot find size
X`09bbc`09#PCB$V_PHDRES, PCB$L_STS(r4), 05$ ; Only check PHD if resident
X`09movl`09PCB$L_PHD(r4), r1`09`09; R1 => PHD
X`09movl`09PHD$L_R1(r1), r1`09`09; R1 = amount requested
X05$:`09printf`09<!_(Requested: !UL. byte!%S, Available: !UL. byte!%S, Quota:
V !UL.)>,-
X`09`09r1, JIB$L_BYTCNT(r3), JIB$L_BYTLM(r3)
X10$:
X`09tstw`09JIB$W_FILCNT(r3)`09`09; Any files left?
X`09bnequ`0920$
X`09print`09<`09Job open file count exhausted (FILCNT zero)>
X20$:
X`09bbc`09#JIB$V_TQCNT_WAITERS, JIB$B_FLAGS(r3), 30$
X`09printf`09<!_Job timer count exhausted (TQCNT: !UW. TQLM: !UW.)>,-
X`09`09JIB$W_TQCNT(r3), JIB$W_TQLM(r3)
X30$:
X`09tstl`09JIB$L_PGFLCNT(r3)`09`09; Any page file space?
X`09bnequ`0940$
X`09print`09<`09Job page file space exhausted (PGFLCNT zero)>
X40$:
X
X100$:`09rsb
X
X`09.disable`09local_block
X`0C
X`09.subtitle`09LOCATE_CMVECT`09Locate the change mode vectors
X;+
X; LOCATE_CMVECT
X;
X; Description:
X;
X;`09This routine is called to locate the change mode (CHMx) vectors in
X;`09the appropriate executive loadable image (EXCEPTION.EXE).
X;`09The loadable image list is scanned to locate EXCEPTION.EXE. When found,
X;`09we search through the "read-only" non-paged pool base for the
X;`09"signature" of the CHME and CHMK vectors. We do a search because this
X;`09code must be able to work with any version of VMS V5, and the previous
X;`09method of using fixed offsets was a loser!
X;
X;`09Once we have the addresses of the CHME and CHMK vectors, we can get the
X;`09address of the *real* routines from DISP_A_SERVICE_ROUTINE
X;
X;`09We have to use the change mode vectors to locate the real code for
X;`09system services as the CHMx numbers are allocated dynamically as the
X;`09services are loaded, and it is therefore uncertain which entry a
X;`09particular service will use.
X;
X; Inputs:
X;
X;`09R6`09=> Internal stack
X;
X; Outputs:
X;
X;`09R8-R11`09destroyed
X;
X;`09MWAIT_M_CMVECT is set in MWAIT_L_FLAGS.
X;`09MWAIT_M_CHMK is set if we located the change mode to kernel vector
X;`09MWAIT_M_CHME ''  '' '' ''    ''   ''    ''    ''  '' executive ''
X;
X;`09CMOD$AR_KERNEL_DISPATCH_VECTOR`09CHMK dispatch vector address
X;`09CMOD$AR_EXEC_DISPATCH_VECTOR`09CHME    ''      ''     ''
X;`09
X; Notes:
X;
X;-
X`09.enable`09local_block
X
XLOCATE_CMVECT:
X`09bisl`09#MWAIT_M_CMVECT, MWAIT_L_FLAGS(r6) ; Say we have looked
X`09bicl`09#<MWAIT_M_CHMK!MWAIT_M_CHME>, MWAIT_L_FLAGS(r6)
X`09movab`09EXCEPTION, r8`09`09`09; R8 => exception image name
X`09movzbl`09(r8)+, r9`09`09`09; R9 = image name length
X`09movaq`09g`5ELDR$GQ_IMAGE_LIST, r10`09; R10 => list header
X`09movl`09r10, r11`09`09`09; R11 => list header
XASSUME`09LDRIMG$L_FLINK eq 0
X10$:`09movl`09LDRIMG$L_FLINK(r10), r10`09; R10 => 1st loadable image block
X`09cmpl`09r10, r11`09`09`09; End of list?
X`09bnequ`0920$
X`09printf`09<%MWAIT-W, Failed to locate image !AC>, EXCEPTION
X`09brw`09100$
X20$:`09cmpb`09r9, LDRIMG$B_IMGNAMLEN(r10)`09; Same length?
X`09bnequ`0910$`09`09`09`09; No
X`09cmpc3`09r9, (r8), LDRIMG$T_IMGNAM(r10)`09; Same text?
X`09bnequ`0910$`09`09`09`09; Branch if no
X
X`09movl`09LDRIMG$L_NONPAG_R_BASE(r10), r11 ; R11 => Base of area to search
X`09moval`09MAX_VECTOR_OFFSET(r11), r9`09; R9 => end of range to search
X25$:`09cmpl`09r11, r9`09`09`09`09; At end yet?
X`09bgtru`0930$`09`09`09`09; Branch if yes
X`09cmpl`09KERNEL_CHECK, (r11)`09`09; Check that its the right vector
X`09bnequ`0927$
X`09cmpl`09KERNEL_CHECK+4, 4(r11)
X`09bnequ`0927$
X`09cmpl`09KERNEL_CHECK+8, 8(r11)
X`09bnequ`0927$
X`09movl`09r11, CMOD$AR_KERNEL_DISPATCH_VECTOR
+-+-+-+-+-+-+-+-  END  OF PART 3 +-+-+-+-+-+-+-+-

