<> <> <> <> <> <> <> <> 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; <> 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; <> 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]; <> THROUGH [1..dif] DO fastBase _ fastBase+pulsesPerSecond ENDLOOP; }; seconds _ newSeconds }; BigDifference: PUBLIC PROC [t1, t2: LONG POINTER TO READONLY EventTime] RETURNS [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 ]; }; <> Loader.MakeProcedureResident[--e.g.--ReadEventTime]; Loader.MakeGlobalFrameResident[--e.g.--ReadEventTime]; END.