IntimeImpl.mesa
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
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
];
};