This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 11/12] Linux/Alpha: don’t use timeval32 system calls.


Linux/Alpha has two versions of several system call wrappers that take
or return data of type ‘struct timeval’ (possibly nested inside a
larger structure).  The GLIBC_2.0 version is a compat symbol that
calls __NR_osf_foo or __NR_old_foo and uses a struct timeval with a
32-bit tv_sec field.  The GLIBC_2.1 version is used for current code,
calls __NR_foo, and uses a struct timeval with a 64-bit tv_sec field.

This patch changes all of the remaining compat symbols of this type to
be wrappers around their GLIBC_2.1 counterparts.  (gettimeofday
already received this treatment in an earlier patch in this series.)
The compat symbols that copy out a 32-bit struct timeval all check for
overflow.  After the Y2038 deadline, they will fail with errno set to
EOVERFLOW, but only after copying out as much as they can, and filling
in the overflowed ‘struct timeval’(s) with tv_sec set to INT32_MAX and
tv_nsec set to zero.

The new header file tv32-compat.h is currently Alpha-specific but I
don’t know any reason why it couldn’t be reused to aid in writing
wrappers for all affected architectures.

	* sysdeps/unix/sysv/linux/alpha/tv32-compat.h: New file declaring
	types and helper functions for 32/64-bit time_t conversion.

	* sysdeps/unix/sysv/linux/alpha/syscalls.list: Remove entries for
	osf_getitimer, osf_setitimer, osf_utimes, osf_getrusage, and osf_wait4.

	* sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
	* sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
	* sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
	* sysdeps/unix/sysv/linux/alpha/osf_utimes.c
	* sysdeps/unix/sysv/linux/alpha/osf_wait4.c:
	New files defining compatibility symbols formerly defined by
	alpha/syscalls.list.

	* sysdeps/unix/sysv/linux/alpha/adjtime.c: Split the compat code to...
	* sysdeps/unix/sysv/linux/alpha/osf_adjtime.c: ...this new file.

	* sysdeps/unix/sysv/linux/alpha/Makefile (sysdep_routines):
        Add osf_adjtime.

	* sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
	* sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c:
	Use tv32-compat.h helpers.
---
 sysdeps/unix/sysv/linux/alpha/Makefile        |   2 +-
 sysdeps/unix/sysv/linux/alpha/adjtime.c       |  70 +-------
 sysdeps/unix/sysv/linux/alpha/osf_adjtime.c   | 135 ++++++++++++++++
 sysdeps/unix/sysv/linux/alpha/osf_getitimer.c |  48 ++++++
 sysdeps/unix/sysv/linux/alpha/osf_getrusage.c |  44 +++++
 .../unix/sysv/linux/alpha/osf_gettimeofday.c  |  27 +---
 sysdeps/unix/sysv/linux/alpha/osf_setitimer.c |  55 +++++++
 .../unix/sysv/linux/alpha/osf_settimeofday.c  |  12 +-
 sysdeps/unix/sysv/linux/alpha/osf_utimes.c    |  36 +++++
 sysdeps/unix/sysv/linux/alpha/osf_wait4.c     |  47 ++++++
 sysdeps/unix/sysv/linux/alpha/syscalls.list   |   9 +-
 sysdeps/unix/sysv/linux/alpha/tv32-compat.h   | 151 ++++++++++++++++++
 12 files changed, 536 insertions(+), 100 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/alpha/osf_adjtime.c
 create mode 100644 sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
 create mode 100644 sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
 create mode 100644 sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
 create mode 100644 sysdeps/unix/sysv/linux/alpha/osf_utimes.c
 create mode 100644 sysdeps/unix/sysv/linux/alpha/osf_wait4.c
 create mode 100644 sysdeps/unix/sysv/linux/alpha/tv32-compat.h

diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile
index fdd089af71..2e132e474b 100644
--- a/sysdeps/unix/sysv/linux/alpha/Makefile
+++ b/sysdeps/unix/sysv/linux/alpha/Makefile
@@ -9,7 +9,7 @@ sysdep_routines += ieee_get_fp_control ieee_set_fp_control \
 		   ioperm
 
 # Support old timeval32 entry points
-sysdep_routines += osf_gettimeofday osf_settimeofday \
+sysdep_routines += osf_adjtime osf_gettimeofday osf_settimeofday \
 		   osf_getitimer osf_setitimer osf_utimes \
 		   osf_getrusage osf_wait4
 
