	.TITLE	NULTIM	COLLECT CPU TIME OF NULL PROCESS
	.IDENT	/1.01/			;FILE: "NULTIM.MAR"

;
;	COPYRIGHT (C) 1979
;		MANAGEMENT SCIENCE ASSOCIATES, INC.
;		5100 CENTRE AVENUE
;		PITTSBURGH, PENNSYLVANIA  15232
;
;	THIS SOFTWARE IS DISTRIBUTED WITHOUT COST, AND MAY BE
;	REPRODUCED ONLY WITH THE INCLUSION OF THIS COPYRIGHT
;	STATEMENT.  MANAGEMENT SCIENCE ASSOCIATES ASSUMES NO
;	RESPONSIBILITY FOR THE PERFORMANCE OF THIS SOFTWARE.
;

;++
;	NULTIM
;
; FUNCTION:	COLLECT CPU TIME OF THE PROCESS NULL
;		THIS IS TO DETERMINE HOW LOADED THE SYSTEM IS
;		(IF THERE'S A BETTER WAY, PLEASE LET US KNOW!)
;
; SPECIAL CONSIDERATIONS:
;	LINK:	WITH SYS$SYSTEM:SYS.STB/SEL
;	RUN:	/PROCESS_NAME=NULTIM/UIC=[1,4]/PRIORITY=7 NULTIM.EXE
;
; NOTE:	CMKRNL PRIVILEGE REQUIRED
;
; OPERATION:	EVERY "TIMINC" SECONDS THE WALL CLOCK TIME AND
;		THE CPU TIME OF THE PROCESS NULL (PID 0) ARE
;		GATHERED.  THESE ARE BUFFERED IN THREE PAGES
;		(A MULTIPLE OF THE 12 BYTES COLLECED EACH TIME)
;		UNTIL THE BUFFER IS FULL, AT WHICH TIME THEY
;		ARE APPENDED TO [SYSMGR]NULTIM.DAT.  ANOTHER
;		PROGRAM IS NEEDED TO ANALYZE THESE STATISTICS.
;		WITH "TIMINC" SET AT 30 (SECONDS) THE BUFFER
;		IS WRITTEN ABOUT EVERY HOUR, SO THE IMPACT ON
;		THE SYSTEM IS MINIMAL, AND ABOUT 500 PAGES
;		(BLOCKS) ARE PRODUCED EVERY WEEK.
;--
	.PAGE

	.LIBRARY	"SYS$LIBRARY:LIB.MLB"
	$IPLDEF
	$PHDDEF
	$UCBDEF

	.PSECT	BUFFER,PIC,CON,REL,NOSHR,NOEXE,RD,WRT,LCL,PAGE

	RECSIZ = 3*512			;THREE PAGES OF DATA PER RECORD

RECORD:	.BLKB	RECSIZ			;THE BUFFER


	.PSECT	DATA,CON,REL,NOSHR,NOEXE,RD,WRT,LCL,LONG

	.ALIGN	LONG
FILFAB:	$FAB	FAC=PUT,-		;ONLY WANT TO WRITE
		FNA=FILNAM,-		;FILE NAME
		FNS=NAMLEN,-		;LENGTH OF FILE NAME
		FOP=<CIF,SQO>,-		;CREATE IF DOESN'T EXIST
		MRS=RECSIZ,-		;MAXIMUM RECORD SIZE
		ORG=SEQ,-		;SEQUENTIAL
		RFM=FIX			;FIXED LENGTH RECORDS

	.ALIGN	LONG
FILRAB:	$RAB	FAB=FILFAB,-		;POINT TO THE FAB
		RAC=SEQ,-		;SEQUENTIAL ACCESS
		RBF=RECORD,-		;RECORD BUFFER ADDRESS
		ROP=EOF,-		;WANT TO APPEND
		RSZ=RECSIZ		;RECORD SIZE

FILNAM:	.ASCII	/DBA0:[SYSMGR]NULTIM.DAT/ ;FILE NAME
	NAMLEN = . - FILNAM		;LENGTH OF FILE NAME

	TIMINC = 30			;NUMBER OF SECONDS TO SLEEP
WAKTIM:	.LONG	<-10*1000*1000>*TIMINC	;QUADWORD DELTA TIME
	.LONG	-1			;


	.PSECT	CODE,PIC,CON,REL,SHR,EXE,RD,NOWRT,LONG
	.PAGE

;++
; NULTIM	RECORD CPU TIME OF NULL PROCESS - MAIN ENTRY
;
; FUNCTION:	WHILE NO ERRORS DO
;			SLEEP FOR "TIMINC" SECONDS
;			ACCUMULATE STATISTICS VIA GETTIM
;			IF THE BUFFER IS FULL, WRITE IT VIA WRTREC
;
; EXIT:		ON ERROR
;--

	.ENTRY	NULTIM,^M<>		;MAIN ENTRY - SAVE NO REGISTERS
10$:	MOVAL	RECORD,R6		;BEGINNING OF RECORD
	MOVAL	RECSIZ(R6),R7		;END OF RECORD
	MOVC5	#0,(R6),#0,#RECSIZ,(R6)	;CLEAR THE BUFFER
	MOVAL	WAKTIM,R8		;DELTA TIME FOR WAKEUP
20$:	$SCHDWK_S	DAYTIM=(R8)	;WAKE US UP LATER
	BLBC	R0,30$			;
	$HIBER_S			;MEANWHILE WE'LL SNOOZE
	BLBC	R0,30$			;
	$CMKRNL_S	GETTIM		;GO COLLECT STATISTICS
	MOVQ	R1,(R6)+		;PUT CURRENT TIME IN BUFFER
	MOVL	R3,(R6)+		;PUT CPU TIME IN BUFFER
	CMPL	R6,R7			;CHECK FOR A FULL BUFFER
	BLSS	20$			;NOT FULL - GO BACK TO SLEEP
	BSBW	WRTREC			;GO WRITE OUR DATA
	BLBS	R0,10$			;IF ALL IS WELL, START OVER
30$:	$EXIT_S		R0		;EXIT WITH FAILURE STATUS
	.PAGE

;++
; WRTREC	WRITE STATISTICS RECORD - LOCAL SUBROUTINE
;
; FUNCTION:	USE RMS TO APPEND OUR BUFFER TO THE STATISTICS FILE
;
; EXIT:		WITH STATUS
;--

WRTREC:	$CREATE		FAB=FILFAB	;OPEN THE FILE
	BLBC	R0,10$			;
	$CONNECT	RAB=FILRAB	;CONNECT RAB TO FAB
	BLBC	R0,10$			;
	$PUT		RAB=FILRAB	;WRITE THE RECORD
	BLBC	R0,10$			;
	$DISCONNECT	RAB=FILRAB	;RELEASE THE RAB
	BLBC	R0,10$			;
	$CLOSE		FAB=FILFAB	;CLOSE THE FILE
10$:	RSB				;RETURN WITH STATUS

	.PAGE

;++
; GETTIM	COLLECT STATISTICS - KERNEL MODE EXECUTION
;
; FUNCTION:	COLLECT STATISTICS AS FOLLOWS:
;			CURRENT TIME - QUAD
;			CPU TIME OF NULL PROCESS PLUS CPU TIME OF CURRENT
;			 PROCESS (PRESUMABLY OTHERWISE USED BY NULL) - LONG
;
; EXIT:		R1,R2 HAVE CURRENT TIME
;		R3 HAS NULL'S CPU TIME PLUS OUR OWN
;--

	.ENTRY	GETTIM,^M<>		;KERNEL MODE EXECUTION
	TSTL	10$			;ENSURE ALL IN WORKING SET
	SETIPL	#IPL$_SYNCH		;INHIBIT SWAPPING
	MOVQ	EXE$GQ_SYSTIME,R1	;THE CURRENT TIME
	MOVL	@SCH$GL_PCBVEC,R0	;FIRST ENTRY IN PCB TABLE IS NULL'S
	MOVL	PCB$L_PHD(R0),R0	;GET NULL'S PHD ADDRESS
	MOVL	PHD$L_CPUTIM(R0),R3	;GET THE CPUTIME FROM THE PHD
	MOVL	SCH$GL_CURPCB,R0	;OUR PCB ADDRESS
	MOVL	PCB$L_PHD(R0),R0	;OUR PHD ADDRESS
	ADDL	PHD$L_CPUTIM(R0),R3	;ADD IN OUR OWN TIME
10$:	SETIPL	#0			;ENABLE SWAPPING NOW
	RET				;LEAVE KERNEL MODE

	.END	NULTIM			;THAT'S ALL, FOLKS!
