[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