diff --git a/sysdeps/unix/sysv/linux/alpha/adjtime.c b/sysdeps/unix/sysv/linux/alpha/adjtime.c
index 65641e9c4d..f67f522300 100644
--- a/sysdeps/unix/sysv/linux/alpha/adjtime.c
+++ b/sysdeps/unix/sysv/linux/alpha/adjtime.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998-2019 Free Software Foundation, Inc.
+/* adjtime -- adjust the system clock.  Linux/Alpha/tv64 version.
+   Copyright (C) 1998-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,76 +16,19 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <shlib-compat.h>
 #include <sysdep.h>
 #include <sys/time.h>
+#include <shlib-compat.h>
 
-
-#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
-struct timeval32
-{
-    int tv_sec, tv_usec;
-};
-
-struct timex32 {
-	unsigned int modes;	/* mode selector */
-	long offset;		/* time offset (usec) */
-	long freq;		/* frequency offset (scaled ppm) */
-	long maxerror;		/* maximum error (usec) */
-	long esterror;		/* estimated error (usec) */
-	int status;		/* clock command/status */
-	long constant;		/* pll time constant */
-	long precision;		/* clock precision (usec) (read only) */
-	long tolerance;		/* clock frequency tolerance (ppm)
-				 * (read only)
-				 */
-	struct timeval32 time;	/* (read only) */
-	long tick;		/* (modified) usecs between clock ticks */
-
-	long ppsfreq;           /* pps frequency (scaled ppm) (ro) */
-	long jitter;            /* pps jitter (us) (ro) */
-	int shift;              /* interval duration (s) (shift) (ro) */
-	long stabil;            /* pps stability (scaled ppm) (ro) */
-	long jitcnt;            /* jitter limit exceeded (ro) */
-	long calcnt;            /* calibration intervals (ro) */
-	long errcnt;            /* calibration errors (ro) */
-	long stbcnt;            /* stability limit exceeded (ro) */
-
-	int  :32; int  :32; int  :32; int  :32;
-	int  :32; int  :32; int  :32; int  :32;
-	int  :32; int  :32; int  :32; int  :32;
-};
-
-#define TIMEVAL		timeval32
-#define TIMEX		timex32
-#define ADJTIME		attribute_compat_text_section __adjtime_tv32
-#define ADJTIMEX(x)	INLINE_SYSCALL (old_adjtimex, 1, x)
-#define ADJTIMEX32(x)	INLINE_SYSCALL (old_adjtimex, 1, x)
-
-#include <sysdeps/unix/sysv/linux/adjtime.c>
-
-int attribute_compat_text_section
-__adjtimex_tv32 (struct timex32 *tx) { return ADJTIMEX (tx); }
-
-strong_alias (__adjtimex_tv32, __adjtimex_tv32_1);
-strong_alias (__adjtimex_tv32, __adjtimex_tv32_2);
-compat_symbol (libc, __adjtimex_tv32_1, __adjtimex, GLIBC_2_0);
-compat_symbol (libc, __adjtimex_tv32_2, adjtimex, GLIBC_2_0);
-compat_symbol (libc, __adjtime_tv32, adjtime, GLIBC_2_0);
-#endif /* SHLIB_COMPAT */
-
-#undef TIMEVAL
-#undef TIMEX
-#undef ADJTIME
-#undef ADJTIMEX
-#define TIMEVAL		timeval
-#define TIMEX		timex
 #define ADJTIMEX(x)	INLINE_SYSCALL (adjtimex, 1, x)
 
 #include <sysdeps/unix/sysv/linux/adjtime.c>
 
 int
