-- File: IntimeImpl.mesa -- Last edited by -- 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 DIRECTORY Intime, Inline USING [ LowHalf, LongDiv, LongNumber, HighHalf ], Process USING [ SecondsToTicks, TicksToMsec ], SpecialSpace USING [ MakeGlobalFrameResident, MakeCodeResident ], System USING [ GetGreenwichMeanTime, GetClockPulses, MicrosecondsToPulses, Pulses, PulsesToMicroseconds, SecondsSinceEpoch ] ; IntimeImpl: MONITOR IMPORTS Inline, Process, SpecialSpace, System EXPORTS Intime SHARES Intime = BEGIN OPEN Intime; msPerDeltaTick: PUBLIC MsTicks _ Process.TicksToMsec[1]; deltaTicksPerSecond: PUBLIC DeltaTicks _ Process.SecondsToTicks[1]; pulsesPerSecond: System.Pulses = System.MicrosecondsToPulses[m: 1000000]; adjustInterval: System.Pulses = [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: System.Pulses; -- 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: System.Pulses; init: BOOLEAN_FALSE; WHILE (now _ [System.GetClockPulses[]-fastBase])>adjustInterval DO InternalAdjustEventTime[init]; init_TRUE; ENDLOOP; -- repeats at most once. RETURN[Increment[by: Inline.LongDiv[num: System.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: BOOLEAN] = { InternalAdjustEventTime[initialize]; }; InternalAdjustEventTime: INTERNAL PROC[initialize: BOOLEAN] = INLINE { newSeconds: LONG CARDINAL = System.SecondsSinceEpoch[System.GetGreenwichMeanTime[]]; IF newSecondsimpossibleInterval THEN initialize_TRUE; IF initialize THEN { milliseconds.higher _ 0; milliseconds.lower _ LONG[Inline.LowHalf[newSeconds]]*1000; milliseconds.hi _ milliseconds.hi + LONG[Inline.HighHalf[newSeconds]]*1000; fastBase _ System.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, -- returns LAST[MsTicks] -- tt: Inline.LongNumber _ [lc[t1.lower - t2.lower]]; RETURN[ IF t1.higher > t2.higher + 1 OR tt.highbits # 0 THEN LAST[CARDINAL] ELSE tt.lowbits] }; -- Initialization -- -- Should be called BEFORE Inscript registers in! SpecialSpace.MakeGlobalFrameResident[IntimeImpl]; SpecialSpace.MakeCodeResident[IntimeImpl]; END.