From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 24-JUL-1989 21:47
To:	MRGATE::"ARISIA::EVERHART"
Subj:	Routine: CPU idle time under VMS V5

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Mon, 24 JUL 89 17:34:47 PDT
Received: from hac2arpa.hac.com by KL.SRI.COM with TCP; Mon, 24 Jul 89 17:15:15 PDT
Received: from [128.152.50.2] by hac2arpa.hac.com (5.59/SMI-DDN)
	id AA04684; Mon, 24 Jul 89 17:15:22 PDT
Resent-From: @ENGVAX.SCG.hac.com:SBAILEY@DOMINOES.UUCP
Resent-Message-Id: <8907250015.AA04684@hac2arpa.hac.com>
Message-Id: <8907250015.AA04684@hac2arpa.hac.com>
Received: from DOMINOES.UUCP by ENGVAX.SCG.HAC.COM; Mon, 24 Jul 89 14:56 PDT
Date: Mon, 24 Jul 89 12:43 PDT
From: Scott Bailey <@ENGVAX.SCG.hac.com:SBAILEY@DOMINOES.UUCP>
Subject: Routine: CPU idle time under VMS V5
To: info-vax-submit@ENGVAX.SCG.hac.com
X-Vms-To: INFO-VAX-SUBMIT
Resent-Date: Mon, 24 Jul 89 16:50 PDT
Resent-To: info-vax%kl.sri.com@hac2arpa.hac.com

I'm posting this to the net because I've seen a number of requests for this go
by recently...  Appended to this message is a routine, CPUIDLE.MAR, which finds
the amount of idle time since system boot for a VMS V5 system.  It's fairly
simpleminded (see comments in the code) but works great for uniprocessor
systems and should :-) work fine for nonpathological SMP systems, too.

Cheers,

  Scott Bailey                    Arpa:   SBailey.ESGSDWCO@Xerox.COM
  VAX Systems Manager             BITNET: SCOTT@HMCVAX
  Xerox Corp. RE/GSD/WCO          Phone:  213 / 333-5441

