diff mbox series

[v8] ada: fix timeval timespec on 32 bits archs with 64 bits time_t [PR114065]

Message ID ZjZXE9dGSe6TvOt2@pegase
State New
Headers show
Series [v8] ada: fix timeval timespec on 32 bits archs with 64 bits time_t [PR114065] | expand

Commit Message

Nicolas Boulenguez May 4, 2024, 3:41 p.m. UTC
PR ada/114065

Ada.Calendar.Clock returns nonsense on 32 bits architectures with 64
bits time_t, because gettimeofday is then a preprocessor macro for
__gettimeofday64, so linking from Ada with "gettimeofday" gets the
wrong version.

On such architectures and also on x32, some Ada declarations for the
time{val,spec} C structs are wrong (for example timespec.tv_nsec is a
not a long int on x32).  This also results in wrong results for Clock.

The attached commits
 * merge or remove all declarations for timeval and timespec
 * calls the 64 bit functions when __USE_TIME_BITS64
 * fixes various overflows with 32 bits Duration detected during tests
 * removes a lot of duplicated code

The bug attachements (v7) contains a python script testing
s-c_time.adb for each combination of type sizes.

The whole patch queue, applied on gcc-13, builds on all Debian
architectures and fixes the original issue on arm{el,hf}.

Comments

Arnaud Charlet May 15, 2024, 2:29 p.m. UTC | #1
Nicolas,

Thank you for such a large and delicate change!

This looks generally good, except for the first parts: we cannot change documented/user
packages, meaning that GNAT.Calendar, System.OS_Lib (via the documented GNAT.OS_Lib) and
Ada.Calendar.Conversion cannot be changed: we need to keep the current interface or else existing user code will break.

Arno
diff mbox series

Patch

From 0f2eba5fd9b6c5a0cd67f5cf6a13e5650ebe4514 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <nicolas@debian.org>
Date: Fri, 26 Apr 2024 20:08:21 +0200
Subject: [PATCH v8 9/9] Ada: select 64 bits time functions from GNU libc when
 __USE_TIME_BITS64 [PR114065]

else Ada.Calendar returns random dates on system affected by the
Y2038 Glibc transition (pr114065).

PR ada/114065
Signed-off-by: Nicolas Boulenguez <nicolas@debian.org>

---
 gcc/ada/libgnarl/a-exetim__posix.adb        |  5 ++++-
 gcc/ada/libgnarl/s-osinte__gnu.ads          | 14 ++++++++++----
 gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads | 14 ++++++++++----
 gcc/ada/libgnarl/s-osinte__linux.ads        | 10 +++++++---
 gcc/ada/libgnat/g-spogwa.adb                |  4 +++-
 gcc/ada/libgnat/s-optide.adb                |  3 ++-
 gcc/ada/libgnat/s-osprim__posix.adb         |  4 +++-
 gcc/ada/libgnat/s-osprim__posix2008.adb     |  3 ++-
 gcc/ada/s-oscons-tmplt.c                    | 16 ++++++++++++++++
 9 files changed, 57 insertions(+), 16 deletions(-)

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-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-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
-- 
2.39.2