فهرست منبع

added support of high precision event timer for Windows and Linux

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7906 8c9fc860-2736-0410-a75d-ab315db34111
eth.morozova 7 سال پیش
والد
کامیت
8d9a245961
2فایلهای تغییر یافته به همراه136 افزوده شده و 0 حذف شده
  1. 86 0
      source/Unix.PrecisionTimer.Mod
  2. 50 0
      source/Win.PrecisionTimer.Mod

+ 86 - 0
source/Unix.PrecisionTimer.Mod

@@ -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 ~

+ 50 - 0
source/Win.PrecisionTimer.Mod

@@ -0,0 +1,50 @@
+(**
+	AUTHOR: Alexey Morozov
+	PURPOSE: high precision timer support for Windows platforms
+*)
+MODULE PrecisionTimer;
+
+IMPORT
+	SYSTEM, Kernel32, KernelLog;
+
+TYPE
+	Counter* = HUGEINT;
+
+CONST
+
+	(**
+		Query timer counter in ticks
+	*)
+	PROCEDURE GetCounter*(): Counter;
+	VAR counter: Counter;
+	BEGIN
+		IF Kernel32.QueryPerformanceCounter(SYSTEM.VAL(Kernel32.LargeInteger,counter)) # 0 THEN
+			RETURN counter;
+		ELSE
+			RETURN 0;
+		END;
+	END GetCounter;
+
+	(**
+		Query timer tick frequency in Hz
+	*)
+	PROCEDURE GetFrequency*(): Counter;
+	VAR frequencyInHz: Counter;
+	BEGIN
+		IF Kernel32.QueryPerformanceFrequency(SYSTEM.VAL(Kernel32.LargeInteger,frequencyInHz)) # 0 THEN
+			RETURN frequencyInHz;
+		ELSE
+			RETURN 0;
+		END;
+	END GetFrequency;
+
+	PROCEDURE InitMod;
+	BEGIN
+		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 ~