> > > It may be surprising to have the RTEMS file used by other OS. The
> > > original comment should have mentionned that in the first place, but
> > > the file was only used with RTEMS. With your change, the file is
> > > effectively shared, so it would be best to rename it.
> > 
> > Could you please suggest an appropriate file name?  This may be
> > obvious for you, but with my limited knowledge of GNAT internals, the
> > diff between s-osprim__rtems.adb and __unix/optide.adb is not
> > sufficient to guess why a separate implementation is/was required.
> 
> Would it be possible to drop it altogether and use s-osprim__posix.adb 
> instead?
> Otherwise what's the remaining difference between
> s-osprim__posix.adb and s-osprim__rtems.adb? The difference should
> help us find a proper name based on properties of the file.

At first view, it seems possible and desirable to merge _posix and
_rtems, but working on this right now would be counter-productive.

I suggest to apply patches 1-2 and fix PR114065 first.

Then the cosmetic changes in patches 3-6 (and possibly a trivial
backport of 8).

After that, we will have all the time in the long winter afternoons to
discuss file names in patch 7.

> Can you post also a diff between version 11 and version 12? It's not
> practical to review the complete changes from scratch at this stage,
> the patch is too big.

The diff between git version branches are attached.
diff --git a/gcc/ada/doc/gnat_rm/the_gnat_library.rst b/gcc/ada/doc/gnat_rm/the_gnat_library.rst
index bcec49f..58c790f 100644
--- a/gcc/ada/doc/gnat_rm/the_gnat_library.rst
+++ b/gcc/ada/doc/gnat_rm/the_gnat_library.rst
@@ -674,6 +674,8 @@ Machine-specific implementations are available in some cases.
 
 Extends the facilities provided by ``Ada.Calendar`` to include handling
 of days of the week, an extended ``Split`` and ``Time_Of`` capability.
+Also provides conversion of ``Ada.Calendar.Duration`` values to and from the
+C ``timeval`` format.
 
 .. _`GNAT.Calendar.Time_IO_(g-catiio.ads)`:
 
diff --git a/gcc/ada/libgnarl/s-osinte__android.ads b/gcc/ada/libgnarl/s-osinte__android.ads
index ee3a5dc..ecf4a32 100644
--- a/gcc/ada/libgnarl/s-osinte__android.ads
+++ b/gcc/ada/libgnarl/s-osinte__android.ads
@@ -207,7 +207,7 @@ package System.OS_Interface is
    type clockid_t is new int;
 
    function clock_gettime
-     (clock_id : clockid_t; tp : access C_time.timespec) return int;
+     (clock_id : clockid_t; tp : access C_Time.timespec) return int;
    pragma Import (C, clock_gettime, "clock_gettime");
 
    function clock_getres
diff --git a/gcc/ada/libgnat/a-calcon.ads b/gcc/ada/libgnat/a-calcon.ads
index ad4ca64..196028e 100644
--- a/gcc/ada/libgnat/a-calcon.ads
+++ b/gcc/ada/libgnat/a-calcon.ads
@@ -30,9 +30,10 @@
 ------------------------------------------------------------------------------
 
 --  This package provides various routines for conversion between Ada and Unix
---  time models - Time, Duration and struct tm.
+--  time models - Time, Duration, struct tm and struct timespec.
 
 with Interfaces.C;
+with System.C_Time;
 
 package Ada.Calendar.Conversions is
 
@@ -67,6 +68,20 @@ package Ada.Calendar.Conversions is
    --  the input values are out of the defined ranges or if tm_sec equals 60
    --  and the instance in time is not a leap second occurrence.
 
