|
@@ -0,0 +1,86 @@
|
|
|
+(**
|
|
|
+ AUTHOR: Alexey Morozov
|
|
|
+ PURPOSE: high precision timer support for Unix platforms
|
|
|
+*)
|
|
|
+MODULE PrecisionTimer;
|
|
|
+
|
|
|
+IMPORT
|
|
|
+ Unix, KernelLog;
|
|
|
+
|
|
|
+TYPE
|
|
|
+ Counter* = HUGEINT; (** Timer counter value type *)
|
|
|
+
|
|
|
+CONST
|
|
|
+ (*
|
|
|
+ The IDs of the various system clocks (for POSIX.1b interval timers):
|
|
|
+ *)
|
|
|
+ CLOCK_REALTIME = 0;
|
|
|
+ CLOCK_MONOTONIC = 1;
|
|
|
+ CLOCK_PROCESS_CPUTIME_ID = 2;
|
|
|
+ CLOCK_THREAD_CPUTIME_ID = 3;
|
|
|
+ CLOCK_MONOTONIC_RAW = 4;
|
|
|
+ CLOCK_REALTIME_COARSE = 5;
|
|
|
+ CLOCK_MONOTONIC_COARSE = 6;
|
|
|
+ CLOCK_BOOTTIME = 7;
|
|
|
+ CLOCK_REALTIME_ALARM = 8;
|
|
|
+ CLOCK_BOOTTIME_ALARM = 9;
|
|
|
+
|
|
|
+TYPE
|
|
|
+ Timespec = RECORD
|
|
|
+ sec: LONGWORD;
|
|
|
+ nsec: LONGINT;
|
|
|
+ END;
|
|
|
+
|
|
|
+VAR
|
|
|
+ clock_gettime: PROCEDURE{C}(clk_id: LONGINT; CONST tp: Timespec): LONGINT;
|
|
|
+ clock_getres: PROCEDURE{C}(clk_id: LONGINT; CONST res: Timespec): LONGINT;
|
|
|
+
|
|
|
+ (*! It is preferable to use CLOCK_MONOTONIC_RAW (not influenced by system time adjustments),
|
|
|
+ but for some reason CLOCK_MONOTONIC is ~3 times faster
|
|
|
+ *)
|
|
|
+ clockType := CLOCK_MONOTONIC: LONGINT; (* timer clock type *)
|
|
|
+ frequency: Counter; (* timer frequency in Hz *)
|
|
|
+
|
|
|
+ (**
|
|
|
+ Query timer counter in ticks
|
|
|
+ *)
|
|
|
+ PROCEDURE GetCounter*(): Counter;
|
|
|
+ VAR t: Timespec;
|
|
|
+ BEGIN
|
|
|
+ IF clock_gettime(clockType, t) = 0 THEN
|
|
|
+ RETURN HUGEINT(t.sec)*1000000000 + HUGEINT(t.nsec);
|
|
|
+ ELSE
|
|
|
+ RETURN 0;
|
|
|
+ END;
|
|
|
+ END GetCounter;
|
|
|
+
|
|
|
+ (**
|
|
|
+ Query timer tick frequency in Hz
|
|
|
+ *)
|
|
|
+ PROCEDURE GetFrequency*(): Counter;
|
|
|
+ VAR t: Timespec;
|
|
|
+ BEGIN
|
|
|
+ IF clock_getres(clockType, t) = 0 THEN
|
|
|
+ (*! a workaround for not known actual clock frequency *)
|
|
|
+ RETURN ENTIERH(1.0D9 / t.nsec + 0.5D0);
|
|
|
+ ELSE
|
|
|
+ RETURN 0;
|
|
|
+ END;
|
|
|
+ END GetFrequency;
|
|
|
+
|
|
|
+ PROCEDURE InitMod;
|
|
|
+ VAR frequency: Counter;
|
|
|
+ BEGIN
|
|
|
+ Unix.Dlsym(Unix.libc, "clock_gettime", ADDRESSOF(clock_gettime));
|
|
|
+ ASSERT(clock_gettime # NIL);
|
|
|
+ Unix.Dlsym(Unix.libc, "clock_getres", ADDRESSOF(clock_getres));
|
|
|
+ ASSERT(clock_getres # NIL);
|
|
|
+
|
|
|
+ KernelLog.String("PrecisionTimer: timer tick frequency is "); KernelLog.Int(GetFrequency(),0); KernelLog.String(" Hz"); KernelLog.Ln;
|
|
|
+ END InitMod;
|
|
|
+
|
|
|
+BEGIN
|
|
|
+ InitMod;
|
|
|
+END PrecisionTimer.
|
|
|
+
|
|
|
+SystemTools.Free PrecisionTimer ~
|