-- File: StatsCold.mesa, Last Edit: November 19, 1979 12:08 PM

-- Copyright Xerox Corporation 1979, 1980

DIRECTORY
IODefs: FROM "IODefs" USING [
CR, WriteChar, WriteLine, WriteOctal, WriteString, NewLine],
OsStaticDefs: FROM "OsStaticDefs" USING [OsStatics],
ProcessDefs: FROM "ProcessDefs" USING [Detach, SetTimeout],
TimeDefs: FROM "TimeDefs" USING [AppendDayTime, DefaultTime, UnpackDT],
StatsDefs: FROM "StatsDefs" USING [StatIncr, StatCounterIndex],
StatsPrivateDefs: FROM "StatsPrivateDefs" USING [
statGrand, statText, StatPrintCounters, StatsHot, StatsPrint, StatsStrings];

StatsCold: MONITOR LOCKS statLock
IMPORTS IODefs, ProcessDefs, TimeDefs, StatsDefs, StatsPrivateDefs
EXPORTS StatsDefs, StatsPrivateDefs =
BEGIN OPEN StatsDefs, StatsPrivateDefs;

statLock: PUBLIC MONITORLOCK;


initDateAndTime:
STRING ← [18];-- when we were initialized


-- Note: This is not locked in core. Don
’t call it from interrupt routines.

StatLog: PUBLIC PROCEDURE [which: StatCounterIndex, p: POINTER, l: CARDINAL] =
BEGIN OPEN IODefs;
-- p+l are for debugging or whatever, maybe someday it will send a packet someplace
s: STRING ← statText[which];
k: CARDINAL;
StatIncr[which];
StatPrintDateAndTime[];
IF s#NIL THEN WriteString[s];
WriteLine[" ********"L];
IF p=NIL THEN RETURN;
WriteOctal[p];
WriteChar[’↑];
FOR k IN [0..MIN[l,100]) DO WriteChar[’ ]; WriteOctal
[(p+k)↑]; ENDLOOP;
WriteChar[CR];
END;

StatsGetCounters: PUBLIC PROCEDURE RETURNS [
POINTER TO ARRAY StatCounterIndex OF LONG CARDIN
AL] =
BEG
IN
RETURN[@statGrand];
END;

StatUpdater: ENTRY PROCEDURE =
BEGIN
updater: CONDITION;
ProcessDefs.SetTimeout[@updater,24000]; -- 20 min at 50 ms/tick
DO -- forever
WAIT updater;
StatUpdateLocked[];
ENDLOOP;
END;

StatUpdate: PUBLIC ENTRY PROCEDURE =
BEGIN
StatUpdateLo
cked[];
END;

-- Update various things.

-- It can be called anytime, but must be called "often enough". The 39ms clock overflows every 41 min, so be sure to call it more often than that. StatsCold FORKs to a PROCESS that calls it every 20 minutes.

-- Also, it should be called before looking at statGrand[StatTime or statSeconds], as in when printing things out.

-- One idea to make things go faster is to actually count things in 16 bit mode, and call somebody before the small counters overflow to copy the info out and reset them. This is where that should get done, but its a hard problem because there are no MESA instr
uctions that do a an atomic read and reset.

ticks: POINTER TO CARDINAL = LOOPHOLE[430B];-- core loc of 39ms clock
ms
PerTick: CARDINAL = 39;-- 39 ms per tick
oldTicks: CAR
DINAL ← ticks↑;-- last copy of 39ms clock

-- this is an INTEGER because time may go backwards when
it gets reset
s
econds: POINTER TO INTEGER = LOOPHOLE[573B];-- core loc of 1 sec clock
oldSeconds: INTE
GER ← seconds↑;-- last copy of 1 sec clock

s
pareSeconds: CARDINAL ← 0;

StatUpdateLocked: INTERNAL PROCEDURE =
BEGIN
nowTicks: CARDINAL ← ticks↑;
recent: CARDINAL;
delta: LONG CARDINAL;
newSeconds: INTEGER ← se
conds↑;
delta ← LONG[(nowTicks-oldTicks)]*msPerTick; -- lengthen before multiply
oldTicks ← nowTicks;
statGrand[statTime] ← statGrand[statTime]+delta;
recent ← newSeconds-oldSeconds;
delta ← newSeconds-oldSeconds;
oldSeconds ← newSeconds;
statGrand[statSeconds] ← statGrand[statSeconds]+delta;
spareSeconds ← spareSeconds+recent;
UNTIL spareSeconds<3600 DO
spareSeconds ← spareSeconds-3600;
statGrand[statHours] ← statGrand[statHours]+1;
ENDLOOP;
END;

