From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  7-JUL-1990 18:08:22.59
To:	MRGATE::"ARISIA::EVERHART"
CC:	
Subj:	Re: Global pointers to process queue's

Received:  by crdgw1.ge.com (5.57/GE 1.70)
	 id AA01672; Sat, 7 Jul 90 17:04:27 EDT
Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Fri,  6 JUL 90 21:51:11 PDT
Received: by ucbvax.Berkeley.EDU (5.63/1.41)
	id AA04599; Fri, 6 Jul 90 21:35:48 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 6 Jul 90 20:06:42 GMT
From: crash!simpact!jeh@nosc.mil
Organization: Simpact Associates, San Diego CA
Subject: Re: Global pointers to process queue's
Message-Id: <1442.26948ce2@dcs.simpact.com>
References: <1943@vela.acs.oakland.edu>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

In article <1943@vela.acs.oakland.edu>, tarcea@vela.acs.oakland.edu 
 (The OUTLAWS) writes:
>   I need to find all the process PHD's on our system. 

Hmm.  Do I really want to help someone with a personal name of "The OUTLAWS"?

> The way I figured I
> would do this is to go to the SCH$GL_xxx queues and trace back from there
> thru the pointer contained in each PCB found there.  The problem I am having
> is that I do not know the names of all the queue's, for instance I know the
> computable queue is located at G^SCH$GL_COMQS...

No no no.  First, SCH$GL_COMQS is not a queue header but a queue summary 
longword; bits in this longword indicate which of the *32* queues for 
computable processes are nonempty.  

Anyway there is a much simpler way to find all of the processes in the system.
SCH$GL_PCBVEC contains the base address of an array of longwords, size
MAXPROCESSCNT.  This array in turn contains the PCB addresses of all processes
in the system.  The array indices are the process indexes -- the low bits of
the PID.  Unused entries in the array contain the address of the null process's
PCB (yes, it's still there in V5, it's just never scheduled).  

The following code works under V4 *or* V5 .  

	; initialization 

	MOVL	G^SCH$GL_MAXPIX, R2	; R2 = max process index (MAXPRCCNT-1)
	MOVL	G^SCH$GL_PCBVEC, R3	; R3 points to PCBVEC
.if defined v4
	MOVAL	G^SCH$GL_NULLPCB, R6	; R6 has addr of null process's PCB
.if_false
	MOVL	G^SCH$AR_NULLPCB, R6	; R6 has addr of null process's PCB
.endc

PROC_LOOP:
	MOVL	(R3)[R2], R4		; R4 points to a PCB
	CMPL	R4, R6			; are we looking at an unused slot?
	BEQL	10$			;  br if yes

	MOVL	PCB$L_xxx(R4), ...	;  look at the process

10$:	SOBGEQ	R2, PROC_LOOP		; continue thru R2=0

	;  all done

Now, isn't that better than scanning upteen different queues???

Naturally you want to do this in an appropriate synch context (hold the
SCHED spinlock) so that things don't change out from under you.  This is 
especially important if you're looking at process headers.  While a 
process's PCB address is constant throughout its life, its PHD address 
might change.  An outswapped process's PHD may not even be in memory.  
You have to look at the PCB to see if the PHD is accessible, and execute
all code that looks at the PHD in a context that ensures that the PHD won't
move out from under you.  $GETJPI does this by sending a special kernel
AST to the process in question.  

	--- Jamie Hanrahan, Simpact Associates, San Diego CA
Chair, VMSnet [DECUS uucp] and Internals Working Groups, DECUS VAX Systems SIG 
Internet:  jeh@dcs.simpact.com, or if that fails, jeh@crash.cts.com
Uucp:  ...{crash,scubed,decwrl}!simpact!jeh

