From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  6-OCT-1989 11:12
To:	MRGATE::"ARISIA::EVERHART"
Subj:	PROCESS_DUMP (DUMP/PROCESS/IDENT=xxx utility) 2/4

Message-Id:  <8910061334.AA02448@crdgw1.ge.com>
Received: From NSFNET-RELAY.AC.UK by CRVAX.SRI.COM with TCP; Fri,  6 OCT 89 05:38:29 PDT
Received: from ncdlab.ulcc.ac.uk by NSFnet-Relay.AC.UK   via Janet with NIFTP
           id aa04080; 6 Oct 89 12:11 BST
Date:           Fri, 6 Oct 89  12:11 BST
From: Nick de Smith <"PSI%JANET.000000000040::NICK%ncdlab.ulcc.ac.uk"@NSFnet-Relay.AC.UK>
To: INFO-VAX <@NSFnet-Relay.AC.UK:INFO-VAX@crvax.sri.com>
Subject:        PROCESS_DUMP (DUMP/PROCESS/IDENT=xxx utility) 2/4

-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
X`009`009movab`009<ast_code>, ACB$L_xAST(r5) ; Set the AST address
X`009`009movl`009#PRI$_xxx, r2`009`009; SCH$QAST needs priority boost in R2
X`009`009jsb`009g`094SCH$QAST`009`009; Queue the AST
X
XThis piece of code is simplistic. It would probably work in some/most situat
Vions. There again, it will crash
Xyour system in some situations too! See K_AST.MAR for a better (definitive?)
V treatment.
X
X`091end`093
$ CALL UNPACK [.PDUMP]AST.TXT;1 823869665
$ create/nolog 'f'
X$`009Setv = F$Verify("Yes")
X$!
X$`009Delete`009= "Delete/Log"
X$`009Macro`009= "Macro/Debug"
X$`009Link`009= "Link"
X$!
X$`009Macro K_AST
X$`009Macro K_MAIN
X$`009Macro PDUMP
X$`009Link PDUMP,K_MAIN,K_AST
X$`009Delete PDUMP.OBJ;
X$!
X$`009Setv = 'F$Verify(Setv)
$ CALL UNPACK [.PDUMP]BUILD.COM;1 909806105
$ create/nolog 'f'
X.title`009K_AST`009Deliver a "special KERNEL mode AST"
X;++
X; K_AST
X;
X; Author:`009Nick de Smith
X;`009`009Applied Telematics Services, 7 Vale Avenue
X;`009`009Tunbridge Wells, Kent TN1 1DJ, England.
X;`009`009+44 892 511000, PSI%234213300154::NICK
X; Date  :`00905-May-87, 19-Dec-88
X;
X; Copyright (c) 1987,1988,1989 by Applied Telematics Group Limited and Nick
V de Smith.
X; This software is supplied for information only. No guarantee is supplied f
Vor
X; this software, and no liability will be accepted for any action resulting
V from
X; the use of this software or the information contained herein. Under no
X; circumstances may this software be used for commercial gain, including its
X; sale, lease or loan. This software may be copied only with the inclusion o
Vf
X; this copyright notice. The author is prepared to enter into correspondance
X; with interested parties, but will not necessarily maintain this software.
X; Having said all that, enjoy it!`032
X;
X; Description:
X;
X; This routine runs in KERNEL mode to deliver a special KERNEL mode AST to
X; the target process.
X;
X;`009`009***********************************
X; You should not need to modify this module - It is common to all programs
X; that deliver special kernel mode ASTs.
X;`009`009***********************************
X;
X; The code to execute in the context of the target process is placed in
X; a separate module (whose template is AST_TEMPLATE.MAR).
X; The technique used is to place your code at the end of an extended ACB.
X; The front of the ACB contains the delivery information and is set up by
X; QUEUE_KERNEL_AST below. This routine also copies AST_LENGTH bytes from
X; AST_CODE into the ACB, which it then queues as a special KERNEL mode AST.
X; Note that this technique will only work for special KERNEL mode ASTs and
X; for normal ASTs that have a "piggy-back" special KERNEL mode AST. In all
X; other cases, the AST delivery code (in ASTDEL) deallocates the ACB before
X; calling the AST routine. Therefore we would be executing code in a region
X; of non-paged pool that was on the free list. Danger! Danger! See AST.TXT
X; for a discussion on different types of ASTs.
X;
X; Edit`009Edit date`009By`009Why
X;  02`00901-Mar-89`009NMdS`009Upgrade to use new page locking macros.
X; 2.01`00919-Dec-88`009NMdS`009VMS V5, make into a template.
X;  01`00905-May-87`009NMdS`009First attempt
X;
X;--
X.ident`009/V02.02/
X
X.library`009"SYS$LIBRARY:LIB"
X.link`009`009"SYS$SYSTEM:SYS.STB" /Selective_Search ; Save typing later
X
X`009$acbdef`009`009`009`009; AST Control Block definitions
X`009$cpudef`009`009`009`009; Define CPU block offsets
X`009$dyndef`009`009`009`009; Data structure type codes
X`009$ipldef`009`009`009`009; Synchronization IPL values
X`009$pcbdef`009`009`009`009; Software PCB fields
X`009$pridef`009`009`009`009; Priority boost classes
X`009$psldef`009`009`009`009; Fields in PSL
X`009$sfdef`009`009`009`009; Saved frame offsets
X`009$ssdef`009`009`009`009; Define system statii
X`009$statedef`009`009`009; Scheduler definitions
X;
X; The following symbols define the location of the user's AST code.
X; See the user template, AST_TEMPLATE.MAR for an explanation.
X;
X.global`009ACB_K_NEW_LENGTH`009`009; Length of user's extended ACB
X.global`009ACB_T_AST_CODE`009`009`009; Where to put user's code in ACB
X.global`009AST_CODE`009`009`009; Address of user's AST code
X.global`009AST_CODE_LENGTH`009`009`009; Length of user's AST code
X`012
X.subtitle QUEUE_KERNEL_AST`009Queue a KERNEL mode AST to another process
X;++
X; QUEUE_KERNEL_AST`009Queue an AST to a target process
X;
X; Calling sequence:
X;
X; K_ARGS:.long`0092`009`009`009; $CMKRNL argument list
X;`009.address EPID`009`009`009; => Target PID to deliver AST to
X;`009.address PRCNAM_DESC`009`009; => Process name descriptor
X;
X;`009$cmkrnl_s`009`009 -`009; Queue the AST
X;`009`009routin = QUEUE_KERNEL_AST,- ; Routine to call
X;`009`009arglst = K_ARGS`009`009; Argument list
X;
X; Input Parameters:
X;
X;`009R4`009=> Caller's PCB (left there by the change mode dispatcher)
X;`0094(ap)`009=> Target process ID
X;`0098(ap)`009=> Target process name descriptor. Used if 4(ap) = 0.
X;
X; EXE$NAMPID converts a PID or process name into an EPID, IPID and PCB addre
Vss:
X;`009Requires:
X;`009`009R4`009=> Caller's PCB (for privilege checks)
X;`009`009@4(AP)`009=  PID to look up (in any format)
X;`009`0098(AP)`009=> Descriptor of process name to look up. Only used
X;`009`009`009   if 4(ap) = 0.
X;`009Returns:
X;`009`009R0`009=  Completion status
X;`009`009R1`009=  IPID of target process, 0 if not found
X;`009`009R4`009=> PCB of target process (if found)
X;`009`009@4(AP)`009=  EPID of target process (if found)
X;`009`009spinlock`009SYNCH for success,
X;`009`009`009`009IPL$_ASTDEL for failure
X;--
X.Entry`009QUEUE_KERNEL_AST, `094m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
X
X`009movab`009g`094EXE$SIGTORET, SF$A_HANDLER(fp) ; Set KERNEL mode exception
V handler
X`009pushr`009#`094m<r4>`009`009`009; Save our PCB address (popped as R6 late
Vr)
X;
X; Get process ID of target process. We use EXE$NAMPID as it provides
X; access control checks (but don't call it at or above IPL$_SYNCH as
X; it probes and modifies its argument list, which might incur a page fault).
X; Because EXE$NAMPID can return at an elevated IPL (above ASTDEL) we must lo
Vck
X; down the call to it because there is a chance (however slight) that we wil
Vl
X; page fault before we can unlock the SCHED spinlock.
X;
X5$:`009SETIPL`00915$,-`009`009`009; Lock down the following code
X`009`009environ = UNIPROCESSOR
X`009jsb`009g`094EXE$NAMPID`009`009; Returns with spinlock SCHED, or IPL$_AST
VDEL
X`009blbs`009r0, 10$`009`009`009;; Branch if PID was valid and we have access
X`009SETIPL`009#0`009`009`009;; Drop IPL from ASTDEL
X`009ret`009`009`009`009; Return to caller
X
X10$:`009UNLOCK`009SCHED`009`009,-`009;; Remove SCHED spinlock
X`009`009newipl`009= #0`009,-`009;; ...and drop elevated IPL
X`009`009preserve= NO`009`009;; ...but don't save R0
X`009cmpl`009r1, g`094SCH$GL_SWPPID`009; NULL and SWAPPER are illegal
X`009bgtru`00920$`009`009`009; Branch if we have a valid IPID
X`009movzwl`009#SS$_NONEXPR, r0`009; Say "Non existant process"
X`009ret
X15$:`009.long`009IPL$_SCHED
X`009ASSUME`009<.-5$> Le 512`009`009; Locked data area > 1 page
X;
X; Now allocate an AST control block and store the relevant parameters
X;
X20$:`009movl`009#ACB_K_NEW_LENGTH, r1`009; Set size of extended ACB
X`009jsb`009g`094EXE$ALONONPAGED`009; Allocate nonpaged pool space
X`009blbs`009r0, 30$`009`009`009; Continue if there was no error
X`009ret`009`009`009`009; Error, so return to caller
X
X30$:`009movl`009r2, r5`009`009`009; R5 => New ACB
X`009movb`009#DYN$C_ACB, ACB$B_TYPE(r5) ; Say block is an ACB
X`009movw`009r1, ACB$W_SIZE(r5)`009; Store size of structure`009
X`009movl`009PCB$L_PID(r4), ACB$L_PID(r5) ; Store PID of target process
X`009movpsl`009r1`009`009`009; Get the current PSL
X`009extzv`009#PSL$V_PRVMOD, #PSL$S_PRVMOD, r1, r1`009; R1 = caller's access
V mode
X`009bisb3`009#<1@ACB$V_KAST>, r1, ACB$B_RMOD(r5)`009; and store it in ACB
X`009movab`009ACB_T_AST_CODE(r5), ACB$L_KAST(r5)`009; Set the AST address
X
X`009popr`009#`094m<r6>`009`009`009; R6 => caller's PCB
X;
X; Fill in the extended ACB fields
X; R4 => Target process's PCB
X; R5 => Allocated ACB
X; R6 => Caller's process PCB
X;
X`009movl`009PCB$L_PID(r6), ACB_L_SPID(r5) ; Store PID of source process
X`009pushr`009#`094m<r4,r5>`009`009; Save registers
X`009movc3`009#AST_LENGTH, AST_CODE, ACB_T_AST_CODE(r5) ; Copy AST code into
V the ACB
X`009popr`009#`094m<r4,r5>`009`009; Restore registers
X;
X; Ready to queue the AST to the target process.
X; Note that the following code is rigorous. You don't need to check if the
X; target PCB is that same as the NULL job PCB and that the PIDs are differen
Vt
X; - the latter test on its own would be sufficient. Also we carry out all
X; possible checks (I think). A fair chunk of the code could be omitted, but
X; "when in KERNEL mode, play safe".
X; In theory we could deliver an AST to a process in MWAIT, but if the proces
Vs
X; is that far down the line, it has enough problems (if its in MWAIT, by the
X; time it comes out, and can service the AST, most of the interesting data
X; would be lost - use SDA in such situations).
X;
XLOCKED_START:
X`009SETIPL`009LOCKED_END,-`009`009; Stop page faults in following code
X`009`009environ = UNIPROCESSOR
X`009LOCK`009SCHED`009`009,-`009;; Lock the database
X`009`009preserve= NO`009`009;; ...but don't save R0
X`009cmpl`009PCB$L_PID(r4), ACB$L_PID(r5) ;; Are PIDs the same?
X`009bneq`009no_process`009`009;; Error if not (process has gone away)
X`009bbs`009#PCB$V_DELPEN, PCB$L_STS(r4), no_process ;; Check if being delete
Vd`009
X`009bbs`009#PCB$V_SUSPEN, PCB$L_STS(r4), suspended ;; Check if suspend pendi
Vng`009
X`009cmpw`009#SCH$C_SUSP, PCB$W_STATE(r4) ;; Check if already suspended
X`009beql`009suspended`009`009;; ...error if it is
X`009cmpw`009#SCH$C_SUSPO, PCB$W_STATE(r4) ;; ...or suspended, outswapped
X`009beql`009suspended`009`009;; ...error if it is
X`009cmpw`009#SCH$C_MWAIT, PCB$W_STATE(r4) ;; ...or (possibly) long wait
X`009beql`009suspended`009`009;; ...error if it is
X`009movl`009#PRI$_TICOM, r2`009`009;; SCH$QAST needs priority boost in R2
X`009jsb`009g`094SCH$QAST`009`009;; Queue the AST
X;
X; If the target process is in COM, COMO, SUSP or SUSPO and at a lower priori
Vty
X; than the current process, boost the target process's current priority to t
Vhe
X; current process's current priority. This is required because SCH$RSE (in R
VSE)
X; will ignore EVT$_AST type events if the target process is in one of COM, C
VOMO,
X; SUSP or SUSPO, and therefore the target might not run (if we continue). No
Vte
X; also that we must not boost into the realtime priority band, as the schedu
Vler
X; will never subsequently lower the priority again. If the process was in an
Vy
X; SUSPx state we would not have got this far anyway.
X;
X`009cmpw`009#SCH$C_COM, PCB$W_STATE(r4) ;; Is process in COM state?
X`009beql`00910$`009`009`009;; ...yes, so boost it
X`009cmpw`009#SCH$C_COMO, PCB$W_STATE(r4) ;; What about COMO?
X`009bneq`00920$`009`009`009;; ...no, so ignore this one
X10$:
X;
X; We can't use CTL$GL_PCB to get the current PCB because, although we have
X; access to the process P1 space, we are now at IPL$_SYNCH, and a page fault
X; here would crash the system.
X;
X`009movb`009PCB$B_PRI(r6), r0`009;; R0 = our current priority
X;
X; As priorities are stored in the PCB in inverted format (eg. a value of 0
X; is a priority of 31), then the larger the value in the PCB, the lower the
X; priority. This is why the following test appears to be the wrong way round
V.
X; It is, in fact, correct.
X;
X`009cmpb`009r0, PCB$B_PRI(r4)`009;; Is target's priority higher?
X`009bgequ`00920$`009`009`009;; ...yes, so quit
X`009cmpb`009#16, r0`009`009`009;; Will boost be into "realtime"?
X`009bgtru`00920$`009`009`009;; ...yes, so don't boost
X`009jsb`009g`094SCH$CHSEP`009`009;; Boost target's priority
X20$:`009UNLOCK`009SCHED`009`009,-`009;; Unlock the database
X`009`009newipl`009= #0`009,-`009; ...force drop in IPL
X`009`009preserve= NO`009`009; ...don't keep R0
X`009movzwl`009#SS$_NORMAL, r0`009`009; Say we did everything
X`009ret`009`009`009`009; Return to caller
X;
X; Process has gone away or is unavailable. Deallocate ACB and return through
X; common exit path.
X;
X`009.enable`009LSB
XNO_PROCESS:
X`009pushl`009#SS$_NONEXPR`009`009;; This is error if process has gone away
X`009brb`00910$
XSUSPENDED:
X`009pushl`009#SS$_SUSPENDED`009`009;; Error if process is suspended
X10$:`009UNLOCK`009SCHED`009`009,-`009;; Remove spinlock
X`009`009newipl`009= #0`009,-`009; ...and remove elevated IPL
X`009`009preserve= NO`009`009; ...don't save R0
X`009movl`009r5, r0`009`009`009; Get address of pool to be deallocated
X`009jsb`009g`094EXE$DEANONPAGED`009; Deallocate the ACB
X`009popl`009r0`009`009`009; Restore status
X`009ret`009`009`009`009; ...and return
XLOCKED_END:`009`009`009`009; End of locked pages
X`009.long`009IPL$_SCHED
X`009ASSUME`009<.-LOCKED_START> le 512`009; Locked data area > 1 page
X
X`009.end
$ CALL UNPACK [.PDUMP]K_AST.MAR;1 355381088
$ create/nolog 'f'
X.title`009`009K_MAIN`009Default main program for KERNEL ASTs
X.subtitle`009Default main program
X;++
X; K_MAIN
X;
X; Author:`009Nick de Smith
X; Date  :`00919-Dec-88
X;
X; Description:
X;
X; This is a default main program for calling the user written KERNEL mode
X; AST code. Normally, this routine will do as the main routine.
X;`032
X;`009$ MACRO AST_TEMPLATE
X;`009$ LINK AST_TEMPLATE,K_MAIN,K_AST
X;`009$ RUN AST_TEMPLATE`009! Requires CMKRNL (surprise!)
X;
X; Edit`009Edit date`009By`009Why
X; 2.01`00919-Dec-88`009NMdS`009VMS V5, integrate with common AST code.
X;--
X.ident`009/V02.01/
X
X`009.psect`009$DATA`009Rd, Wrt, NoExe, Pic, Long
X
XEPID_DESC:`009`009`009`009; Descriptor for ascii PID
X`009.ascid`009-               -`009; 15 characters
XEPID:`009.long`0090`009`009`009; Binary PID of target process
XPID_PROMPT:`009`009`009`009; Prompt to use for PID
X`009.ascid`009-_Target PID: -
X
XK_ARGS:`009.long`0092`009`009`009; $CMKRNL argument list
X`009.address EPID`009`009`009; Target PID to deliver AST to
X`009.address EPID_DESC`009`009; Process name descriptor
X`012
X.subtitle`009K_MAIN`009Main program
X;++
X; K_MAIN`009Main program for queing ASTs to another process.
X;
X; This routine provides a template main routine for programs calling
X; K_AST to deliver special KERNEL mode ASTs to a target process.
X;
X; This routine:
X;`009- Gets the target PID from the user
X;`009- Converts PID into binary. If the supplied PID cannot be
+-+-+-+-+-+-+-+-  END  OF PART 2 +-+-+-+-+-+-+-+-

