Unix.PrecisionTimer.Mod 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. (**
  2. AUTHOR: Alexey Morozov
  3. PURPOSE: high precision timer support for Unix platforms
  4. *)
  5. MODULE PrecisionTimer;
  6. IMPORT
  7. Unix, KernelLog;
  8. TYPE
  9. Counter* = HUGEINT; (** Timer counter value type *)
  10. CONST
  11. (*
  12. The IDs of the various system clocks (for POSIX.1b interval timers):
  13. *)
  14. CLOCK_REALTIME = 0;
  15. CLOCK_MONOTONIC = 1;
  16. CLOCK_PROCESS_CPUTIME_ID = 2;
  17. CLOCK_THREAD_CPUTIME_ID = 3;
  18. CLOCK_MONOTONIC_RAW = 4;
  19. CLOCK_REALTIME_COARSE = 5;
  20. CLOCK_MONOTONIC_COARSE = 6;
  21. CLOCK_BOOTTIME = 7;
  22. CLOCK_REALTIME_ALARM = 8;
  23. CLOCK_BOOTTIME_ALARM = 9;
  24. TYPE
  25. Timespec = RECORD
  26. sec: LONGWORD;
  27. nsec: LONGINT;
  28. END;
  29. VAR
  30. clock_gettime: PROCEDURE{C}(clk_id: LONGINT; CONST tp: Timespec): LONGINT;
  31. clock_getres: PROCEDURE{C}(clk_id: LONGINT; CONST res: Timespec): LONGINT;
  32. (*! It is preferable to use CLOCK_MONOTONIC_RAW (not influenced by system time adjustments),
  33. but for some reason CLOCK_MONOTONIC is ~3 times faster
  34. *)
  35. clockType := CLOCK_MONOTONIC: LONGINT; (* timer clock type *)
  36. frequency: Counter; (* timer frequency in Hz *)
  37. (**
  38. Query timer counter in ticks
  39. *)
  40. PROCEDURE GetCounter*(): Counter;
  41. VAR t: Timespec;
  42. BEGIN
  43. IF clock_gettime(clockType, t) = 0 THEN
  44. RETURN HUGEINT(t.sec)*1000000000 + HUGEINT(t.nsec);
  45. ELSE
  46. RETURN 0;
  47. END;
  48. END GetCounter;
  49. (**
  50. Query timer tick frequency in Hz
  51. *)
  52. PROCEDURE GetFrequency*(): Counter;
  53. VAR t: Timespec;
  54. BEGIN
  55. IF clock_getres(clockType, t) = 0 THEN
  56. (*! a workaround for not known actual clock frequency *)
  57. RETURN ENTIERH(1.0D9 / t.nsec + 0.5D0);
  58. ELSE
  59. RETURN 0;
  60. END;
  61. END GetFrequency;
  62. PROCEDURE InitMod;
  63. VAR frequency: Counter;
  64. BEGIN
  65. Unix.Dlsym(Unix.libc, "clock_gettime", ADDRESSOF(clock_gettime));
  66. ASSERT(clock_gettime # NIL);
  67. Unix.Dlsym(Unix.libc, "clock_getres", ADDRESSOF(clock_getres));
  68. ASSERT(clock_getres # NIL);
  69. KernelLog.String("PrecisionTimer: timer tick frequency is "); KernelLog.Int(GetFrequency(),0); KernelLog.String(" Hz"); KernelLog.Ln;
  70. END InitMod;
  71. BEGIN
  72. InitMod;
  73. END PrecisionTimer.
  74. SystemTools.Free PrecisionTimer ~