Copyright (C) 1994, Digital Equipment Corp. MODULETickPosix EXPORTSTick ; IMPORT Utime, Word; CONST IntModulus = FLOAT(LAST(INTEGER), LONGREAL) + 1.0D0; WordModulus = 2.0D0 * IntModulus; IntModulusAsWord = Word.Plus(LAST(INTEGER), 1); VAR (*CONST*) MicrosecondsPerTick, SecondsPerTick: LONGREAL; PROCEDURENow (): T = VAR tv: Utime.struct_timeval; tz: Utime.struct_timezone; i := Utime.gettimeofday(tv, tz); d: LONGREAL; BEGIN <* ASSERT i=0 *> d := (FLOAT(tv.tv_sec, LONGREAL)*1.0D6 + FLOAT(tv.tv_usec, LONGREAL)) / MicrosecondsPerTick MOD WordModulus; IF d < IntModulus THEN RETURN TRUNC(d) ELSE RETURN Word.Plus(IntModulusAsWord, TRUNC(d-IntModulus)) END END Now; PROCEDUREToSeconds (t: Word.T): LONGREAL = BEGIN IF Word.LT(t, IntModulusAsWord) THEN RETURN FLOAT(t, LONGREAL) * SecondsPerTick ELSE RETURN (FLOAT(Word.Minus(t, IntModulusAsWord), LONGREAL) + IntModulus) * SecondsPerTick END END ToSeconds; PROCEDUREFromSeconds (s: LONGREAL): Word.T RAISES {Overflow} = BEGIN WITH d = s / SecondsPerTick DO IF d < IntModulus THEN RETURN TRUNC(d) ELSIF d < WordModulus THEN RETURN Word.Plus(IntModulusAsWord, TRUNC(d-IntModulus)) ELSE RAISE Overflow END END END FromSeconds; VAR t0, t1: T; BEGIN (* Determine value of "MicrosecondsPerTick" experimentally. Note that this will fail if this thread is descheduled for a tick during the loop below. *) MicrosecondsPerTick := 1.0D0; (* just for now! *) t0 := Now(); REPEAT t1 := Now() UNTIL t1 # t0; MicrosecondsPerTick := FLOAT(t1-t0, LONGREAL); SecondsPerTick := MicrosecondsPerTick / 1.0D6 END TickPosix.