+   function To_Duration
+     (tv_sec  : System.C_Time.Tv_Sec_Long;
+      tv_nsec : System.C_Time.Tv_Nsec_Long)
+     return System.C_Time.Non_Negative_Duration
+   renames System.C_Time.To_Duration;
+   --  Deprecated.  Please use C_Time directly.
+
+   procedure To_Struct_Timespec
+     (D       : System.C_Time.Non_Negative_Duration;
+      tv_sec  : out System.C_Time.Tv_Sec_Long;
+      tv_nsec : out System.C_Time.Tv_Nsec_Long)
+   renames System.C_Time.To_Struct_Timespec;
+   --  Deprecated.  Please use C_Time directly.
+
    procedure To_Struct_Tm
      (T       : Time;
       tm_year : out Interfaces.C.int;
diff --git a/gcc/ada/libgnat/g-calend.ads b/gcc/ada/libgnat/g-calend.ads
index f317ab4..7791943 100644
--- a/gcc/ada/libgnat/g-calend.ads
+++ b/gcc/ada/libgnat/g-calend.ads
@@ -40,6 +40,7 @@
 --  Day_Of_Week, Day_In_Year and Week_In_Year.
 
 with Ada.Calendar.Formatting;
+with System.C_Time;
 
 package GNAT.Calendar is
 
@@ -144,6 +145,19 @@ package GNAT.Calendar is
    --  Return the week number as defined in ISO 8601 along with the year in
    --  which the week occurs.
 
+   subtype timeval is System.C_Time.timeval;
+   --  Deprecated.  Please use C_Time directly.
+
+   function To_Duration (T : not null access timeval)
+                        return System.C_Time.Non_Negative_Duration
+     with Inline
+   is (System.C_Time.To_Duration (T.all));
+   --  Deprecated.  Please use C_Time directly.
+
+   function To_Timeval (D : System.C_Time.Non_Negative_Duration) return timeval
+   renames System.C_Time.To_Timeval;
+   --  Deprecated.  Please use C_Time directly.
+
 private
 
    function Julian_Day
diff --git a/gcc/ada/libgnat/s-c_time.adb b/gcc/ada/libgnat/s-c_time.adb
index 26820a4..d44727c 100644
--- a/gcc/ada/libgnat/s-c_time.adb
+++ b/gcc/ada/libgnat/s-c_time.adb
@@ -36,6 +36,9 @@ package body System.C_Time is
    --   32    0.02                   42_949_672.94
    --   64    0.000_000_001       9_223_372_036.854_775_807
 
+   --  The overflows listed in comments must raise Constraint_Error.
+   pragma Unsuppress (Overflow_Check);
+
    -----------------
    -- In_Duration --
    -----------------
@@ -72,7 +75,7 @@ package body System.C_Time is
    -- Milliseconds_To_Timeval --
    -----------------------------
 
-   function Milliseconds_To_Timeval (M : Interfaces.C.int) return timeval is
+   function Milliseconds_To_Timeval (M : Non_Negative_Int) return timeval is
       use Interfaces.C;
       Q : constant int range 0 .. int'Last / 1_000 := M  /  1_000;
       R : constant int range 0 .. 999              := M mod 1_000;
@@ -85,7 +88,7 @@ package body System.C_Time is
    -- Nanoseconds_To_Timespec --
    -----------------------------
 
-   function Nanoseconds_To_Timespec (N : Interfaces.C.int) return timespec is
+   function Nanoseconds_To_Timespec (N : Non_Negative_Int) return timespec is
       use Interfaces.C;
       Q : constant int range 0 .. int'Last / 10**9 := N  /  10**9;
       R : constant int range 0 .. 999_999_999      := N mod 10**9;
@@ -98,31 +101,60 @@ package body System.C_Time is
    -- To_Duration --
    -----------------
 
-   function To_Duration (T : timeval) return Duration is
+   function To_Duration (T : timeval) return Non_Negative_Duration is
+      Usec : usec_t range 0 .. 1_009_999;
       Frac : Duration range 0.0 .. 1.0;
    begin
       if Duration'Size = 64 then
-         Frac := Duration (T.tv_usec)          / 1_000_000;
+         Usec := T.tv_usec;
       else
-         --  Fix the rounding (999_999.0 / 1_000_000 = 0.98).
-         Frac := Duration (T.tv_usec + 10_000) / 1_000_000;
+         --  Fix the rounding (999_999.0 / 1_000_000 = 0.98)
+         --  with a bias of half Duration'Small = 10 ms.
+         Usec := T.tv_usec + 10_000;
       end if;
+      Frac := Duration (Usec) / 1_000_000;
+
       return Duration (T.tv_sec) + Frac;
+      --  Both the conversion and the addition may overflow.
    end To_Duration;
 
-   function To_Duration (T : timespec) return Duration is
+   function To_Duration (T : timespec) return Non_Negative_Duration is
       Frac : Duration range 0.0 .. 1.0;
    begin
       if Duration'Size = 64 then
          Frac := Duration (T.tv_nsec) / 1_000_000_000;
       else
          --  Avoid an overflow (Duration'Last < 999_999_999).
-         --  Fix the rounding (999_999_999.0 / 1_000_000_000 = 0.98).
+         --  Fix the rounding (999_999_999.0 / 1_000_000_000 = 0.98)
+         --  with a bias of half Duration'Small = 10 ms.
          Frac := Duration (T.tv_nsec / 10_000_000 + 1) / 100;
       end if;
+
       return Duration (T.tv_sec) + Frac;
+      --  Both the conversion and the addition may overflow.
    end To_Duration;
 
+   function To_Duration (tv_sec  : Tv_Sec_Long;
+                         tv_nsec : Tv_Nsec_Long)
+                        return Non_Negative_Duration is
+   begin
+      return To_Duration (timespec'(tv_sec  => time_t (tv_sec),
+                                    tv_nsec => nsec_t (tv_nsec)));
+   end To_Duration;
+
+   ------------------------
+   -- To_Struct_Timespec --
+   ------------------------
+
+   procedure To_Struct_Timespec (D       : Non_Negative_Duration;
+                                 tv_sec  : out Tv_Sec_Long;
+                                 tv_nsec : out Tv_Nsec_Long) is
+      T : constant timespec := To_Timespec (D);
+   begin
+      tv_sec  := Tv_Sec_Long (T.tv_sec);  --  May overflow Interfaces.C.long.
+      tv_nsec := Tv_Nsec_Long (T.tv_nsec);
+   end To_Struct_Timespec;
+
    -----------------
    -- To_Timespec --
    -----------------
@@ -133,7 +165,7 @@ package body System.C_Time is
               tv_nsec => 1_000 * nsec_t (T.tv_usec));
    end To_Timespec;
 
-   function To_Timespec (D : Duration) return timespec is
+   function To_Timespec (D : Non_Negative_Duration) return timespec is
       --  See To_Timeval.
       Dm1  : constant Duration range -1.0 .. Duration'Last - 1.0 := D - 1.0;
       Sec  : constant time_t range -1 .. time_t'Last := time_t (Dm1);
@@ -143,13 +175,14 @@ package body System.C_Time is
       if Duration'Size = 64 then
          Nsec := nsec_t (1_000_000_000 * Frac);
       else
-         --  Avoid an overflow when Duration'Last < 999_999_999.
-         Nsec := 10_000_000 * nsec_t (100 * Frac);
+         --  Duration'Last < 500_000_000 so there is an overflow issue,
+         --  easy to solve because Frac has few significative digits.
+         Nsec := 20_000_000 * nsec_t (50 * Frac);
       end if;
       if Nsec < 0 then
-         return (Sec,     Nsec + 1_000_000_000);
+         return (tv_sec => Sec,     tv_nsec => Nsec + 1_000_000_000);
       else
