IntimeImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Dan Swinehart March 23, 1982 12:58 pm
MBrown on 23-Mar-82 16:03:41
Dan Swinehart on April 14, 1982 11:04 am
Paul Rovner on August 10, 1983 5:49 pm
Russ Atkinson, September 16, 1983 6:00 pm
Doug Wyatt, February 28, 1985 7:13:36 pm PST
DIRECTORY
Basics USING [LowHalf, LongDiv, LongNumber, HighHalf],
Intime,
Loader USING [MakeProcedureResident, MakeGlobalFrameResident],
Process USING [SecondsToTicks, TicksToMsec],
ProcessorFace USING [GetGreenwichMeanTime, GetClockPulses, gmtEpoch, microsecondsPerHundredPulses];
IntimeImpl: MONITOR
IMPORTS Basics, Loader, Process, ProcessorFace
EXPORTS Intime
SHARES Intime
= BEGIN OPEN Intime;
note: microsecondsPerHundredPulses/100 = microsecondsPerPulse
MicrosecondsToPulses: PROC[ms: LONG CARDINAL] RETURNS[LONG CARDINAL] = {
RETURN[(ms*100)/ProcessorFace.microsecondsPerHundredPulses]; -- RRA
};
PulsesToMicroseconds: PROC[p: LONG CARDINAL] RETURNS[LONG CARDINAL] = {
RETURN[(p*ProcessorFace.microsecondsPerHundredPulses)/100]; -- RRA
};
msPerDeltaTick: PUBLIC MsTicks ← Process.TicksToMsec[1];
deltaTicksPerSecond: PUBLIC DeltaTicks ← Process.SecondsToTicks[1];
pulsesPerSecond: LONG CARDINAL = MicrosecondsToPulses[1000000];
adjustInterval: LONG CARDINAL = pulsesPerSecond-1;
impossibleInterval: LONG CARDINAL = 30; -- seconds, must be < 64K/1000
seconds: LONG CARDINAL; -- seconds since System.gmtEpoch the last time we set milliseconds
milliseconds: EventTime; -- milliseconds since System.gmtEpoch
fastBase: LONG CARDINAL;
value of System.GetClockPulses[] at time (in the recent past) when milliseconds = System.GetGreenwichMeanTime[]. things stop working if System.GetClockPulses[]-fastBase gets large (one minute or so). Frequently-running process is supposed to call AdjustEventTime often enough to update fastBase within adjustInterval pulses.
ReadEventTime: PUBLIC ENTRY PROC [] RETURNS[res: EventTime] = {
now: LONG CARDINAL;
init: BOOL ← FALSE;
WHILE (now ← ProcessorFace.GetClockPulses[]-fastBase)>adjustInterval DO
InternalAdjustEventTime[init]; init←TRUE; ENDLOOP; -- repeats at most once.
RETURN[Increment[by: Basics.LongDiv[num: PulsesToMicroseconds[now], den: 1000]]]
};
Increment: INTERNAL PROC
[by: --milliseconds--CARDINAL] RETURNS[res: EventTime] = INLINE {
res← [hiShort[higher: 0, lower: LONG[by] + LONG[milliseconds.lo]]];
res.hi ← res.hi + milliseconds.hi;
};
AdjustEventTime: PUBLIC ENTRY PROC [initialize: BOOL] = {
InternalAdjustEventTime[initialize]
};
InternalAdjustEventTime: INTERNAL PROC [initialize: BOOL] = INLINE {
newSeconds: LONG CARDINAL =
ProcessorFace.GetGreenwichMeanTime[] - ProcessorFace.gmtEpoch;
IF newSeconds < seconds OR newSeconds - seconds > impossibleInterval
THEN initialize←TRUE;
IF initialize THEN {
milliseconds.higher ← 0;
milliseconds.lower ← LONG[Basics.LowHalf[newSeconds]]*1000;
milliseconds.hi ← milliseconds.hi + LONG[Basics.HighHalf[newSeconds]]*1000;
fastBase ← ProcessorFace.GetClockPulses[];
}
ELSE {
dif: NAT ← newSeconds - seconds;
milliseconds ← Increment[by: 1000*dif];
Usually go through following loop zero or one times, never more than impossibleInterval times.
THROUGH [1..dif] DO fastBase ← fastBase+pulsesPerSecond ENDLOOP;
};
seconds ← newSeconds
};
BigDifference: PUBLIC PROC
[t1, t2: LONG POINTER TO READONLY EventTime] RETURNS [MsTicks] = {
t1 presumed later than or equal to t2. For time differences beyond the MsTicks range, BigDifference returns LAST[MsTicks]
tt: Basics.LongNumber ← [lc[t1.lower - t2.lower]];
RETURN[
IF t1.higher > t2.higher + 1 OR tt.highbits # 0 THEN LAST[CARDINAL]
ELSE tt.lowbits
];
};
START HERE
Loader.MakeProcedureResident[--e.g.--ReadEventTime];
Loader.MakeGlobalFrameResident[--e.g.--ReadEventTime];
END.