-- 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.