-         return (Sec + 1, Nsec);
+         return (tv_sec => Sec + 1, tv_nsec => Nsec);
       end if;
    end To_Timespec;
 
@@ -157,7 +190,9 @@ package body System.C_Time is
    -- To_Timeval --
    -----------------
 
-   function To_Timeval (D : Duration) return timeval is
+   function To_Timeval (D : Non_Negative_Duration) return timeval is
+
+      --   Most comments also apply to the timespec variant.
 
       --    Sec := time_t (D);
       --    Usec := usec_t (1_000_000 * (D - Duration (Sec)));
@@ -167,17 +202,25 @@ package body System.C_Time is
 
       --    Sec := time_t (D - 0.5);
       --    Usec := usec_t (1_000_000 * (D - Duration (Sec)));
-      --  fails when D is
-      --    0.0           (Sec is rounded down and Usec = 1_000_000)
-      --    0.999_999_999 (Usec is rounded up to 1_000_000)
+      --  leads to Usec = 1_000_000 when D is
+      --    0.0           (Sec is rounded down)
+      --    0.999_999_999 (Usec is rounded up) (not an issue with timespec)
 
-      --  Converting D - 1 seems to solve overflow and simplify roundings.
       Dm1  : constant Duration range -1.0 .. Duration'Last - 1.0 := D - 1.0;
+      --  Converting D - 1 avoids overflows and simplifies roundings.
+
       Sec  : constant time_t range -1 .. time_t'Last := time_t (Dm1);
+      --  The conversion of Dm1 may overflow if time_t has 32 bits.
+
       Frac : constant Duration range -0.5 .. 0.5 := Dm1 - Duration (Sec);
+      --  The conversion back is always possible, Sec <= Duration'Last - 0.5.
+
       Usec : constant usec_t range -500_000 .. 500_000
         := usec_t (1_000_000 * Frac);
    begin
+      --  Add the second substracted at the beginning, in a way fixing
+      --  the Usec interval if necessary.
+      --  In both cases, tv_sec may exceed MAX_tv_sec.
       if Usec < 0 then
          return (tv_sec => Sec,     tv_usec => Usec + 1_000_000);
       else
diff --git a/gcc/ada/libgnat/s-c_time.ads b/gcc/ada/libgnat/s-c_time.ads
index e943dd0..8eaf22d 100644
--- a/gcc/ada/libgnat/s-c_time.ads
+++ b/gcc/ada/libgnat/s-c_time.ads
@@ -36,50 +36,63 @@ with Interfaces.C;
 private with System.OS_Constants;
 
 package System.C_Time
-  with Preelaborate
+  with Pure
 is
 
-   type timeval is private;  --  Non negative duration in microseconds.
+   --  These C structs represent non negative durations with different
+   --  accuracies and maximal values.
+   type timespec is private;  --  accurate to 1  nanosecond
+   type timeval  is private;  --  accurate to 1 microsecond
 
-   Timeval_Zero : constant timeval;
-   --  g-sothco.ads
-
-   function To_Timeval (D : Duration) return timeval
-     with Pre => 0.0 <= D;
-   --  The value is rounded if Duration'Size = 64.
-
-   function In_Duration (T : timeval) return Boolean
-     with Inline;
-   --  True if computing To_Duration (T) is safe,
-   --  False if Constraint Error would be raised.
+   --  Duration is accurate to either 1 nanosecond or 20 milliseconds.
+   subtype Non_Negative_Duration is Duration range 0.0 .. Duration'Last;
 
-   function To_Duration (T : timeval) return Duration
-     with Post => 0.0 <= To_Duration'Result;
-   --  The value is rounded if Duration'Size = 32.
+   --  All conversions round if the target type is less accurate than
+   --  the source type, away from zero if the source value is midway
+   --  between two values of the target type.
+   --  They raise Constraint_Error when the value, after rounding,
+   --  exceeds the last value of the target type.
 
-   type timespec is private;  --  Non negative duration in nanoseconds.
+   function To_Duration (T : timespec) return Non_Negative_Duration;
+   function To_Duration (T : timeval)  return Non_Negative_Duration;
 
-   function To_Timespec (D : Duration) return timespec
-     with Pre => 0.0 <= D;
+   function To_Timespec (D : Non_Negative_Duration) return timespec;
+   function To_Timeval  (D : Non_Negative_Duration) return timeval;
 
-   function To_Duration (T : timespec) return Duration
-     with Post => 0.0 <= To_Duration'Result;
-   --  The value is rounded if Duration'Size = 32.
+   Timeval_Zero : constant timeval;
+   --  g-sothco.ads
 
