-- Copyright (C) 1984, 1985 by Xerox Corporation. All rights reserved. -- IdleTime.mesa -- HGM, 21-May-85 23:35:01 -- last edited by Hankins 14-Aug-84 8:44:29 DIRECTORY Inline USING [LowHalf], LogDefs USING [DisplayNumber, Percentage], Process USING [ Detach, GetPriority, Milliseconds, MsecToTicks, Priority, SetPriority, SetTimeout, Yield], ProcessPriorities USING [priorityClientHigh, priorityClientLow], ProcessorFace USING [SetMP], SpecialSpace USING [MakeProcedureResident], System USING [ GetClockPulses, MicrosecondsToPulses, Pulses, PulsesToMicroseconds]; IdleTime: MONITOR IMPORTS Inline, LogDefs, Process, ProcessorFace, SpecialSpace, System = BEGIN -- Types, Constants, Vars: updateDisplay: CONDITION; displayUpdateMsec: Process.Milliseconds ← 1000; priorityPublisher: Process.Priority ← ProcessPriorities.priorityClientHigh; priorityIdler: Process.Priority ← ProcessPriorities.priorityClientLow; -- CPU utilization related declarations: cycles: LONG CARDINAL ← 0; cyclesPerRefresh, pulsesPerRefresh: LONG CARDINAL ← 0; -- set by Calibrate idleFive: CARDINAL ← 0; -- last sec, average last 10 sec (percentage*100) idlePercent: LogDefs.Percentage ← LAST[LogDefs.Percentage]; -- Internal Procedures -- Idler: PROCEDURE = { DO THROUGH [0..10000) DO cycles ← cycles.SUCC; Process.Yield[]; ENDLOOP; ENDLOOP}; Calibrate: PROCEDURE = BEGIN cyclesToSample: CARDINAL = 10000; -- about a second on a DLion priorityPrev: Process.Priority ← Process.GetPriority[]; first, last: System.Pulses; nanoSecPerCycle: LONG CARDINAL; Process.SetPriority[Process.Priority.LAST]; first ← System.GetClockPulses[]; THROUGH [0..cyclesToSample) DO cycles ← cycles.SUCC; Process.Yield[]; ENDLOOP; -- This seems slow if an extra timeout scan happens, packet arrives or ... -- Unfortunately, that causes confusion when idle > 100% last ← System.GetClockPulses[]; cycles ← (cycles - cyclesToSample); Process.SetPriority[priorityPrev]; nanoSecPerCycle ← System.PulsesToMicroseconds[[LONG[1000] * (last - first)]] / cyclesToSample; cyclesPerRefresh ← (1000000 * displayUpdateMsec) / nanoSecPerCycle; pulsesPerRefresh ← System.MicrosecondsToPulses[ displayUpdateMsec * LONG[1000]]; END; Publisher: ENTRY PROCEDURE = BEGIN startPulses: LONG CARDINAL ← System.GetClockPulses[]; startCycles: LONG CARDINAL ← cycles; pulsesThisRefresh, cyclesThisRefresh: LONG CARDINAL ← 0; idle: CARDINAL ← 0; Process.SetPriority[priorityPublisher]; DO startPulses ← (startPulses + pulsesThisRefresh); startCycles ← (startCycles + cyclesThisRefresh); -- wait for a second WAIT updateDisplay; -- now update pulsesThisRefresh ← (System.GetClockPulses[] - startPulses); cyclesThisRefresh ← (cycles - startCycles); THROUGH [0..10) DO cyclesThisTry: LONG CARDINAL = cyclesThisRefresh * pulsesPerRefresh / pulsesThisRefresh; idle ← Inline.LowHalf[cyclesThisTry * 10000 / cyclesPerRefresh]; IF idle > 10000 THEN -- Calibration screwed up {cyclesPerRefresh ← cyclesPerRefresh + 1; LOOP} ELSE EXIT; REPEAT FINISHED => idle ← 10000; ENDLOOP; idlePercent ← idle / 100; --idleTen ← Inline.LongDiv[idle + Inline.LongMult[idleTen,9], 10]; -- this latter would be more interesting info (slower fluctuations) but -- not sure of the cost of latter calculation so won't use, instead try this: idlePercent ← idleFive ← (idlePercent + idleFive * 4) / 5; ProcessorFace.SetMP[100-idlePercent]; ENDLOOP; END; Initialize: PROCEDURE = BEGIN -- once-only initialization. priorityPrev: Process.Priority; Process.SetTimeout[@updateDisplay, Process.MsecToTicks[displayUpdateMsec]]; SpecialSpace.MakeProcedureResident[Idler]; Calibrate[]; -- start up Publisher process Process.Detach[FORK Publisher[]]; priorityPrev ← Process.GetPriority[]; -- start up Idle process Process.SetPriority[priorityIdler]; Process.Detach[FORK Idler[]]; Process.SetPriority[priorityPrev]; LogDefs.DisplayNumber["Idle time"L, [percent[@idlePercent]]]; END; --Initialize -- Main Body: Initialize[]; END. 13-Aug-84 9:40:40: blh - threw away old code and copied from Klamath ActivityImpl hack.