-__adjtimex_tv64 (struct timex *tx) { return ADJTIMEX (tx); }
+__adjtimex_tv64 (struct timex *tx)
+{
+  return ADJTIMEX (tx);
+}
 
 libc_hidden_ver (__adjtimex_tv64, __adjtimex)
 strong_alias (__adjtimex_tv64, __adjtimex_tv64p);
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c b/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c
new file mode 100644
index 0000000000..57c77c3072
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c
@@ -0,0 +1,135 @@
+/* adjtime -- adjust the system clock.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <tv32-compat.h>
+
+struct timex32 {
+	unsigned int modes;	/* mode selector */
+	long offset;		/* time offset (usec) */
+	long freq;		/* frequency offset (scaled ppm) */
+	long maxerror;		/* maximum error (usec) */
+	long esterror;		/* estimated error (usec) */
+	int status;		/* clock command/status */
+	long constant;		/* pll time constant */
+	long precision;		/* clock precision (usec) (read only) */
+	long tolerance;		/* clock frequency tolerance (ppm)
+				 * (read only)
+				 */
+	struct timeval32 time;	/* (read only) */
+	long tick;		/* (modified) usecs between clock ticks */
+
+	long ppsfreq;           /* pps frequency (scaled ppm) (ro) */
+	long jitter;            /* pps jitter (us) (ro) */
+	int shift;              /* interval duration (s) (shift) (ro) */
+	long stabil;            /* pps stability (scaled ppm) (ro) */
+	long jitcnt;            /* jitter limit exceeded (ro) */
+	long calcnt;            /* calibration intervals (ro) */
+	long errcnt;            /* calibration errors (ro) */
+	long stbcnt;            /* stability limit exceeded (ro) */
+
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+};
+
+int attribute_compat_text_section
+__adjtime_tv32 (const struct timeval32 *itv, struct timeval32 *otv)
+{
+  struct timeval itv64, otv64;
+  TV32_TO_TV64 (&itv64, itv);
+  if (__adjtime (&itv64, &otv64))
+    return -1;
+  if (TV64_TO_TV32 (otv, &itv64))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return 0;
+}
+
+int attribute_compat_text_section
+__adjtimex_tv32 (struct timex32 *tx)
+{
+  struct timex tx64;
+  memset (&tx64, 0, sizeof tx64);
+  tx64.modes     = tx->modes;
+  tx64.offset    = tx->offset;
+  tx64.freq      = tx->freq;
+  tx64.maxerror  = tx->maxerror;
+  tx64.esterror  = tx->esterror;
+  tx64.status    = tx->status;
+  tx64.constant  = tx->constant;
+  tx64.precision = tx->precision;
+  tx64.tolerance = tx->tolerance;
+  tx64.tick      = tx->tick;
+  tx64.ppsfreq   = tx->ppsfreq;
+  tx64.jitter    = tx->jitter;
+  tx64.shift     = tx->shift;
+  tx64.stabil    = tx->stabil;
+  tx64.jitcnt    = tx->jitcnt;
+  tx64.calcnt    = tx->calcnt;
+  tx64.errcnt    = tx->errcnt;
+  tx64.stbcnt    = tx->stbcnt;
+  TV32_TO_TV64 (&tx64.time, &tx->time);
+
+  int status = __adjtimex (&tx64);
+  if (status < 0)
+    return status;
+
+  memset (tx, 0, sizeof *tx);
+  tx->modes     = tx64.modes;
+  tx->offset    = tx64.offset;
+  tx->freq      = tx64.freq;
+  tx->maxerror  = tx64.maxerror;
+  tx->esterror  = tx64.esterror;
+  tx->status    = tx64.status;
+  tx->constant  = tx64.constant;
+  tx->precision = tx64.precision;
+  tx->tolerance = tx64.tolerance;
+  tx->tick      = tx64.tick;
+  tx->ppsfreq   = tx64.ppsfreq;
+  tx->jitter    = tx64.jitter;
+  tx->shift     = tx64.shift;
+  tx->stabil    = tx64.stabil;
+  tx->jitcnt    = tx64.jitcnt;
+  tx->calcnt    = tx64.calcnt;
+  tx->errcnt    = tx64.errcnt;
+  tx->stbcnt    = tx64.stbcnt;
+  if (TV64_TO_TV32 (&tx->time, &tx64.time))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  return status;
+}
+
+strong_alias (__adjtimex_tv32, __adjtimex_tv32_1);
+strong_alias (__adjtimex_tv32, __adjtimex_tv32_2);
+compat_symbol (libc, __adjtimex_tv32_1, __adjtimex, GLIBC_2_0);
+compat_symbol (libc, __adjtimex_tv32_2, adjtimex, GLIBC_2_0);
+compat_symbol (libc, __adjtime_tv32, adjtime, GLIBC_2_0);
+
+#endif /* SHLIB_COMPAT */
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c b/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
new file mode 100644
index 0000000000..d15d8f5be4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
@@ -0,0 +1,48 @@
+/* getitimer -- Get the state of an interval timer.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <tv32-compat.h>
+
+int
+__getitimer_tv32 (int which, struct itimerval32 *curr_value)
+{
+  struct itimerval curr_value_64;
+  if (__getitimer (which, &curr_value_64))
+    return -1;
+
+  /* Make sure both fields of the output are filled in, even if one of them
+     overflows.  */
+  int e;
+  e  = TV64_TO_TV32 (&curr_value->it_interval, &curr_value_64.it_interval);
+  e |= TV64_TO_TV32 (&curr_value->it_value, &curr_value_64.it_value);
+  if (e)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return 0;
+}
+
+compat_symbol (libc, __getitimer_tv32, getitimer, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c b/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
new file mode 100644
index 0000000000..ac094dddbf
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
@@ -0,0 +1,44 @@
+/* utimes -- change file timestamps.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <tv32-compat.h>
+
+int
+__getrusage_tv32 (int who, struct rusage32 *usage32)
+{
+  struct rusage usage64;
+  if (__getrusage (who, &usage64))
+    return -1;
+
+  if (RUSAGE64_TO_RUSAGE32 (usage32, &usage64))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return 0;
+}
+
+compat_symbol (libc, __getrusage_tv32, getrusage, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c b/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
index 9868dfd9c9..cc4c4eebdf 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
@@ -16,19 +16,15 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <limits.h>
-#include <string.h>
-#include <time.h>
 #include <sys/time.h>
 #include <shlib-compat.h>
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
-struct timeval32
-{
-    int tv_sec, tv_usec;
-};
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <tv32-compat.h>
 
 /* Get the current time of day, putting it into *TV.
    If *TZ is not NULL, clear it.
@@ -36,29 +32,20 @@ struct timeval32
 
 int
 attribute_compat_text_section
-__gettimeofday_tv32 (struct timeval32 *tv32,
-                     struct timezone *tz)
+__gettimeofday_tv32 (struct timeval32 *restrict tv32, void *restrict tz)
 {
   if (__glibc_unlikely (tz != 0))
-    memset (tz, 0, sizeof *tz);
+    memset (tz, 0, sizeof (struct timezone));
 
   struct timespec ts;
   if (__clock_gettime (CLOCK_REALTIME, &ts))
     return -1;
 
-  if (__glibc_unlikely (ts.tv_sec > (time_t)INT_MAX))
+  if (TS64_TO_TV32 (tv32, &ts))
     {
-      /* The clock has advanced past the time representable in a 32-bit
-         time_t.  Fail, but write a saturated value to the output first,
-         because callers don't typically expect gettimeofday to fail.  */
       __set_errno (EOVERFLOW);
-      tv32->tv_sec  = INT_MAX;
-      tv32->tv_usec = 0;
       return -1;
     }
