-- File: StatsCold.mesa, Last Edit: January 7, 1981 1:20 PM DIRECTORY Process USING [Detach, SetTimeout, SecondsToTicks], Put USING [CR, Char, Text, Line], System USING [ GreenwichMeanTime, GetGreenwichMeanTime, Pulses, GetClockPulses, Microseconds, PulsesToMicroseconds], Time USING [AppendCurrent], Window USING [Handle], StatsDefs USING [StatBump, StatCounterIndex], StatsOps USING [statGrand, StatPrintCounters, StatsPrint, StatsStrings]; StatsCold: MONITOR LOCKS statLock IMPORTS Process, Put, System, Time, StatsDefs, StatsOps EXPORTS StatsDefs, StatsOps = BEGIN OPEN StatsDefs, StatsOps; statLock: PUBLIC MONITORLOCK; initDateAndTime: STRING ← [18]; -- when we were initialized grand: ARRAY StatCounterIndex OF LONG CARDINAL; StatsGetCounters: PUBLIC PROCEDURE RETURNS [POINTER TO ARRAY StatCounterIndex OF LONG CARDINAL] = BEGIN RETURN[@grand]; END; StatUpdater: ENTRY PROCEDURE = BEGIN updater: CONDITION; Process.SetTimeout[@updater, Process.SecondsToTicks[15*60]]; DO -- forever WAIT updater; StatUpdateLocked[]; ENDLOOP; END; StatUpdate: PUBLIC ENTRY PROCEDURE = BEGIN StatUpdateLocked[]; 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 grand[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 instructions that do an atomic read and reset. -- our copies of the time sampled when we last looked at the clock oldSeconds: System.GreenwichMeanTime ← System.GetGreenwichMeanTime[]; oldPulses: System.Pulses ← System.GetClockPulses[]; -- Time may go backwards when it gets reset. spareSeconds: LONG INTEGER ← 0; -- remembers fractions of an hour StatUpdateLocked: INTERNAL PROCEDURE = BEGIN nowPulses: System.Pulses ← System.GetClockPulses[]; recent: LONG CARDINAL; delta: System.Microseconds; newSeconds: System.GreenwichMeanTime ← System.GetGreenwichMeanTime[]; delta ← System.PulsesToMicroseconds[System.Pulses[nowPulses - oldPulses]]; grand[statTime] ← grand[statTime] + delta/1000; oldPulses ← nowPulses; recent ← newSeconds - oldSeconds; oldSeconds ← newSeconds; grand[statSeconds] ← grand[statSeconds] + recent; spareSeconds ← spareSeconds + recent; UNTIL spareSeconds < 3600 DO spareSeconds ← spareSeconds - 3600; grand[statHours] ← grand[statHours] + 1; ENDLOOP; END; -- remember current date and time for header lines StatNew: PUBLIC ENTRY PROCEDURE = BEGIN initDateAndTime.length ← 0; Time.AppendCurrent[initDateAndTime]; StatZap[]; END; -- reset counters, and print a here-we-go line StatStart: PUBLIC ENTRY PROCEDURE [wh: Window.Handle, header: STRING] = BEGIN StatZap[]; StatPrintDateAndTime[wh]; Put.Text[wh, header]; IF initDateAndTime.length # 0 THEN BEGIN Put.Text[wh, " of "L]; Put.Text[wh, initDateAndTime]; END; Put.Line[wh, "."L]; END; -- print out current numbers StatPrintCurrent: PUBLIC ENTRY PROCEDURE [wh: Window.Handle] = BEGIN StatUpdateLocked[]; StatPrintDateAndTime[wh]; Put.Line[wh, "Current counters."L]; StatPrintCounters[wh, @grand]; Put.CR[wh]; END; -- print out current numbers StatFinish: PUBLIC ENTRY PROCEDURE [wh: Window.Handle] = BEGIN StatUpdateLocked[]; StatPrintDateAndTime[wh]; Put.Line[wh, "Grand Totals."L]; StatPrintCounters[wh, @grand]; Put.CR[wh]; StatZap[]; -- just in case END; -- reset the world to be nice and clean again StatZapit: ENTRY PROCEDURE = BEGIN StatZap[]; END; StatZap: INTERNAL PROCEDURE = BEGIN StatUpdateLocked[]; -- init most internal stuff spareSeconds ← 0; recent ← grand ← ALL[0]; END; -- our copy of grand at last call to StatSince or StatReady recent: ARRAY StatCounterIndex OF LONG CARDINAL; -- setup things for StatSince or StatSummary StatReady: PUBLIC ENTRY PROCEDURE = BEGIN StatUpdateLocked[]; recent ← grand; END; -- print out new numbers since last call to StatReady or StatSince StatSince: PUBLIC PROCEDURE [wh: Window.Handle] = BEGIN temp: ARRAY StatCounterIndex OF LONG CARDINAL; GetCopies: ENTRY PROCEDURE = INLINE BEGIN StatUpdateLocked[]; temp ← grand; END; GetCopies[]; FOR i: StatCounterIndex IN StatCounterIndex DO recent[i] ← temp[i] - recent[i]; ENDLOOP; StatPrintDateAndTime[wh]; Put.Line[wh, "Recent Statistics."L]; StatPrintCounters[wh, @recent]; Put.CR[wh]; recent ← temp; END; -- AppendCurrent has format of dd-mmm-yy hh:mm:ss StatPrintDateAndTime: PUBLIC PROCEDURE [wh: Window.Handle] = BEGIN string: STRING ← [18]; --Toolies don't know how to do this (yet?)! IF ~NewLine[] THEN Put.CR[wh]; Time.AppendCurrent[string]; Put.Text[wh, string]; Put.Char[wh, ' ]; Put.Char[wh, ' ]; END; -- initialization StatsDefs.StatBump[statMouseTrap, 0]; -- StatsHot isn't part of our config in Pilot StatsOps.statGrand ← @grand; START StatsOps.StatsPrint; START StatsOps.StatsStrings; StatZapit[]; Process.Detach[FORK StatUpdater[]]; END.