-   --  Direct conversions avoiding an intermediate Duration that may
-   --  loose precision (when Duration'Size = 32) or overflow (when
-   --  time_t'Size = 64).
+   function In_Duration (T : timeval) return Boolean with Inline;
+   --  True if computing To_Duration (T) is safe,
+   --  False if Constraint Error would be raised.
+   --  g-socket.adb:
 
-   function Milliseconds_To_Timeval (M : Interfaces.C.int) return timeval
-     with Inline,
-          Pre => Interfaces.C."<=" (0, M);
+   subtype Non_Negative_Int is
+     Interfaces.C.int range 0 .. Interfaces.C.int'Last;
 
-   function Nanoseconds_To_Timespec (N : Interfaces.C.int) return timespec
-     with Inline,
-          Pre => Interfaces.C."<=" (0, N);
+   function Milliseconds_To_Timeval (M : Non_Negative_Int) return timeval
+     with Inline;
+   --  g-spogwa.adb
 
-   function To_Timespec (T : timeval) return timespec
+   function Nanoseconds_To_Timespec (N : Non_Negative_Int) return timespec
+     with Inline;
+   function To_Timespec (T : timeval) return timespec with Inline;
+   --  s-osinte__darwin.adb
+
+   --  These functions are provided for backward compatibility,
+   --  but lead to non portable interfaces with C.
+   --  Tv_sec and tv_nsec do not match the long int type on x32,
+   --  or on 32 bits ARM with a 2038-compatible GNU libc.
+
+   subtype Tv_Sec_Long  is Interfaces.C.long range 0 .. Interfaces.C.long'Last;
+   subtype Tv_Nsec_Long is Interfaces.C.long range 0 .. 999_999_999;
+   function To_Duration (tv_sec  : Tv_Sec_Long;
+                         tv_nsec : Tv_Nsec_Long) return Non_Negative_Duration
      with Inline;
+   procedure To_Struct_Timespec (D       : Non_Negative_Duration;
+                                 tv_sec  : out Tv_Sec_Long;
+                                 tv_nsec : out Tv_Nsec_Long) with Inline;
+   --  a-calcon.ads
 
 private
 
diff --git a/gcc/ada/libgnat/s-os_lib.adb b/gcc/ada/libgnat/s-os_lib.adb
index 976d39c..20e109a 100644
--- a/gcc/ada/libgnat/s-os_lib.adb
+++ b/gcc/ada/libgnat/s-os_lib.adb
@@ -2980,7 +2980,7 @@ package body System.OS_Lib is
    -- To_Ada --
    ------------
 
-   function To_Ada (Time : Long_Long_Integer) return OS_Time is
+   function To_Ada (Time : time_t) return OS_Time is
    begin
       return OS_Time (Time);
    end To_Ada;
@@ -3014,6 +3014,15 @@ package body System.OS_Lib is
       return Return_Val;
    end To_Path_String_Access;
 
+   ----------
+   -- To_C --
+   ----------
+
+   function To_C (Time : OS_Time) return time_t is
+   begin
+      return time_t (Time);
+   end To_C;
+
    ------------------
    -- Wait_Process --
    ------------------
diff --git a/gcc/ada/libgnat/s-os_lib.ads b/gcc/ada/libgnat/s-os_lib.ads
index c69e357..10157b6 100644
--- a/gcc/ada/libgnat/s-os_lib.ads
+++ b/gcc/ada/libgnat/s-os_lib.ads
@@ -165,8 +165,15 @@ package System.OS_Lib is
    -- Time_t Stuff --
    ------------------
 
-   function To_Ada (Time : Long_Long_Integer) return OS_Time;
-   --  Convert C time_t type to OS_Time
+   --  Note: Do not use time_t in the compiler and host-based tools; instead
+   --  use OS_Time.
+
+   subtype time_t is Long_Long_Integer;
+   --  Supported for backward compatibility, but no longer related
+   --  with the C time_t type.  For that, see System.C_Time.
+
+   function To_C (Time : OS_Time) return time_t;
+   function To_Ada (Time : time_t) return OS_Time;
 
    ----------------
    -- File Stuff --
@@ -1105,6 +1112,7 @@ private
    pragma Import (Intrinsic, ">");
    pragma Import (Intrinsic, "<=");
    pragma Import (Intrinsic, ">=");
+   pragma Inline (To_C);
    pragma Inline (To_Ada);
 
    type Process_Id is new Integer;
diff --git a/gcc/ada/libgnat/s-osprim__rtems.adb b/gcc/ada/libgnat/s-osprim__rtems.adb
index f7b607a..6116345 100644
--- a/gcc/ada/libgnat/s-osprim__rtems.adb
+++ b/gcc/ada/libgnat/s-osprim__rtems.adb
@@ -29,7 +29,7 @@
 --                                                                          --
 ------------------------------------------------------------------------------
 
---  This version is for POSIX-like operating systems
+--  This version is for POSIX-like operating systems, Darwin and Linux/x32.
 
 with System.C_Time;
 
diff --git a/gcc/ada/libgnat/s-osprim__unix.adb b/gcc/ada/libgnat/s-osprim__unix.adb
index c1c7e51..62e5e59 100644
--- a/gcc/ada/libgnat/s-osprim__unix.adb
+++ b/gcc/ada/libgnat/s-osprim__unix.adb
@@ -30,7 +30,8 @@
 ------------------------------------------------------------------------------
 
 --  This version uses gettimeofday and select
---  This file is suitable for OpenNT, Dec Unix and SCO UnixWare.
+--  This file is suitable for OpenNT, Dec Unix, SCO UnixWare
+--  and Solaris (32 and 64 bits).
 
 with System.C_Time;
 
diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c
index 8551d78..f579c93 100644
--- a/gcc/ada/s-oscons-tmplt.c
+++ b/gcc/ada/s-oscons-tmplt.c
@@ -1740,9 +1740,9 @@ CND(IPV6_V6ONLY, "Restricted to IPv6 communications only")
    --  Sizes (in bytes) of the components of struct timeval
 */
 #define SIZEOF_tv_sec (sizeof tv.tv_sec)
-CND(SIZEOF_tv_sec, "tv_sec, time_t")
+CND(SIZEOF_tv_sec, "tv_sec")
 #define SIZEOF_tv_usec (sizeof tv.tv_usec)
-CND(SIZEOF_tv_usec, "tv_usec, suseconds_t")
+CND(SIZEOF_tv_usec, "tv_usec")
 /*
 
    --  Maximum allowed value for tv_sec
@@ -1772,7 +1772,7 @@ CNS(MAX_tv_sec, "")
    --  The tv_sec field is the same than in struct timeval.
 */
 #define SIZEOF_tv_nsec (sizeof (ts.tv_nsec))
-CND(SIZEOF_tv_nsec, "tv_nsec, long except on x32");
+CND(SIZEOF_tv_nsec, "tv_nsec");
 }
 
 /*
diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c
index f579c93..a64e578 100644
--- a/gcc/ada/s-oscons-tmplt.c
+++ b/gcc/ada/s-oscons-tmplt.c
@@ -1785,7 +1785,7 @@ CND(SIZEOF_tv_nsec, "tv_nsec");
    --  The test is safe in files that do not require GNU specifically.
 
 */
