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

Message ID 20190820132152.24100-12-zackw@panix.com
State Superseded
Headers

Commit Message

Zack Weinberg Aug. 20, 2019, 1:21 p.m. UTC
  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
  

Comments

Adhemerval Zanella Aug. 21, 2019, 6:49 p.m. UTC | #1
On 20/08/2019 10:21, Zack Weinberg wrote:
> 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
>  

Ok.

> 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);

I think you can just remove this file by adding

adjtimex       adjtime adjtimex        i:p     __adjtimex      __adjtimex@GLIBC_2.1 adjtimex@GLIBC_2.1

on sysdeps/unix/sysv/linux/alpha/syscalls.list.

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

No implicit checks.

> +  if (TV64_TO_TV32 (otv, &itv64))

Ditto.

> +    {
> +      __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);

Maybe struct timex tx64 = { 0 } ?

> +  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;
> +    }

I am not sure it is correct to return EOVERFLOW for this pattern, because
the side-effects of time adjustment will be visible after the call. The
kernel (arch/alpha/kernel/osf_sys.c:1254) does not handle the overflow,
so I think we just need to mimic the kernel for this (the caller will see
the overflow in the returned value).

> +
> +  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 */

Ok.

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

No implicit checks.

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

Ok.

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

No implicit checks.

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

Ok.

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

Ok.

>  
>  #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;

I think it can be simplified to assume __clock_gettime (CLOCK_REALTIME) can't
fail.

>  
> -  if (__glibc_unlikely (ts.tv_sec > (time_t)INT_MAX))
> +  if (TS64_TO_TV32 (tv32, &ts))


No implicit checks.

>      {
> -      /* 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;
>  }
>  

Ok.

> 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);

I think you code guidelines state we need to check against NULL.

> +
> +  struct itimerval old_value_64;
> +  if (__setitimer (which, &new_value_64, &old_value_64))
> +    return -1;

No implicit checks.

> +
> +  /* 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;
> +}

As for adjtimer, I am not sure it is correct to return EOVERFLOW for this 
pattern due the side-effects of time adjustment being visible after the
call.

> +
> +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);
>  }
>  

Ok.

> 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

Ok.

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

No implicit checks.

> +    {
> +      __set_errno (EOVERFLOW);
> +      return -1;
> +    }

I am not sure it is correct to return EOVERFLOW for this pattern, because
wait return value expects that an -1 error either the input in invalid or
the child was not reaped.  With this pattern, the child will be terminated
correctly, but it won't indicate the correct value.

I think since it is a compat symbol to just convert to rusage32 and return
the value to caller.

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

Ok.

> 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

I personally prefer to prefix arch-specific header with the architectures
initial to allow include-next (although this header specific does not
actually require it).

> +
> +#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 " */
> +};

s/long/long int/

> +
> +/* 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;
> +}

I think since it is an internal header and we explict build glibc with gnu11,
use static inline should be suffice instead of __extern_always_inline.  Also,
although it is not a rule, glibc uses capitalized names for macros definitions
and default names for static inline functions.  The implementation looks ok.

> +
> +__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;
> +    }
> +}

Use bool/_Bool so there is no need to use explicit check for the function
use.  Same for TS64_TO_TV32 and RUSAGE64_TO_RUSAGE32.

> +
> +__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 */
>
  
Zack Weinberg Aug. 22, 2019, 1:36 p.m. UTC | #2
On 8/21/19 2:49 PM, Adhemerval Zanella wrote:

>> +__adjtimex_tv64 (struct timex *tx)
>> +{
>> +  return ADJTIMEX (tx);
>> +}
>>  
>>  libc_hidden_ver (__adjtimex_tv64, __adjtimex)
>>  strong_alias (__adjtimex_tv64, __adjtimex_tv64p);
> 
> I think you can just remove this file by adding
> 
> adjtimex       adjtime adjtimex        i:p     __adjtimex      __adjtimex@GLIBC_2.1 adjtimex@GLIBC_2.1
> 
> on sysdeps/unix/sysv/linux/alpha/syscalls.list.

Thanks for the suggestion.  I'll try it.

>> +  if (__adjtime (&itv64, &otv64))
>> +    return -1;
> 
> No implicit checks.

*sigh* Will change.

>> +int attribute_compat_text_section
>> +__adjtimex_tv32 (struct timex32 *tx)
>> +{
>> +  struct timex tx64;
>> +  memset (&tx64, 0, sizeof tx64);
> 
> Maybe struct timex tx64 = { 0 } ?

I would prefer to keep parallel structure with the treatment of `tx`
below; we cannot use an initializer for that.

>> +  if (TV64_TO_TV32 (&tx->time, &tx64.time))
>> +    {
>> +      __set_errno (EOVERFLOW);
>> +      return -1;
>> +    }
> 
> I am not sure it is correct to return EOVERFLOW for this pattern, because
> the side-effects of time adjustment will be visible after the call. The
> kernel (arch/alpha/kernel/osf_sys.c:1254) does not handle the overflow,
> so I think we just need to mimic the kernel for this (the caller will see
> the overflow in the returned value).

This (and other comments along these lines) make me realize we need to
have a design discussion about this patch's proposed semantics for Y2038
overflow, separate from the line-by-line review.

To facilitate this, I am going to split this patch from the larger
series and resubmit it separately, after making some changes to the
semantics, not necessarily the ones you asked for.

(Unfortunately, because gettimeofday is one of the affected symbols, the
larger patch series depends on this patch.  So we're going to have to
have the discussion now.)

>> +#ifndef _TV32_COMPAT_H
>> +#define _TV32_COMPAT_H 1
> 
> I personally prefer to prefix arch-specific header with the architectures
> initial to allow include-next (although this header specific does not
> actually require it).

I didn't do that in this case because I am expecting that this header
will be moved up to sysdeps/unix/sysv/linux or maybe even all the way to
sysdeps/posix as part of the larger Y2038 project.  We want to have
consistent overflow behavior on all architectures, after all.  The only
reason not to make it arch-generic right now is I haven't checked that
other 32-bit architectures' structure layouts match the ones used for
Linux/Alpha.

>> +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 " */
>> +};
> 
> s/long/long int/

