-- Copyright (C) 1984, 1985 by Xerox Corporation. All rights reserved. -- Alive.mesa, HGM, 28-Sep-85 18:18:36 -- Do something so I can see it's still alive... -- This is also the Shift-STOP watcher. (Only it's the Alt-Boot button.) -- Hacked to bypass PROMs that defer wakeups DIRECTORY DicentraInputOutput USING [GetExternalStatus, SetExtCtrl, SetWakeupBits], Inline USING [LongDiv, LongMult, LowHalf], PilotClient USING [], Process USING [Milliseconds, MsecToTicks, Pause, SetPriority, Ticks, Yield], ProcessPriorities USING [priorityClientLow, priorityFrameFault, priorityPageFaultLow], Runtime USING [CallDebugger], System USING [GetClockPulses, MicrosecondsToPulses, Pulses, PulsesToMicroseconds], CpuIdle USING [], Watchdog USING [Deactivate]; UtilityPilotClientImpl: PROGRAM IMPORTS DicentraInputOutput, Inline, Process, Runtime, System, Watchdog EXPORTS PilotClient, CpuIdle = BEGIN displayUpdateMsec: Process.Milliseconds = 1000; cyclesPerSecond: LONG CARDINAL ← 0; pulsesPerSecond: LONG CARDINAL; cycles: LONG CARDINAL ← 0; used: CARDINAL ← 0; watcher: PROCESS = FORK Watcher[]; blinker: PROCESS; background: PROCESS; GetSmoothedCpuUtilization: PUBLIC PROCEDURE RETURNS [CARDINAL] = BEGIN RETURN[used/10]; END; GetCycles: PUBLIC PROCEDURE RETURNS[LONG CARDINAL] = BEGIN RETURN[cycles]; END; GetCalibration: PUBLIC PROCEDURE RETURNS [LONG CARDINAL, LONG CARDINAL, BOOLEAN] = BEGIN RETURN[cyclesPerSecond, pulsesPerSecond, TRUE]; END; Run: PUBLIC PROCEDURE = BEGIN -- Start Blinker after Start Traps have done the real work blinker ← FORK Blinker[]; background ← FORK Background[]; END; out: WORD ← 0; Watcher: PROCEDURE = BEGIN ticks: Process.Ticks = Process.MsecToTicks[displayUpdateMsec]; points: ARRAY [0..4) OF WORD ← [87H, 47H, 27H, 17H]; down: CARDINAL ← 0; Process.SetPriority[ProcessPriorities.priorityFrameFault]; IF DicentraInputOutput.GetExternalStatus[].altBoot THEN BEGIN Watchdog.Deactivate[]; Runtime.CallDebugger["Key Stop 2.001"L]; END; DO FOR i: CARDINAL IN [0..4) DO out ← points[i]; IF DicentraInputOutput.GetExternalStatus[].altBoot THEN BEGIN down ← down + 1; IF down = 2 THEN BEGIN Watchdog.Deactivate[]; Runtime.CallDebugger["Poof"L]; END ELSE out ← 0F7H; -- All 4 END ELSE down ← 0; DicentraInputOutput.SetExtCtrl[out]; Process.Pause[ticks]; ENDLOOP; ENDLOOP; END; Blinker: PROCEDURE = BEGIN ticks: Process.Ticks = Process.MsecToTicks[displayUpdateMsec]; Process.SetPriority[ProcessPriorities.priorityPageFaultLow]; Calibrate[]; DO Process.Pause[ticks]; ShowIdleTime[]; DicentraInputOutput.SetExtCtrl[out]; ENDLOOP; END; Background: PROCEDURE = BEGIN Process.SetPriority[ProcessPriorities.priorityClientLow]; DO THROUGH [0..50000) DO cycles ← SUCC[cycles]; IF FALSE THEN -- I think they have all been replaced by now. HGM, 28-Sep-85 18:18:09 DicentraInputOutput.SetWakeupBits[0]; -- Hack for buggy PROMs Process.Yield[]; ENDLOOP; ENDLOOP; END; startPulses: LONG CARDINAL ← System.GetClockPulses[]; startCycles: LONG CARDINAL ← cycles; ShowIdleTime: PROCEDURE = BEGIN pulsesThisRefresh: LONG CARDINAL ← System.GetClockPulses[] - startPulses; cyclesThisRefresh: LONG CARDINAL ← cycles - startCycles; cyclesThisTry: LONG CARDINAL ← cyclesThisRefresh * pulsesPerSecond / pulsesThisRefresh; idle: CARDINAL ← Inline.LowHalf[cyclesThisTry * 1000 / cyclesPerSecond]; IF idle > 1000 THEN idle ← 1000; used ← Inline.LongDiv[1000 - idle + Inline.LongMult[used,9],10]; SetMP[used/10]; startPulses ← startPulses + pulsesThisRefresh; startCycles ← startCycles + cyclesThisRefresh; END; SetMP: PROCEDURE [n: CARDINAL] = BEGIN -- Hack to avoid hogging CPU DicentraInputOutput.SetExtCtrl[5]; FOR i: CARDINAL IN [0..n) DO DicentraInputOutput.SetExtCtrl[3]; DicentraInputOutput.SetExtCtrl[7]; ENDLOOP; END; Calibrate: PROCEDURE = BEGIN cyclesToSample: CARDINAL = 10000; -- about a second on a DLion first, last: System.Pulses; nanoSecPerCycle: LONG CARDINAL; first ← System.GetClockPulses[]; THROUGH [0..cyclesToSample) DO cycles ← SUCC[cycles]; DicentraInputOutput.SetWakeupBits[0]; -- Hack for buggy PROMs Process.Yield[]; ENDLOOP; -- This appears to go slow if an extra timeout scan happens, packet arrives or ... -- Unfortunately, that causes confusion when idle > 100% last ← System.GetClockPulses[]; cycles ← cycles - cyclesToSample; nanoSecPerCycle ← System.PulsesToMicroseconds[[LONG[1000]*(last-first)]]/cyclesToSample; cyclesPerSecond ← (1000000*displayUpdateMsec)/nanoSecPerCycle; pulsesPerSecond ← System.MicrosecondsToPulses[displayUpdateMsec*LONG[1000]]; END; END.....