-
-  tv32->tv_sec = ts.tv_sec;
-  tv32->tv_usec = ts.tv_nsec / 1000;
   return 0;
 }
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c b/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
new file mode 100644
index 0000000000..48d5bbcd75
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
@@ -0,0 +1,55 @@
+/* getitimer -- Get the state of an interval timer.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <tv32-compat.h>
+
+int
+__setitimer_tv32 (int which, const struct itimerval32 *restrict new_value,
+		  struct itimerval32 *restrict old_value)
+{
+  struct itimerval new_value_64;
+  TV32_TO_TV64 (&new_value_64.it_interval, &new_value->it_interval);
+  TV32_TO_TV64 (&new_value_64.it_value, &new_value->it_value);
+
+  if (!old_value)
+    return __setitimer (which, &new_value_64, 0);
+
+  struct itimerval old_value_64;
+  if (__setitimer (which, &new_value_64, &old_value_64))
+    return -1;
+
+  /* Write all fields of 'old_value' even on error.  */
+  int e = 0;
+  e |= TV64_TO_TV32 (&old_value->it_interval, &old_value_64.it_interval);
+  e |= TV64_TO_TV32 (&old_value->it_value, &old_value_64.it_value);
+  if (e)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return 0;
+}
+
+compat_symbol (libc, __setitimer_tv32, setitimer, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
index a61fcab482..d793b24dbf 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
@@ -16,17 +16,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <time.h>
 #include <sys/time.h>
 #include <shlib-compat.h>
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
-struct timeval32
-{
-    int tv_sec, tv_usec;
-};
+#include <errno.h>
+#include <time.h>
+#include <tv32-compat.h>
 
 /* Set the current time of day and timezone information.
    This call is restricted to the super-user.  */
@@ -46,8 +43,7 @@ __settimeofday_tv32 (const struct timeval32 *tv32,
     }
 
   struct timespec ts;
-  ts.tv_sec = tv32->tv_sec;
-  ts.tv_nsec = tv32->tv_usec * 1000;
+  TV32_TO_TS64 (&ts, tv32);
   return __clock_settime (CLOCK_REALTIME, &ts);
 }
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_utimes.c b/sysdeps/unix/sysv/linux/alpha/osf_utimes.c
new file mode 100644
index 0000000000..7ed483ffb8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_utimes.c
@@ -0,0 +1,36 @@
+/* utimes -- change file timestamps.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <tv32-compat.h>
+
+int
+__utimes_tv32 (const char *filename, const struct timeval32 times32[2])
+{
+  struct timeval times[2];
+  TV32_TO_TV64 (&times[0], &times32[0]);
+  TV32_TO_TV64 (&times[1], &times32[1]);
+  return __utimes (filename, times);
+}
+
+compat_symbol (libc, __utimes_tv32, utimes, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_wait4.c b/sysdeps/unix/sysv/linux/alpha/osf_wait4.c
new file mode 100644
index 0000000000..6ad3f1d510
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_wait4.c
@@ -0,0 +1,47 @@
+/* wait4 -- wait for process to change state.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <string.h>
+#include <tv32-compat.h>
+
+pid_t
+__wait4_tv32 (pid_t pid, int *status, int options, struct rusage32 *usage32)
+{
+  struct rusage usage64;
+  pid_t child = __wait4 (pid, status, options, &usage64);
+  if (child < 0)
+    return child;
+
+  if (RUSAGE64_TO_RUSAGE32 (usage32, &usage64))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return child;
+}
+
+compat_symbol (libc, __wait4_tv32, wait4, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/syscalls.list b/sysdeps/unix/sysv/linux/alpha/syscalls.list
index 9ceed78c8d..0e472b4542 100644
--- a/sysdeps/unix/sysv/linux/alpha/syscalls.list
+++ b/sysdeps/unix/sysv/linux/alpha/syscalls.list
@@ -22,14 +22,7 @@ pciconfig_read	EXTRA	pciconfig_read	5	pciconfig_read
 pciconfig_write	EXTRA	pciconfig_write	5	pciconfig_write
 pciconfig_iobase EXTRA	pciconfig_iobase 3	__pciconfig_iobase pciconfig_iobase
 
-# support old timeval32 entry points
-osf_getitimer	-	osf_getitimer	2	__getitimer_tv32  getitimer@GLIBC_2.0
-osf_setitimer	-	osf_setitimer	3	__setitimer_tv32  setitimer@GLIBC_2.0
-osf_utimes	-	osf_utimes	2	__utimes_tv32  utimes@GLIBC_2.0
-osf_getrusage	-	osf_getrusage	2	__getrusage_tv32  getrusage@GLIBC_2.0
-osf_wait4	-	osf_wait4	4	__wait4_tv32  wait4@GLIBC_2.0
-
-# support new timeval64 entry points
+# new timeval64 entry points (see osf_* for the GLIBC_2.0 versions)
 getitimer	-	getitimer	2	__getitimer getitimer@@GLIBC_2.1
 setitimer	-	setitimer	3	__setitimer setitimer@@GLIBC_2.1
 utimes		-	utimes		2	__utimes utimes@@GLIBC_2.1
diff --git a/sysdeps/unix/sysv/linux/alpha/tv32-compat.h b/sysdeps/unix/sysv/linux/alpha/tv32-compat.h
new file mode 100644
index 0000000000..926e8ce017
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/tv32-compat.h
@@ -0,0 +1,151 @@
+/* Compatibility definitions for `struct timeval' with 32-bit time_t.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _TV32_COMPAT_H
+#define _TV32_COMPAT_H 1
+
+#include <features.h>
+
+#include <bits/types.h>
+#include <bits/types/time_t.h>
+#include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timespec.h>
+#include <bits/types/struct_rusage.h>
+
+#include <stdint.h> // for INT32_MAX
+#include <string.h> // for memset
+
+/* A version of 'struct timeval' with 32-bit time_t.  */
+struct timeval32
+{
+  int32_t tv_sec;
+  int32_t tv_usec;
+};
+
+/* Structures containing 'struct timeval' with 32-bit time_t.  */
+struct itimerval32
+{
+  struct timeval32 it_interval;
+  struct timeval32 it_value;
+};
+
+struct rusage32
+{
+  struct timeval32 ru_utime;	/* user time used */
+  struct timeval32 ru_stime;	/* system time used */
+  long ru_maxrss;		/* maximum resident set size */
+  long ru_ixrss;		/* integral shared memory size */
+  long ru_idrss;		/* integral unshared data size */
+  long ru_isrss;		/* integral unshared stack size */
+  long ru_minflt;		/* page reclaims */
+  long ru_majflt;		/* page faults */
+  long ru_nswap;		/* swaps */
+  long ru_inblock;		/* block input operations */
+  long ru_oublock;		/* block output operations */
+  long ru_msgsnd;		/* messages sent */
+  long ru_msgrcv;		/* messages received */
+  long ru_nsignals;		/* signals received */
+  long ru_nvcsw;		/* voluntary context switches */
+  long ru_nivcsw;		/* involuntary " */
+};
+
+/* Conversion functions.  If the seconds field of a timeval32 would
+   overflow, they write { INT32_MAX, 0 } to the output and return -1;
+   otherwise they return 0.  */
+
+__extern_always_inline void
+TV32_TO_TV64 (struct timeval *restrict tv64,
+              const struct timeval32 *restrict tv32)
+{
+  tv64->tv_sec = tv32->tv_sec;
+  tv64->tv_usec = tv32->tv_usec;
+}
+
+__extern_always_inline void
+TV32_TO_TS64 (struct timespec *restrict ts64,
+              const struct timeval32 *restrict tv32)
+{
+  ts64->tv_sec = tv32->tv_sec;
+  ts64->tv_nsec = tv32->tv_usec * 1000;
+}
+
+__extern_always_inline int
+TV64_TO_TV32 (struct timeval32 *restrict tv32,
+              const struct timeval *restrict tv64)
+{
+  if (__glibc_unlikely (tv64->tv_sec > (time_t) INT32_MAX))
+    {
+      tv32->tv_sec = INT32_MAX;
+      tv32->tv_usec = 0;
+      return -1;
+    }
+  else
+    {
+      tv32->tv_sec = tv64->tv_sec;
+      tv32->tv_usec = tv64->tv_usec;
+      return 0;
+    }
+}
+
+__extern_always_inline int
+TS64_TO_TV32 (struct timeval32 *restrict tv32,
+              const struct timespec *restrict ts64)
+{
+  if (__glibc_unlikely (ts64->tv_sec > (time_t) INT32_MAX))
+    {
+      tv32->tv_sec = INT32_MAX;
+      tv32->tv_usec = 0;
+      return -1;
+    }
+  else
+    {
+      tv32->tv_sec = ts64->tv_sec;
+      tv32->tv_usec = ts64->tv_nsec / 1000;
+      return 0;
+    }
+}
+
+__extern_always_inline int
+RUSAGE64_TO_RUSAGE32 (struct rusage32 *restrict r32,
+                      const struct rusage *restrict r64)
+{
+  /* Fill out the entire structure even on failure.  */
+  memset (r32, 0, sizeof *r32);
+
+  int e = 0;
+  e |= TV64_TO_TV32 (&r32->ru_utime, &r64->ru_utime);
+  e |= TV64_TO_TV32 (&r32->ru_stime, &r64->ru_stime);
+  r32->ru_maxrss   = r64->ru_maxrss;
+  r32->ru_ixrss    = r64->ru_ixrss;
+  r32->ru_idrss    = r64->ru_idrss;
+  r32->ru_isrss    = r64->ru_isrss;
+  r32->ru_minflt   = r64->ru_minflt;
+  r32->ru_majflt   = r64->ru_majflt;
+  r32->ru_nswap    = r64->ru_nswap;
+  r32->ru_inblock  = r64->ru_inblock;
+  r32->ru_oublock  = r64->ru_oublock;
+  r32->ru_msgsnd   = r64->ru_msgsnd;
+  r32->ru_msgrcv   = r64->ru_msgrcv;
+  r32->ru_nsignals = r64->ru_nsignals;
+  r32->ru_nvcsw    = r64->ru_nvcsw;
+  r32->ru_nivcsw   = r64->ru_nivcsw;
+
+  return e;
+}
+
+#endif /* tv32-compat.h */
-- 
2.23.0.rc1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]