-#ifdef __USE_TIME_BITS64
+#if defined(__USE_TIME64_REDIRECTS) || (__TIMESIZE == 32 && __USE_TIME_BITS64)
   C("Glibc_Use_Time_Bits64", Boolean, "True", "Y2038 Glibc transition")
 #else
   C("Glibc_Use_Time_Bits64", Boolean, "False", "Y2038 Glibc transition")
diff --git a/gcc/ada/libgnat/g-calend.ads b/gcc/ada/libgnat/g-calend.ads
index 7791943..4a21d49 100644
--- a/gcc/ada/libgnat/g-calend.ads
+++ b/gcc/ada/libgnat/g-calend.ads
@@ -150,7 +150,6 @@ package GNAT.Calendar is
 
    function To_Duration (T : not null access timeval)
                         return System.C_Time.Non_Negative_Duration
-     with Inline
    is (System.C_Time.To_Duration (T.all));
    --  Deprecated.  Please use C_Time directly.
 
diff --git a/gcc/ada/libgnat/s-c_time.adb b/gcc/ada/libgnat/s-c_time.adb
index d44727c..4a96c8d 100644
--- a/gcc/ada/libgnat/s-c_time.adb
+++ b/gcc/ada/libgnat/s-c_time.adb
@@ -67,8 +67,8 @@ package body System.C_Time is
       Maybe_Sec : constant := (if Dur_Covers_Tv_Sec then 1 else Sec);
    begin
       return Dur_Covers_Tv_Sec
-             or else  T.tv_sec < Maybe_Sec
-             or else (T.tv_sec = Maybe_Sec and then T.tv_usec <= Usec);
+        or else  T.tv_sec < Maybe_Sec
+        or else (T.tv_sec = Maybe_Sec and then T.tv_usec <= Usec);
    end In_Duration;
 
    -----------------------------
diff --git a/gcc/ada/libgnarl/a-exetim__posix.adb b/gcc/ada/libgnarl/a-exetim__posix.adb
index db873fb..7fbd6c1 100644
--- a/gcc/ada/libgnarl/a-exetim__posix.adb
+++ b/gcc/ada/libgnarl/a-exetim__posix.adb
@@ -35,6 +35,7 @@ with Ada.Task_Identification;  use Ada.Task_Identification;
 with Ada.Unchecked_Conversion;
 
 with System.C_Time;
+with System.OS_Constants;
 with System.Tasking;
 with System.OS_Interface; use System.OS_Interface;
 with System.Task_Primitives.Operations; use System.Task_Primitives.Operations;
@@ -115,7 +116,9 @@ package body Ada.Execution_Time is
         (clock_id : Interfaces.C.int;
          tp       : access System.C_Time.timespec)
          return int;
-      pragma Import (C, clock_gettime, "clock_gettime");
+      pragma Import (C, clock_gettime,
+        (if System.OS_Constants.Glibc_Use_Time_Bits64
+         then "__clock_gettime64" else "clock_gettime"));
       --  Function from the POSIX.1b Realtime Extensions library
 
       function pthread_getcpuclockid
diff --git a/gcc/ada/libgnarl/s-linux__loongarch.ads b/gcc/ada/libgnarl/s-linux__loongarch.ads
index 44d8c65..ae22441 100644
--- a/gcc/ada/libgnarl/s-linux__loongarch.ads
+++ b/gcc/ada/libgnarl/s-linux__loongarch.ads
@@ -43,7 +43,6 @@ package System.Linux is
    -- Time --
    ----------
 
-   subtype int         is Interfaces.C.int;
    subtype clockid_t   is Interfaces.C.int;
 
    -----------
diff --git a/gcc/ada/libgnarl/s-osinte__gnu.ads b/gcc/ada/libgnarl/s-osinte__gnu.ads
index b4597c5..90ef2d5 100644
--- a/gcc/ada/libgnarl/s-osinte__gnu.ads
+++ b/gcc/ada/libgnarl/s-osinte__gnu.ads
@@ -39,6 +39,7 @@
 --  Preelaborate. This package is designed to be a bottom-level (leaf) package
 
 with Interfaces.C;
+with System.Os_Constants;
 with System.C_Time;
 with Ada.Unchecked_Conversion;
 
@@ -208,7 +209,8 @@ package System.OS_Interface is
    --  Indicates whether time slicing is supported (i.e SCHED_RR is supported)
 
    function nanosleep (rqtp, rmtp : access C_Time.timespec) return int;
-   pragma Import (C, nanosleep, "nanosleep");
+   pragma Import (C, nanosleep, (if OS_Constants.Glibc_Use_Time_Bits64
+     then "__nanosleep64" else "nanosleep"));
 
    type clockid_t is new int;
    CLOCK_REALTIME : constant clockid_t := 0;
@@ -218,12 +220,14 @@ package System.OS_Interface is
      (clock_id : clockid_t;
       tp       : access C_Time.timespec)
       return int;
-   pragma Import (C, clock_gettime, "clock_gettime");
+   pragma Import (C, clock_gettime, (if OS_Constants.Glibc_Use_Time_Bits64
+     then "__clock_gettime64" else "clock_gettime"));
 
    function clock_getres
      (clock_id : clockid_t;
       res      : access C_Time.timespec) return int;