$! ------------------ CUT HERE -----------------------
$!
$! This archive created by VMS_SHARE Version 7.1-001  26-JUN-1989
$!   On 24-JUL-1989 12:39:27.38   By user SBAILEY 
$!
$! This VMS_SHARE Written by:
$!    Andy Harper, Kings College London UK
$!
$! Acknowledgements to:
$!    James Gray       - Original VMS_SHARE
$!    Michael Bednarek - Original Concept and implementation
$!
$! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER
$! AND EXECUTE AS A COMMAND PROCEDURE  (  @name  )
$!
$! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING:
$!       1. CPUIDLE.MAR;1
$!
$f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID"))
$e="write sys$error  ""%UNPACK"", "
$w="write sys$output ""%UNPACK"", "
$ if f$trnlnm("SHARE_LOG") then $ w = "!"
$ if f$getsyi("version") .ges. "4.4" then $ goto START
$ e "-E-OLDVER, Must run at least VMS 4.4"
$ exit 44
$UNPACK: SUBROUTINE ! P1=filename, P2=checksum
$ if f$search(P1) .eqs. "" then $ goto file_absent
$ e "-W-EXISTS, File ''P1' exists. Skipped."
$ delete/nolog 'f'*
$ exit
$file_absent:
$ if f$parse(P1) .nes. "" then $ goto dirok
$ dn=f$parse(P1,,,"DIRECTORY")
$ w "-I-CREDIR, Creating directory ''dn'."
$ create/dir 'dn'
$ if $status then $ goto dirok
$ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped."
$ delete/nolog 'f'*
$ exit
$dirok:
$ w "-I-PROCESS, Processing file ''P1'."
$ define/user sys$output nl:
$ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1'
PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET(
SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");
buff:=CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(buff))
;LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION(
BEGINNING_OF(buff));g:=0;LOOP EXITIF MARK(NONE)=END_OF(buff);x:=
ERASE_CHARACTER(1);IF g = 0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x=
"V" THEN APPEND_LINE;MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;
IF x="+" THEN g:=1;ERASE_LINE;ENDIF;ELSE IF x="-" THEN g:=0;ENDIF;ERASE_LINE;
ENDIF;ENDLOOP;p:="`";POSITION(BEGINNING_OF(buff));LOOP r:=SEARCH(p,FORWARD);
EXITIF r=0;POSITION(r);ERASE(r);COPY_TEXT(ASCII(INT(ERASE_CHARACTER(3))));
ENDLOOP;o:=GET_INFO(COMMAND_LINE,"output_file");WRITE_FILE(buff,o);
ENDPROCEDURE;Unpacker;EXIT;
$ delete/nolog 'f'*
$ CHECKSUM 'P1'
$ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT
$ e "-E-CHKSMFAIL, Checksum of ''P1' failed."
$ ENDSUBROUTINE
$START:
$ create/nolog 'f'
X;  +------------------------------------------------------------------------
V---+
X;  `124`009`009`009`009`009`009`009`009`009       `124
X;  `124  UTIL$ROOT:`091PERFMON`093CPUIDLE.MAR`009`009      Calculate CPU Idl
Ve Time  `124
X;  `124  Scott Bailey, Xerox Corp. RE/GSD/WCO`009    Created November 14, 19
V88  `124
X;  `124`009`009`009`009`009`009`009`009`009       `124
X;  `124  Modification History`009`009`009`009`009`009       `124
X;  `124  V1.0-002`00911/14/88 RSB`009Original version`009`009`009       `124
X;  `124`009`009`009`009`009`009`009`009`009       `124
X;  +------------------------------------------------------------------------
V---+
X;
X; This procedure returns the number of 10-ms ticks of idle time accumulated
V by
X; the active CPUs found on the system.  It also returns the number of CPUs
X; found, so the caller can determine how useful the returned idle time is. T
Vhe
X; basic algorithm is stolen from the routine GET_SPC in module SYSGETSPI in
X; facility MONITOR from the VMS V5.0 fiche.
X;
X`009.TITLE`009CPUIDLE - Calculate CPU Idle Time
X`009.IDENT`009'V1.0-002'
X`009.LIBRARY 'SYS$LIBRARY:LIB'
X`009.LINK`009'SYS$SYSTEM:SYS.STB' /SELECTIVE_SEARCH
X;
X`009$CPUDEF
X`009$SSDEF
X;
X; status.wl.v = CPUIDLE(idle.wl.r,cpus.wl.r)
X;
X; IDLE (longword output parameter, passed by reference) contains the total
X; aggregate idle time measured on the system, in 10-ms ticks.
X; CPUS (longword output parameter, passed by reference) contains the number
X; of active CPUs whose idle times were analyzed.
X; STATUS (longword function value) contains the return status from this call
V.
X; It will be SS$_BADPARAM if the argument count was incorrect, otherwise it
X; will be SS$_NORMAL.  Flakey arguments may cause access violations.
X;
XIDLE = 4`009`009`009`009; Argument list offset definitions
XCPUS = 8
X;
X; This procedure has been tested only on uniprocessor systems.  The effects
V of
X; starting and stopping cpus on a multiprocessor system are unknown but prob
Vably
X; result in idle times which are not monotonically increasing with time; e.g
V.
X; if a cpu is stopped, its idle time is probably removed from the total, whi
Vch
X; causes the returned value to decrease.
X;
X`009.PSECT`009$CODE`009`009PIC,USR,CON,REL,LCL,SHR,EXE,RD,NOWRT,NOVEC
X`009.ENTRY`009CPUIDLE,`094M<R2,R3,R4>
X`009CMPL`009#2,(AP)`009`009`009`009; Did user supply 2 arguments?
X`009BEQL`00910$`009`009`009`009; Yes, continue
X`009MOVL`009#SS$_BADPARAM,R0`009`009; Set error status
X`009RET`009`009`009`009`009; and get out
X10$:`009`009`009`009`009`009; Initialize counters
X`009CLRL`009R0`009`009`009`009; Idle tick counter
X`009CLRL`009R4`009`009`009`009; Active CPU counter
X`009MOVL`009G`094SMP$GL_ACTIVE_CPUS,R1`009`009; Get bitmask of active CPUs
X20$:`009`009`009`009`009`009; Start of scan loop
X`009FFS`009#0,#32,R1,R2`009`009`009; R2 will have next CPU index
X`009BEQL`00930$`009`009`009`009; Quit if no more active CPUs
X`009MOVL`009G`094SMP$GL_CPU_DATA`091R2`093,R3`009; R3 points to CPU's counte
Vrs
X`009ADDL2`009CPU$L_NULLCPU(R3),R0`009`009; Add in idle time
X`009INCL`009R4`009`009`009`009; Count this CPU
X`009BBSC`009R2,R1,20$`009`009`009; Mark CPU 'counted' & loop
X30$:`009`009`009`009`009`009; Pass back information
X`009MOVL`009R0,@IDLE(AP)`009`009`009; Store total idle time
X`009MOVL`009R4,@CPUS(AP)`009`009`009; Store active CPU count
X`009MOVL`009#SS$_NORMAL,R0`009`009`009; We finished okay
X`009RET
X`009.END
$ CALL UNPACK CPUIDLE.MAR;1 2117241941
$ EXIT