-- reme
mber current date and time for header lines
StatNew: PUBLIC ENTRY PROCEDURE =
BEGIN OPEN TimeDefs;
initDateAndTime.length ← 0;
AppendDayTime[initDateAndTime,UnpackDT[DefaultTime]];
StatZap[];
END;


--
reset counters, and print a here-we-go line
StatStart: PUBLIC ENTRY PROCEDURE [header: STRING] =
BEGIN OPEN OsStaticDefs, IODefs;
StatZap[];
StatPrintDateAndTime[];
WriteString[header];
WriteString[" of "L];
WriteString[initDateAndTime];
WriteString[" on #"L];
WriteOctal[OsStatics↑.SerialNumber];
WriteLine["
."L];
END;


-
- print out current numbers
StatPrintCurrent: PUBLIC ENTRY PROCEDURE =
BEGIN OPEN IODefs;
StatUpdateLocked[];
StatPrintTime[]; WriteLine["Current counters."L];
StatPrintCounters[@statGrand];
WriteChar
[CR];
EN
D;


-- print out current numbers
StatFinish: PUBLIC ENTRY PROCEDURE =
BEGIN OPEN IODefs;
StatUpdateLocked[];
StatPrintDateAndTime[]; WriteLine["Grand Totals."L];
StatPrintCounters[@statGrand];
WriteChar[CR];
StatZap[]; -- just in case
END;


--
reset the world to be nice and clean again
StatZap: INTERNAL PROCEDURE =
BEGIN
i: StatCounterIndex;
StatUpdateLocked[]; -- init most internal stuff
spareSeconds ← 0;
FOR i IN StatCounterIndex DO recent[i] ← statGrand[i] ← 0; ENDLOOP;
END;
-- our copy of statGrand at last call to StatSince or StatReady
recent: ARRAY StatCounterIndex OF LONG CARDINAL;


-- setup things for StatSince or StatSummary
StatReady: PUBLIC ENTRY PROCEDURE =
BEGIN
i: StatCounterIndex;
StatUpdateLocked[];
FOR i IN StatCounterIndex DO recent[i] ← statGrand[i]; ENDLOOP;
END;

-- print out new numbers since last call to StatReady or StatSince
StatSince: PUBLIC PROCEDURE =
BEGIN OPEN IODefs;
i: StatCounterIndex;
temp: ARRAY StatCounterIndex OF LONG CARDINAL;
GetCopies: ENTRY PROCEDURE = INLINE
BEGIN
StatUpdateLocked[];
FOR i IN StatCounterIndex DO temp[i]←statGrand[i]; ENDLOOP;
END;
GetCopies[];
FOR i IN StatCounterIndex DO recent[i] ← temp[i]-recent[i]; ENDLOOP;
StatPrintTime[];
WriteLine["Recent Statistics."L];
StatPrintCounters[@recent];
WriteChar[CR];
FOR i IN StatCounterIndex DO recent[i] ← temp[i]; ENDLOOP;
END;

-- AppendDayTime has format of dd-mmm-yy hh:mm:ss

StatPrintDateAndTime: PUBLIC PROCEDURE =
BEGIN OPEN IODefs, TimeDefs;
string: STRING ← [18];
IF ~NewLine[] THEN WriteChar[CR];
AppendDayTime[string,UnpackDT[DefaultTime]];
WriteString[string];
WriteChar[’ ];
WriteChar[’ ];
END;

StatPrintTime: PROCEDURE =
BEGIN OPEN IODefs, TimeDefs;
i: CARDINAL;
string: STRING ← [18];
AppendDayTime[string,UnpackDT[DefaultTime]];
FOR i IN [10..18) DO WriteChar[string[i]]; ENDLOOP;
WriteChar[’ ];
WriteChar[’ ];
END;


-- initialization
START StatsPrivateDefs.StatsHot;
START StatsPrivateDefs.StatsPrint;
START StatsPrivateDefs.StatsStrings;
StatNew[];
ProcessDefs.Detach[FORK StatUpdater[]];
END.