-   pragma Import (C, clock_getres, "clock_getres");
+   pragma Import (C, clock_getres, (if OS_Constants.Glibc_Use_Time_Bits64
+     then "__clock_getres64" else "clock_getres"));
 
    --  From: /usr/include/unistd.h
    function sysconf (name : int) return long;
@@ -477,7 +481,9 @@ package System.OS_Interface is
      (cond    : access pthread_cond_t;
       mutex   : access pthread_mutex_t;
       abstime : access C_Time.timespec) return int;
-   pragma Import (C, pthread_cond_timedwait, "pthread_cond_timedwait");
+   pragma Import (C, pthread_cond_timedwait,
+     (if OS_Constants.Glibc_Use_Time_Bits64 then "__pthread_cond_timedwait64"
+      else "pthread_cond_timedwait"));
 
    Relative_Timed_Wait : constant Boolean := False;
    --  pthread_cond_timedwait requires an absolute delay time
diff --git a/gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads b/gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads
index 9b40c9a..59e6f79 100644
--- a/gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads
+++ b/gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads
@@ -40,6 +40,7 @@
 
 with Ada.Unchecked_Conversion;
 with Interfaces.C;
+with System.OS_Constants;
 with System.C_Time;
 
 package System.OS_Interface is
@@ -203,7 +204,8 @@ package System.OS_Interface is
    --  Indicates whether time slicing is supported (i.e SCHED_RR is supported)
 
    function nanosleep (rqtp, rmtp : access C_Time.timespec) return int;
-   pragma Import (C, nanosleep, "nanosleep");
+   pragma Import (C, nanosleep, (if OS_Constants.Glibc_Use_Time_Bits64
+     then "__nanosleep64" else "nanosleep"));
 
    type clockid_t is new int;
    CLOCK_REALTIME : constant clockid_t := 0;
@@ -212,12 +214,14 @@ package System.OS_Interface is
      (clock_id : clockid_t;
       tp       : access C_Time.timespec)
       return int;
