[Ada] Use the Monotonic Clock on Linux
Duncan Sands
baldrick@free.fr
Mon Sep 25 12:36:00 GMT 2017
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 --
> --------------
More information about the Gcc-patches
mailing list