Hi,
On 09/25/2017 10:47 AM, Pierre-Marie de Rodat wrote:
The monotonic clock epoch is set to some undetermined time
in the past (typically system boot time). In order to use the
monotonic clock for absolute time, the offset from a known epoch
is calculated and incorporated into timed delay and sleep.
--- libgnarl/s-taprop__linux.adb (revision 253134)
+++ libgnarl/s-taprop__linux.adb (working copy)
@@ -257,6 +266,73 @@
end if;
end Abort_Handler;
+ ----------------------------------
+ -- Compute_Base_Monotonic_Clock --
+ ----------------------------------
+
+ function Compute_Base_Monotonic_Clock return Duration is
+ TS_Bef0, TS_Mon0, TS_Aft0 : aliased timespec;
+ TS_Bef, TS_Mon, TS_Aft : aliased timespec;
+ Bef, Mon, Aft : Duration;
+ Res_B, Res_M, Res_A : Interfaces.C.int;
+ begin
+ Res_B := clock_gettime
+ (clock_id => OSC.CLOCK_REALTIME, tp => TS_Bef0'Unchecked_Access);
+ pragma Assert (Res_B = 0);
+ Res_M := clock_gettime
+ (clock_id => OSC.CLOCK_RT_Ada, tp => TS_Mon0'Unchecked_Access);
+ pragma Assert (Res_M = 0);
+ Res_A := clock_gettime
+ (clock_id => OSC.CLOCK_REALTIME, tp => TS_Aft0'Unchecked_Access);
+ pragma Assert (Res_A = 0);
+
+ for I in 1 .. 10 loop
+ -- Guard against a leap second which will cause CLOCK_REALTIME
+ -- to jump backwards. In the extrenmely unlikely event we call
+ -- clock_gettime before and after the jump the epoch result will
+ -- be off slightly.
+ -- Use only results where the tv_sec values match for the sake
+ -- of convenience.
+ -- Also try to calculate the most accurate
+ -- epoch by taking the minimum difference of 10 tries.
+
+ Res_B := clock_gettime
+ (clock_id => OSC.CLOCK_REALTIME, tp => TS_Bef'Unchecked_Access);
+ pragma Assert (Res_B = 0);
+ Res_M := clock_gettime
+ (clock_id => OSC.CLOCK_RT_Ada, tp => TS_Mon'Unchecked_Access);
+ pragma Assert (Res_M = 0);
+ Res_A := clock_gettime
+ (clock_id => OSC.CLOCK_REALTIME, tp => TS_Aft'Unchecked_Access);
+ pragma Assert (Res_A = 0);
+
+ if (TS_Bef0.tv_sec /= TS_Aft0.tv_sec and then
+ TS_Bef.tv_sec = TS_Aft.tv_sec)
+ -- The calls to clock_gettime before the loop were no good.
+ or else
+ (TS_Bef0.tv_sec = TS_Aft0.tv_sec and then
+ TS_Bef.tv_sec = TS_Aft.tv_sec and then
+ (TS_Aft.tv_nsec - TS_Bef.tv_nsec <
+ TS_Aft0.tv_nsec - TS_Bef0.tv_nsec))
+ -- The most recent calls to clock_gettime were more better.
were more better -> were better
Best wishes, Duncan.
+ then
+ TS_Bef0.tv_sec := TS_Bef.tv_sec;
+ TS_Bef0.tv_nsec := TS_Bef.tv_nsec;
+ TS_Aft0.tv_sec := TS_Aft.tv_sec;
+ TS_Aft0.tv_nsec := TS_Aft.tv_nsec;
+ TS_Mon0.tv_sec := TS_Mon.tv_sec;
+ TS_Mon0.tv_nsec := TS_Mon.tv_nsec;
+ end if;
+ end loop;
+
+ Bef := To_Duration (TS_Bef0);
+ Mon := To_Duration (TS_Mon0);
+ Aft := To_Duration (TS_Aft0);
+
+ return Bef / 2 + Aft / 2 - Mon;
+ -- Distribute the division to avoid potential type overflow someday.
+ end Compute_Base_Monotonic_Clock;
+
--------------
-- Lock_RTS --
--------------