-   pragma Import (C, clock_gettime, "clock_gettime");
+   pragma Import (C, clock_gettime, (if OS_Constants.Glibc_Use_Time_Bits64
+     then "__clock_gettime64" else "clock_gettime");
 
    function clock_getres
      (clock_id : clockid_t;
       res      : access C_Time.timespec) return int;
-   pragma Import (C, clock_getres, "clock_getres");
+   pragma Import (C, clock_getres, (if OS_Constants.Glibc_Use_Time_Bits64
+     then "__clock_getres64" else "clock_getres");
 
    function sysconf (name : int) return long;
    pragma Import (C, sysconf);
@@ -420,7 +424,9 @@ package System.OS_Interface is
      (cond    : access pthread_cond_t;
       mutex   : access pthread_mutex_t;
       abstime : access C_Time.timespec) return int;
-   pragma Import (C, pthread_cond_timedwait, "pthread_cond_timedwait");
+   pragma Import (C, pthread_cond_timedwait,
+     (if OS_Constants.Glibc_Use_Time_Bits64 then "__pthread_cond_timedwait64"
+      else "pthread_cond_timedwait");
 
    --------------------------
    -- POSIX.1c  Section 13 --
diff --git a/gcc/ada/libgnarl/s-osinte__linux.ads b/gcc/ada/libgnarl/s-osinte__linux.ads
index 9de227e..7a0d37d 100644
--- a/gcc/ada/libgnarl/s-osinte__linux.ads
+++ b/gcc/ada/libgnarl/s-osinte__linux.ads
@@ -229,12 +229,14 @@ package System.OS_Interface is
 
    function clock_gettime
      (clock_id : clockid_t; tp : access C_Time.timespec) return int;
-   pragma Import (C, clock_gettime, "clock_gettime");
+   pragma Import (C, clock_gettime, (if OS_Constants.Glibc_Use_Time_Bits64
+     then "__clock_gettime64" else "clock_gettime"));
 
    function clock_getres
      (clock_id : clockid_t;
       res      : access C_Time.timespec) return int;
-   pragma Import (C, clock_getres, "clock_getres");
+   pragma Import (C, clock_getres, (if OS_Constants.Glibc_Use_Time_Bits64
+     then "__clock_getres64" else "clock_getres"));
 
    function sysconf (name : int) return long;
    pragma Import (C, sysconf);
@@ -445,7 +447,9 @@ package System.OS_Interface is
      (cond    : access pthread_cond_t;
       mutex   : access pthread_mutex_t;
       abstime : access C_Time.timespec) return int;
-   pragma Import (C, pthread_cond_timedwait, "pthread_cond_timedwait");
+   pragma Import (C, pthread_cond_timedwait,
+     (if OS_Constants.Glibc_Use_Time_Bits64 then "__pthread_cond_timedwait64"
+      else "pthread_cond_timedwait"));
 
    --------------------------
    -- POSIX.1c  Section 13 --
diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb
index ccc4feb..02c2bab 100644
--- a/gcc/ada/libgnat/g-socket.adb
+++ b/gcc/ada/libgnat/g-socket.adb
@@ -2629,6 +2629,7 @@ package body GNAT.Sockets is
               (1 .. (if Option.Name = Bind_To_Device
                      then C.size_t (ASU.Length (Option.Device) + 1)
                      else 0));
+      VT  : aliased System.C_Time.timeval;
       Len : C.int;
       Add : System.Address := Null_Address;
       Res : C.int;
diff --git a/gcc/ada/libgnat/g-spogwa.adb b/gcc/ada/libgnat/g-spogwa.adb
index 530a6cd..598f3fc 100644
--- a/gcc/ada/libgnat/g-spogwa.adb
+++ b/gcc/ada/libgnat/g-spogwa.adb
@@ -42,7 +42,9 @@ is
       writefds  : access FD_Set_Type;
       exceptfds : access FD_Set_Type;
       timeout   : access System.C_Time.timeval) return Integer
-     with Import => True, Convention => Stdcall, External_Name => "select";
+     with Import => True, Convention => Stdcall,
+       External_Name => (if System.OS_Constants.Glibc_Use_Time_Bits64
+         then "__select64" else "select");
 
    Timeout_V : aliased System.C_Time.timeval;
    Timeout_A : access System.C_Time.timeval;
diff --git a/gcc/ada/libgnat/s-optide.adb b/gcc/ada/libgnat/s-optide.adb
index 4ad16a2..a9025d0 100644
--- a/gcc/ada/libgnat/s-optide.adb
+++ b/gcc/ada/libgnat/s-optide.adb
@@ -41,7 +41,8 @@ is
                       return Integer
      with Import,
           Convention => C,
-          External_Name => "nanosleep";
+          External_Name => (if OS_Constants.Glibc_Use_Time_Bits64
+            then "__nanosleep64" else "nanosleep");
 
    Request    : aliased C_Time.timespec;
    Remaind    : aliased C_Time.timespec;
diff --git a/gcc/ada/libgnat/s-osprim__posix.adb b/gcc/ada/libgnat/s-osprim__posix.adb
index b331d5c..f647968 100644
--- a/gcc/ada/libgnat/s-osprim__posix.adb
+++ b/gcc/ada/libgnat/s-osprim__posix.adb
@@ -31,6 +31,7 @@
 
 --  This version is for POSIX-like operating systems
 with System.C_Time;
+with System.OS_Constants;
 
 package body System.OS_Primitives is
 
@@ -47,7 +48,8 @@ package body System.OS_Primitives is
       function gettimeofday
         (Tv : access C_Time.timeval;
          Tz : System.Address := System.Null_Address) return Integer;
-      pragma Import (C, gettimeofday, "gettimeofday");
+      pragma Import (C, gettimeofday, (if OS_Constants.Glibc_Use_Time_Bits64
+        then "__gettimeofday64" else "gettimeofday"));
 
    begin
       --  The return codes for gettimeofday are as follows (from man pages):
diff --git a/gcc/ada/libgnat/s-osprim__posix2008.adb b/gcc/ada/libgnat/s-osprim__posix2008.adb
index 7f44efa..0dbde83 100644
--- a/gcc/ada/libgnat/s-osprim__posix2008.adb
+++ b/gcc/ada/libgnat/s-osprim__posix2008.adb
@@ -54,7 +54,8 @@ package body System.OS_Primitives is
       function clock_gettime
         (clock_id : clockid_t;
          tp       : access C_Time.timespec) return int;
-      pragma Import (C, clock_gettime, "clock_gettime");
+      pragma Import (C, clock_gettime, (if OS_Constants.Glibc_Use_Time_Bits64
+        thon "__clock_gettime64" else "clock_gettime"));
 
    begin
       Result := clock_gettime (CLOCK_REALTIME, TS'Unchecked_Access);
diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c
index 5beb929..8551d78 100644
--- a/gcc/ada/s-oscons-tmplt.c
+++ b/gcc/ada/s-oscons-tmplt.c
@@ -1775,6 +1775,22 @@ CNS(MAX_tv_sec, "")
 CND(SIZEOF_tv_nsec, "tv_nsec, long except on x32");
 }
 
+/*
+
+   --  Functions with time_t suseconds_t timeval timespec parameters like
+   --    clock_get{res,time} gettimeofday nanosleep
+   --    pthread_cond_{,timed}wait select
+   --  must be imported from the GNU C library with
+   --    External_Name => (if Glibc_Use_Time_Bits64 then "__foo64" else "foo")
+   --  The test is safe in files that do not require GNU specifically.
+
+*/
+#ifdef __USE_TIME_BITS64
+  C("Glibc_Use_Time_Bits64", Boolean, "True", "Y2038 Glibc transition")
+#else
+  C("Glibc_Use_Time_Bits64", Boolean, "False", "Y2038 Glibc transition")
+#endif
+
 /*
 
    --  Sizes of various data types
diff --git a/gcc/ada/libgnat/s-c_time.adb b/gcc/ada/libgnat/s-c_time.adb
index 9f862ec..26820a4 100644
--- a/gcc/ada/libgnat/s-c_time.adb
+++ b/gcc/ada/libgnat/s-c_time.adb
@@ -78,7 +78,7 @@ package body System.C_Time is
       R : constant int range 0 .. 999              := M mod 1_000;
    begin
       return (tv_sec  => time_t (Q),
-              tv_usec => 1_000 * suseconds_t (R));
+              tv_usec => 1_000 * usec_t (R));
    end Milliseconds_To_Timeval;
 
    -----------------------------
@@ -90,8 +90,8 @@ package body System.C_Time is
       Q : constant int range 0 .. int'Last / 10**9 := N  /  10**9;
       R : constant int range 0 .. 999_999_999      := N mod 10**9;
    begin
-      return (tv_sec  =>      time_t (Q),
-              tv_nsec => snseconds_t (R));
+      return (tv_sec  => time_t (Q),
+              tv_nsec => nsec_t (R));
    end Nanoseconds_To_Timespec;
 
    -----------------
@@ -130,7 +130,7 @@ package body System.C_Time is
    function To_Timespec (T : timeval) return timespec is
    begin
       return (tv_sec  => T.tv_sec,
-              tv_nsec => 1_000 * snseconds_t (T.tv_usec));
+              tv_nsec => 1_000 * nsec_t (T.tv_usec));
    end To_Timespec;
 
    function To_Timespec (D : Duration) return timespec is
@@ -138,13 +138,13 @@ package body System.C_Time is
       Dm1  : constant Duration range -1.0 .. Duration'Last - 1.0 := D - 1.0;
       Sec  : constant time_t range -1 .. time_t'Last := time_t (Dm1);
       Frac : constant Duration range -0.5 .. 0.5 := Dm1 - Duration (Sec);
-      Nsec : snseconds_t range -500_000_000 .. 500_000_000;
+      Nsec : nsec_t range -500_000_000 .. 500_000_000;
    begin
       if Duration'Size = 64 then
-         Nsec := snseconds_t (1_000_000_000 * Frac);
+         Nsec := nsec_t (1_000_000_000 * Frac);
       else
          --  Avoid an overflow when Duration'Last < 999_999_999.
-         Nsec := 10_000_000 * snseconds_t (100 * Frac);
+         Nsec := 10_000_000 * nsec_t (100 * Frac);
       end if;
       if Nsec < 0 then
          return (Sec,     Nsec + 1_000_000_000);
@@ -160,13 +160,13 @@ package body System.C_Time is
    function To_Timeval (D : Duration) return timeval is
 
       --    Sec := time_t (D);
-      --    Usec := suseconds_t (1_000_000 * (D - Duration (Sec)));
+      --    Usec := usec_t (1_000_000 * (D - Duration (Sec)));
       --  fails when D is
       --    Duration'Last (Sec is rounded up and Duration (Sec) overflows)
       --    0.9           (Sec is rounded up and Usec < 0)
 
       --    Sec := time_t (D - 0.5);
-      --    Usec := suseconds_t (1_000_000 * (D - Duration (Sec)));
+      --    Usec := usec_t (1_000_000 * (D - Duration (Sec)));
       --  fails when D is
       --    0.0           (Sec is rounded down and Usec = 1_000_000)
       --    0.999_999_999 (Usec is rounded up to 1_000_000)
@@ -175,8 +175,8 @@ package body System.C_Time is
       Dm1  : constant Duration range -1.0 .. Duration'Last - 1.0 := D - 1.0;
       Sec  : constant time_t range -1 .. time_t'Last := time_t (Dm1);
       Frac : constant Duration range -0.5 .. 0.5 := Dm1 - Duration (Sec);
-      Usec : constant suseconds_t range -500_000 .. 500_000
-        := suseconds_t (1_000_000 * Frac);
+      Usec : constant usec_t range -500_000 .. 500_000
+        := usec_t (1_000_000 * Frac);
    begin
       if Usec < 0 then
          return (tv_sec => Sec,     tv_usec => Usec + 1_000_000);
diff --git a/gcc/ada/libgnat/s-c_time.ads b/gcc/ada/libgnat/s-c_time.ads
index 0feabb3..e943dd0 100644
--- a/gcc/ada/libgnat/s-c_time.ads
+++ b/gcc/ada/libgnat/s-c_time.ads
@@ -87,23 +87,26 @@ private
                          2 ** (OS_Constants.SIZEOF_tv_sec * 8 - 1) - 1
      with Convention => C, Size => OS_Constants.SIZEOF_tv_sec * 8;
 
-   type suseconds_t is range -2 ** (OS_Constants.SIZEOF_tv_usec * 8 - 1) ..
-                              2 ** (OS_Constants.SIZEOF_tv_usec * 8 - 1) - 1
+   type usec_t is range -2 ** (OS_Constants.SIZEOF_tv_usec * 8 - 1) ..
+                         2 ** (OS_Constants.SIZEOF_tv_usec * 8 - 1) - 1
      with Convention => C, Size => OS_Constants.SIZEOF_tv_usec * 8;
+   --  Larger than the suseconds_t C type on ARM 32 bits with GNU libc
+   --  when __TIME_BITS=64.
 
-   type snseconds_t is range -2 ** (OS_Constants.SIZEOF_tv_nsec * 8 - 1) ..
-                              2 ** (OS_Constants.SIZEOF_tv_nsec * 8 - 1) - 1
+   type nsec_t is range -2 ** (OS_Constants.SIZEOF_tv_nsec * 8 - 1) ..
+                         2 ** (OS_Constants.SIZEOF_tv_nsec * 8 - 1) - 1
      with Convention => C, Size => OS_Constants.SIZEOF_tv_nsec * 8;
+   --  Larger than the signed long int C type on x32.
 
    type timeval is record
-      tv_sec  : time_t range 0 .. OS_Constants.MAX_tv_sec;  -- seconds
-      tv_usec : suseconds_t range 0 .. 999_999;             -- microseconds
+      tv_sec  : time_t range 0 .. OS_Constants.MAX_tv_sec;  --  seconds
+      tv_usec : usec_t range 0 .. 999_999;                  --  microseconds
    end record
      with Convention => C;
 
    type timespec is record
-      tv_sec  : time_t range 0 .. OS_Constants.MAX_tv_sec;  -- seconds
-      tv_nsec : snseconds_t range 0 .. 999_999_999;         -- nanoseconds
+      tv_sec  : time_t range 0 .. OS_Constants.MAX_tv_sec;  --  seconds
+      tv_nsec : nsec_t range 0 .. 999_999_999;              --  nanoseconds
    end record
      with Convention => C;
 
diff --git a/gcc/ada/libgnarl/s-osinte__gnu.ads b/gcc/ada/libgnarl/s-osinte__gnu.ads
index 90ef2d5..08884ec 100644
--- a/gcc/ada/libgnarl/s-osinte__gnu.ads
+++ b/gcc/ada/libgnarl/s-osinte__gnu.ads
@@ -39,7 +39,7 @@
 --  Preelaborate. This package is designed to be a bottom-level (leaf) package
 
 with Interfaces.C;
-with System.Os_Constants;
+with System.OS_Constants;
 with System.C_Time;
 with Ada.Unchecked_Conversion;
 

Reply via email to