Must we?  That will make it harder for people in the future to check
whether the structure matches the kernel headers' version.

>> +/* 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;
>> +}
> 
> I think since it is an internal header and we explict build glibc with gnu11,
> use static inline should be suffice instead of __extern_always_inline.  Also,
> although it is not a rule, glibc uses capitalized names for macros definitions
> and default names for static inline functions.  The implementation looks ok.

I'm using capitalized names to match the convention established by
<sys/time.h>'s TIMEVAL_TO_TIMESPEC and friends.

I will switch to static inline.

> Use bool/_Bool so there is no need to use explicit check for the function
> use.  Same for TS64_TO_TV32 and RUSAGE64_TO_RUSAGE32.

I will also make this change.

zw
  
Adhemerval Zanella Aug. 23, 2019, 6:48 p.m. UTC | #3
On 22/08/2019 10:36, Zack Weinberg wrote:
> On 8/21/19 2:49 PM, Adhemerval Zanella wrote:
> 
>>> +__adjtimex_tv64 (struct timex *tx)
>>> +{
>>> +  return ADJTIMEX (tx);
>>> +}
>>>  
>>>  libc_hidden_ver (__adjtimex_tv64, __adjtimex)
>>>  strong_alias (__adjtimex_tv64, __adjtimex_tv64p);
>>
>> I think you can just remove this file by adding
>>
>> adjtimex       adjtime adjtimex        i:p     __adjtimex      __adjtimex@GLIBC_2.1 adjtimex@GLIBC_2.1
>>
>> on sysdeps/unix/sysv/linux/alpha/syscalls.list.
> 
> Thanks for the suggestion.  I'll try it.
> 
>>> +  if (__adjtime (&itv64, &otv64))
>>> +    return -1;
>>
>> No implicit checks.
> 
> *sigh* Will change.
> 
>>> +int attribute_compat_text_section
>>> +__adjtimex_tv32 (struct timex32 *tx)
>>> +{
>>> +  struct timex tx64;
>>> +  memset (&tx64, 0, sizeof tx64);
>>
>> Maybe struct timex tx64 = { 0 } ?
> 
> I would prefer to keep parallel structure with the treatment of `tx`
> below; we cannot use an initializer for that.

Fair enough.

> 
>>> +  if (TV64_TO_TV32 (&tx->time, &tx64.time))
>>> +    {
>>> +      __set_errno (EOVERFLOW);
>>> +      return -1;
>>> +    }
>>
>> I am not sure it is correct to return EOVERFLOW for this pattern, because
>> the side-effects of time adjustment will be visible after the call. The
>> kernel (arch/alpha/kernel/osf_sys.c:1254) does not handle the overflow,
>> so I think we just need to mimic the kernel for this (the caller will see
>> the overflow in the returned value).
> 
> This (and other comments along these lines) make me realize we need to
> have a design discussion about this patch's proposed semantics for Y2038
> overflow, separate from the line-by-line review.
> 
> To facilitate this, I am going to split this patch from the larger
> series and resubmit it separately, after making some changes to the
> semantics, not necessarily the ones you asked for.
> 
> (Unfortunately, because gettimeofday is one of the affected symbols, the
> larger patch series depends on this patch.  So we're going to have to
> have the discussion now.)

Alright.

> 
>>> +#ifndef _TV32_COMPAT_H
>>> +#define _TV32_COMPAT_H 1
>>
>> I personally prefer to prefix arch-specific header with the architectures
>> initial to allow include-next (although this header specific does not
>> actually require it).
> 
> I didn't do that in this case because I am expecting that this header
> will be moved up to sysdeps/unix/sysv/linux or maybe even all the way to
> sysdeps/posix as part of the larger Y2038 project.  We want to have
> consistent overflow behavior on all architectures, after all.  The only
> reason not to make it arch-generic right now is I haven't checked that
> other 32-bit architectures' structure layouts match the ones used for
> Linux/Alpha.

Alright.

> 
>>> +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 " */
>>> +};
>>
>> s/long/long int/
> 
> Must we?  That will make it harder for people in the future to check
> whether the structure matches the kernel headers' version.

This is the feedback I got from Florian on my 'Refactor sigcontextinfo.h'
patch where I also copied some struct definition from kernel. I think 
we should follow GNU code convention even for such cases.

> 
>>> +/* 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;
>>> +}
>>
>> I think since it is an internal header and we explict build glibc with gnu11,
>> use static inline should be suffice instead of __extern_always_inline.  Also,
>> although it is not a rule, glibc uses capitalized names for macros definitions
>> and default names for static inline functions.  The implementation looks ok.
> 
> I'm using capitalized names to match the convention established by
> <sys/time.h>'s TIMEVAL_TO_TIMESPEC and friends.
> 
> I will switch to static inline.
> 
>> Use bool/_Bool so there is no need to use explicit check for the function
>> use.  Same for TS64_TO_TV32 and RUSAGE64_TO_RUSAGE32.
> 
> I will also make this change.
> 
> zw
>
  

Patch

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 */