[PATCH v7 0/5] Always use 32-bit time_t for certain syscalls

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH v7 0/5] Always use 32-bit time_t for certain syscalls

Sourceware - libc-alpha mailing list
On y2038 safe 32-bit systems the Linux kernel expects itimerval
and rusage to use a 32-bit time_t, even though the other time_t's
are 64-bit.

This series converts getitimer, setitimer, getrusage and wait4 to be
both y2038 safe and pass a 32-bit time_t based on the
__KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 macro. On 32-bit systems
we will pass a 32-bit time to the kernel (no matter the time_t size). This is
no change for most 64-bit architectures or 32-bit architectures with a 32-bit time_t.

We can also remove the old Alpha functions as this is now handled genericly.

This follows the standard y2038 conversion so that we don't break
backwards compatibility but we expose a 64-bit version for y2038 safe
architectrures (like RV32).

This series was tested by running:
  ./scripts/build-many-glibcs.py ... compilers
  ./scripts/build-many-glibcs.py ... glibcs
on my x86_64 machine.

I also ran make check on RV32 and I only see a total of 10 test failures.

I don't have a way to test this on Alpha, would someone mind testing it for me?

v7:
 - Fix the lack of setting for getitimer
v6:
 - Rebase on master
 - Address v5 review comments
v5:
 - Rebase on master

Alistair Francis (5):
  sysv: Define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
  linux: Use long time_t __getitimer/__setitimer
  resource: Add a __rusage64 struct
  linux: Use long time_t for wait4/getrusage
  sysv/alpha: Use generic __timeval32 and helpers

 bits/typesizes.h                              |   6 +
 include/sys/resource.h                        | 121 ++++++++++++++++++
 include/time.h                                |  15 +++
 sysdeps/unix/syscalls.list                    |   3 -
 .../unix/sysv/linux/alpha/bits/typesizes.h    |   3 +
 sysdeps/unix/sysv/linux/alpha/osf_adjtime.c   |  15 ++-
 sysdeps/unix/sysv/linux/alpha/osf_getitimer.c |   9 +-
 sysdeps/unix/sysv/linux/alpha/osf_getrusage.c |  10 +-
 .../unix/sysv/linux/alpha/osf_gettimeofday.c  |   6 +-
 sysdeps/unix/sysv/linux/alpha/osf_setitimer.c |  15 ++-
 .../unix/sysv/linux/alpha/osf_settimeofday.c  |   6 +-
 sysdeps/unix/sysv/linux/alpha/osf_utimes.c    |   8 +-
 sysdeps/unix/sysv/linux/alpha/osf_wait4.c     |  10 +-
 .../unix/sysv/linux/generic/bits/typesizes.h  |   6 +
 sysdeps/unix/sysv/linux/getitimer.c           |  61 +++++++++
 sysdeps/unix/sysv/linux/getrusage.c           |  58 +++++++++
 sysdeps/unix/sysv/linux/s390/bits/typesizes.h |   6 +
 sysdeps/unix/sysv/linux/setitimer.c           |  94 ++++++++++++++
 .../unix/sysv/linux/sparc/bits/typesizes.h    |   6 +
 .../alpha-tv32-compat.h => tv32-compat.h}     |  94 ++++++--------
 sysdeps/unix/sysv/linux/wait4.c               |  50 +++++++-
 sysdeps/unix/sysv/linux/x86/bits/typesizes.h  |   5 +
 22 files changed, 507 insertions(+), 100 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/getitimer.c
 create mode 100644 sysdeps/unix/sysv/linux/getrusage.c
 create mode 100644 sysdeps/unix/sysv/linux/setitimer.c
 rename sysdeps/unix/sysv/linux/{alpha/alpha-tv32-compat.h => tv32-compat.h} (53%)

--
2.26.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v7 1/5] sysv: Define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64

Sourceware - libc-alpha mailing list
On y2038 safe 32-bit systems the Linux kernel expects itimerval
and rusage to use a 32-bit time_t, even though the other time_t's
are 64-bit. There are currently no plans to make 64-bit time_t versions
of these structs.

There are also other occurrences where the time passed to the kernel via
timeval doesn't match the wordsize.

To handle these cases let's define a new macro
__KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64. This macro specifies if the
kernel's old_timeval matches the new timeval64. This should be true for
64-bit architectures except for Alpha's old osf syscalls and x32.

Reviewed-by: Lukasz Majewski <[hidden email]>
---
 bits/typesizes.h                                 | 6 ++++++
 sysdeps/unix/sysv/linux/alpha/bits/typesizes.h   | 3 +++
 sysdeps/unix/sysv/linux/generic/bits/typesizes.h | 6 ++++++
 sysdeps/unix/sysv/linux/s390/bits/typesizes.h    | 6 ++++++
 sysdeps/unix/sysv/linux/sparc/bits/typesizes.h   | 6 ++++++
 sysdeps/unix/sysv/linux/x86/bits/typesizes.h     | 5 +++++
 6 files changed, 32 insertions(+)

diff --git a/bits/typesizes.h b/bits/typesizes.h
index 599408973e..8f16903a21 100644
--- a/bits/typesizes.h
+++ b/bits/typesizes.h
@@ -76,10 +76,16 @@
 
 /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
 # define __STATFS_MATCHES_STATFS64  1
+
+/* And for getitimer, setitimer and rusage  */
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
 #else
 # define __RLIM_T_MATCHES_RLIM64_T 0
 
 # define __STATFS_MATCHES_STATFS64  0
+
+/* And for getitimer, setitimer and rusage  */
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
 #endif
 
 /* Number of descriptors that can fit in an `fd_set'.  */
diff --git a/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h b/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
index 28ee3e5920..1d1fd242dc 100644
--- a/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
@@ -73,6 +73,9 @@
 /* Not for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
 # define __STATFS_MATCHES_STATFS64  0
 
+/* And for getitimer, setitimer and rusage  */
+#define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
+
 /* Number of descriptors that can fit in an `fd_set'.  */
 #define __FD_SETSIZE 1024
 
diff --git a/sysdeps/unix/sysv/linux/generic/bits/typesizes.h b/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
index 7c963e523e..4fb246ac74 100644
--- a/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
@@ -77,11 +77,17 @@
 
 /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
 # define __STATFS_MATCHES_STATFS64  1
+
+/* And for getitimer, setitimer and rusage  */
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
 #else
 # define __RLIM_T_MATCHES_RLIM64_T 0
 
 # define __STATFS_MATCHES_STATFS64  0
+
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
 #endif
+
 /* Number of descriptors that can fit in an `fd_set'.  */
 #define __FD_SETSIZE 1024
 
diff --git a/sysdeps/unix/sysv/linux/s390/bits/typesizes.h b/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
index e775e460bb..2bc87c1079 100644
--- a/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
@@ -82,10 +82,16 @@
 
 /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
 # define __STATFS_MATCHES_STATFS64  1
+
+/* And for getitimer, setitimer and rusage  */
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
 #else
 # define __RLIM_T_MATCHES_RLIM64_T 0
 
 # define __STATFS_MATCHES_STATFS64  0
+
+/* And for getitimer, setitimer and rusage  */
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
 #endif
 
 /* Number of descriptors that can fit in an `fd_set'.  */
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h b/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
index ac48c23e37..288a902b5f 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
@@ -76,10 +76,16 @@
 
 /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
 # define __STATFS_MATCHES_STATFS64  1
+
+/* And for getitimer, setitimer and rusage  */
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
 #else
 # define __RLIM_T_MATCHES_RLIM64_T 0
 
 # define __STATFS_MATCHES_STATFS64  0
+
+/* And for getitimer, setitimer and rusage  */
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
 #endif
 
 /* Number of descriptors that can fit in an `fd_set'.  */
diff --git a/sysdeps/unix/sysv/linux/x86/bits/typesizes.h b/sysdeps/unix/sysv/linux/x86/bits/typesizes.h
index 87c50a4f32..1bb4a1620c 100644
--- a/sysdeps/unix/sysv/linux/x86/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/x86/bits/typesizes.h
@@ -88,10 +88,15 @@
 
 /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
 # define __STATFS_MATCHES_STATFS64  1
+
+/* And for getitimer, setitimer and rusage  */
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
 #else
 # define __RLIM_T_MATCHES_RLIM64_T 0
 
 # define __STATFS_MATCHES_STATFS64  0
+
+# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
 #endif
 
 /* Number of descriptors that can fit in an `fd_set'.  */
--
2.26.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v7 2/5] linux: Use long time_t __getitimer/__setitimer

Sourceware - libc-alpha mailing list
In reply to this post by Sourceware - libc-alpha mailing list
The Linux kernel expects itimerval to use a 32-bit time_t, even on archs
with a 64-bit time_t (like RV32). To address this let's convert
itimerval to/from 32-bit and 64-bit to ensure the kernel always gets
a 32-bit time_t.

While we are converting these functions let's also convert them to be
the y2038 safe versions. This means there is a *64 function that is
called by a backwards compatible wrapper.

Tested-by: Lukasz Majewski <[hidden email]>
Reviewed-by: Adhemerval Zanella  <[hidden email]>
---
 include/time.h                        | 15 +++++
 sysdeps/unix/syscalls.list            |  2 -
 sysdeps/unix/sysv/linux/getitimer.c   | 61 +++++++++++++++++
 sysdeps/unix/sysv/linux/setitimer.c   | 94 +++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/tv32-compat.h | 31 +++++++++
 5 files changed, 201 insertions(+), 2 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/getitimer.c
 create mode 100644 sysdeps/unix/sysv/linux/setitimer.c
 create mode 100644 sysdeps/unix/sysv/linux/tv32-compat.h

diff --git a/include/time.h b/include/time.h
index 2523e0ff0d..4522fe9c4f 100644
--- a/include/time.h
+++ b/include/time.h
@@ -6,6 +6,7 @@
 # include <bits/types/locale_t.h>
 # include <stdbool.h>
 # include <time/mktime-internal.h>
+# include <sys/time.h>
 # include <endian.h>
 # include <time-clockid.h>
 # include <sys/time.h>
@@ -127,6 +128,20 @@ struct __itimerval64
 };
 #endif
 
+#if __TIMESIZE == 64
+# define __getitimer64 __getitimer
+# define __setitimer64 __setitimer
+#else
+extern int __getitimer64 (enum __itimer_which __which,
+                          struct __itimerval64 *__value);
+
+libc_hidden_proto (__getitimer64)
+extern int __setitimer64 (enum __itimer_which __which,
+                          const struct __itimerval64 *__restrict __new,
+                          struct __itimerval64 *__restrict __old);
+libc_hidden_proto (__setitimer64)
+#endif
+
 #if __TIMESIZE == 64
 # define __ctime64 ctime
 #else
diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
index e28e801c7a..d249049d6e 100644
--- a/sysdeps/unix/syscalls.list
+++ b/sysdeps/unix/syscalls.list
@@ -25,7 +25,6 @@ getgid - getgid Ei: __getgid getgid
 getgroups - getgroups i:ip __getgroups getgroups
 gethostid - gethostid i: gethostid
 gethostname - gethostname i:bn __gethostname gethostname
-getitimer - getitimer i:ip __getitimer getitimer
 getpeername - getpeername i:ibN __getpeername getpeername
 getpid - getpid Ei: __getpid getpid
 getpriority - getpriority i:ii __getpriority getpriority
@@ -67,7 +66,6 @@ setgid - setgid i:i __setgid setgid
 setgroups - setgroups i:ip setgroups
 sethostid - sethostid i:i sethostid
 sethostname - sethostname i:pi sethostname
-setitimer - setitimer i:ipp __setitimer setitimer
 setpgid - setpgrp i:ii __setpgid setpgid
 setpriority - setpriority i:iii __setpriority setpriority
 setregid - setregid i:ii __setregid setregid
diff --git a/sysdeps/unix/sysv/linux/getitimer.c b/sysdeps/unix/sysv/linux/getitimer.c
new file mode 100644
index 0000000000..cb894a5516
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/getitimer.c
@@ -0,0 +1,61 @@
+/* getitimer -- Get the state of an interval timer.  Linux/32 version.
+   Copyright (C) 2020 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 <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sysdep.h>
+#include <tv32-compat.h>
+
+int
+__getitimer64 (__itimer_which_t which, struct __itimerval64 *curr_value)
+{
+#if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
+  return INLINE_SYSCALL_CALL (getitimer, which, curr_value);
+#else
+  struct __itimerval32 curr_value_32;
+
+  if (INLINE_SYSCALL_CALL (getitimer, which, &curr_value_32) == -1)
+    return -1;
+
+  curr_value->it_interval
+    = valid_timeval32_to_timeval64 (curr_value_32.it_interval);
+  curr_value->it_value
+    = valid_timeval32_to_timeval64 (curr_value_32.it_value);
+  return 0;
+#endif
+}
+
+#if __TIMESIZE != 64
+libc_hidden_def (__getitimer64)
+int
+__getitimer (__itimer_which_t which, struct itimerval *curr_value)
+{
+  struct __itimerval64 val64;
+  if (__getitimer64 (which, &val64) != 0)
+    return -1;
+
+  curr_value->it_interval
+    = valid_timeval64_to_timeval (val64.it_interval);
+  curr_value->it_value
+    = valid_timeval64_to_timeval (val64.it_value);
+
+  return 0;
+}
+#endif
+weak_alias (__getitimer, getitimer)
diff --git a/sysdeps/unix/sysv/linux/setitimer.c b/sysdeps/unix/sysv/linux/setitimer.c
new file mode 100644
index 0000000000..c7597dfbd3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/setitimer.c
@@ -0,0 +1,94 @@
+/* setitimer -- Set the state of an interval timer.  Linux/32 version.
+   Copyright (C) 2020 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 <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sysdep.h>
+#include <tv32-compat.h>
+
+int
+__setitimer64 (__itimer_which_t which,
+               const struct __itimerval64 *restrict new_value,
+               struct __itimerval64 *restrict old_value)
+{
+#if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
+  return INLINE_SYSCALL_CALL (setitimer, which, new_value, old_value);
+#else
+  struct __itimerval32 new_value_32;
+
+  if (! in_time_t_range (new_value->it_interval.tv_sec))
+  {
+    __set_errno (EOVERFLOW);
+    return -1;
+  }
+  new_value_32.it_interval
+    = valid_timeval64_to_timeval32 (new_value->it_interval);
+
+  if (! in_time_t_range (new_value->it_value.tv_sec))
+  {
+    __set_errno (EOVERFLOW);
+    return -1;
+  }
+  new_value_32.it_value
+    = valid_timeval64_to_timeval32 (new_value->it_value);
+
+  if (old_value == NULL)
+    return INLINE_SYSCALL_CALL (setitimer, which, &new_value_32, NULL);
+
+  struct __itimerval32 old_value_32;
+  if (INLINE_SYSCALL_CALL (setitimer, which, &new_value_32, &old_value_32) == -1)
+    return -1;
+
+  old_value->it_interval
+     = valid_timeval32_to_timeval64 (old_value_32.it_interval);
+  old_value->it_value
+     = valid_timeval32_to_timeval64 (old_value_32.it_value);
+  return 0;
+#endif
+}
+
+#if __TIMESIZE != 64
+libc_hidden_def (__setitimer64)
+int
+__setitimer (__itimer_which_t which,
+             const struct itimerval *restrict new_value,
+             struct itimerval *restrict old_value)
+{
+  int ret;
+  struct __itimerval64 new64, old64;
+
+  new64.it_interval
+    = valid_timeval_to_timeval64 (new_value->it_interval);
+  new64.it_value
+    = valid_timeval_to_timeval64 (new_value->it_value);
+
+  ret = __setitimer64 (which, &new64, old_value ? &old64 : NULL);
+
+  if (ret == 0 && old_value)
+    {
+      old_value->it_interval
+        = valid_timeval64_to_timeval (old64.it_interval);
+      old_value->it_value
+        = valid_timeval64_to_timeval (old64.it_value);
+    }
+
+  return ret;
+}
+#endif
+weak_alias (__setitimer, setitimer)
diff --git a/sysdeps/unix/sysv/linux/tv32-compat.h b/sysdeps/unix/sysv/linux/tv32-compat.h
new file mode 100644
index 0000000000..061a3539e2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tv32-compat.h
@@ -0,0 +1,31 @@
+/* Compatibility definitions for 'struct timeval' with 32-bit time_t.
+   Copyright (C) 2020 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 <bits/types/time_t.h>
+
+/* Structures containing 'struct timeval' with 32-bit time_t.  */
+struct __itimerval32
+{
+  struct __timeval32 it_interval;
+  struct __timeval32 it_value;
+};
+
+#endif /* tv32-compat.h */
--
2.26.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v7 3/5] resource: Add a __rusage64 struct

Sourceware - libc-alpha mailing list
In reply to this post by Sourceware - libc-alpha mailing list
Add a __rusage64 struct which always uses a 64-bit time_t.

Reviewed-by: Lukasz Majewski <[hidden email]>
Reviewed-by: Adhemerval Zanella  <[hidden email]>
---
 include/sys/resource.h | 110 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 110 insertions(+)

diff --git a/include/sys/resource.h b/include/sys/resource.h
index c55d4e63bd..9d604dfe3e 100644
--- a/include/sys/resource.h
+++ b/include/sys/resource.h
@@ -2,6 +2,116 @@
 #include <resource/sys/resource.h>
 
 #ifndef _ISOMAC
+# include <time.h>
+# include <string.h>
+
+/* Internal version of rusage with a 64-bit time_t. */
+#if __TIMESIZE == 64
+# define __rusage64 rusage
+#else
+struct __rusage64
+  {
+    struct __timeval64 ru_utime;
+    struct __timeval64 ru_stime;
+    __extension__ union
+      {
+ long int ru_maxrss;
+ __syscall_slong_t __ru_maxrss_word;
+      };
+    __extension__ union
+      {
+ long int ru_ixrss;
+ __syscall_slong_t __ru_ixrss_word;
+      };
+    __extension__ union
+      {
+ long int ru_idrss;
+ __syscall_slong_t __ru_idrss_word;
+      };
+    __extension__ union
+      {
+ long int ru_isrss;
+ __syscall_slong_t __ru_isrss_word;
+      };
+    __extension__ union
+      {
+ long int ru_minflt;
+ __syscall_slong_t __ru_minflt_word;
+      };
+    __extension__ union
+      {
+ long int ru_majflt;
+ __syscall_slong_t __ru_majflt_word;
+      };
+    __extension__ union
+      {
+ long int ru_nswap;
+ __syscall_slong_t __ru_nswap_word;
+      };
+    __extension__ union
+      {
+ long int ru_inblock;
+ __syscall_slong_t __ru_inblock_word;
+      };
+    __extension__ union
+      {
+ long int ru_oublock;
+ __syscall_slong_t __ru_oublock_word;
+      };
+    __extension__ union
+      {
+ long int ru_msgsnd;
+ __syscall_slong_t __ru_msgsnd_word;
+      };
+    __extension__ union
+      {
+ long int ru_msgrcv;
+ __syscall_slong_t __ru_msgrcv_word;
+      };
+    __extension__ union
+      {
+ long int ru_nsignals;
+ __syscall_slong_t __ru_nsignals_word;
+      };
+    __extension__ union
+      {
+ long int ru_nvcsw;
+ __syscall_slong_t __ru_nvcsw_word;
+      };
+    __extension__ union
+      {
+ long int ru_nivcsw;
+ __syscall_slong_t __ru_nivcsw_word;
+      };
+  };
+#endif
+
+static inline void
+rusage64_to_rusage (const struct __rusage64 *restrict r64,
+                    struct rusage *restrict r)
+{
+  /* Make sure the entire output structure is cleared, including
+     padding and reserved fields.  */
+  memset (r, 0, sizeof *r);
+
+  r->ru_utime    = valid_timeval64_to_timeval (r64->ru_utime);
+  r->ru_stime    = valid_timeval64_to_timeval (r64->ru_stime);
+  r->ru_maxrss   = r64->ru_maxrss;
+  r->ru_ixrss    = r64->ru_ixrss;
+  r->ru_idrss    = r64->ru_idrss;
+  r->ru_isrss    = r64->ru_isrss;
+  r->ru_minflt   = r64->ru_minflt;
+  r->ru_majflt   = r64->ru_majflt;
+  r->ru_nswap    = r64->ru_nswap;
+  r->ru_inblock  = r64->ru_inblock;
+  r->ru_oublock  = r64->ru_oublock;
+  r->ru_msgsnd   = r64->ru_msgsnd;
+  r->ru_msgrcv   = r64->ru_msgrcv;
+  r->ru_nsignals = r64->ru_nsignals;
+  r->ru_nvcsw    = r64->ru_nvcsw;
+  r->ru_nivcsw   = r64->ru_nivcsw;
+}
+
 /* Prototypes repeated instead of using __typeof because
    sys/resource.h is included in C++ tests, and declaring functions
    with __typeof and __THROW doesn't work for C++.  */
--
2.26.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v7 4/5] linux: Use long time_t for wait4/getrusage

Sourceware - libc-alpha mailing list
In reply to this post by Sourceware - libc-alpha mailing list
The Linux kernel expects rusage to use a 32-bit time_t, even on archs
with a 64-bit time_t (like RV32). To address this let's convert
rusage to/from 32-bit and 64-bit to ensure the kernel always gets
a 32-bit time_t.

While we are converting these functions let's also convert them to be
the y2038 safe versions. This means there is a *64 function that is
called by a backwards compatible wrapper.

Reviewed-by: Lukasz Majewski <[hidden email]>
---
 include/sys/resource.h                | 11 +++++
 sysdeps/unix/syscalls.list            |  1 -
 sysdeps/unix/sysv/linux/getrusage.c   | 58 +++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/tv32-compat.h | 47 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/wait4.c       | 50 ++++++++++++++++++++++-
 5 files changed, 164 insertions(+), 3 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/getrusage.c

diff --git a/include/sys/resource.h b/include/sys/resource.h
index 9d604dfe3e..64925f257c 100644
--- a/include/sys/resource.h
+++ b/include/sys/resource.h
@@ -134,5 +134,16 @@ extern int __getrusage (enum __rusage_who __who, struct rusage *__usage)
 extern int __setrlimit (enum __rlimit_resource __resource,
  const struct rlimit *__rlimits);
 libc_hidden_proto (__setrlimit);
+
+#if __TIMESIZE == 64
+# define __getrusage64 __getrusage
+# define __wait4_time64 __wait4
+#else
+extern int __getrusage64 (enum __rusage_who who, struct __rusage64 *usage);
+libc_hidden_proto (__getrusage64)
+extern pid_t __wait4_time64 (pid_t pid, int *stat_loc, int options,
+                             struct __rusage64 *usage);
+libc_hidden_proto (__wait4_time64)
+#endif
 #endif
 #endif
diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
index d249049d6e..01c4a0e6b1 100644
--- a/sysdeps/unix/syscalls.list
+++ b/sysdeps/unix/syscalls.list
@@ -29,7 +29,6 @@ getpeername - getpeername i:ibN __getpeername getpeername
 getpid - getpid Ei: __getpid getpid
 getpriority - getpriority i:ii __getpriority getpriority
 getrlimit - getrlimit i:ip __getrlimit getrlimit
-getrusage - getrusage i:ip __getrusage getrusage
 getsockname - getsockname i:ibN __getsockname getsockname
 getsockopt - getsockopt i:iiiBN getsockopt
 getuid - getuid Ei: __getuid getuid
diff --git a/sysdeps/unix/sysv/linux/getrusage.c b/sysdeps/unix/sysv/linux/getrusage.c
new file mode 100644
index 0000000000..a4e382ed53
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/getrusage.c
@@ -0,0 +1,58 @@
+/* getrusage -- get the rusage struct.  Linux version.
+   Copyright (C) 2020 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/types.h>
+#include <sysdep.h>
+#include <tv32-compat.h>
+
+int
+__getrusage64 (enum __rusage_who who, struct __rusage64 *usage)
+{
+#if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
+  return INLINE_SYSCALL_CALL (getrusage, who, usage);
+#else
+  struct __rusage32 usage32;
+  if (INLINE_SYSCALL_CALL (getrusage, who, &usage32) == -1)
+    return -1;
+
+  rusage32_to_rusage64 (&usage32, usage);
+  return 0;
+#endif
+}
+
+#if __TIMESIZE != 64
+libc_hidden_def (__getrusage64)
+int
+__getrusage (enum __rusage_who who, struct rusage *usage)
+{
+  int ret ;
+  struct __rusage64 usage64;
+
+  ret = __getrusage64 (who, &usage64);
+
+  if (ret != 0)
+    return ret;
+
+  rusage64_to_rusage (&usage64, usage);
+
+  return ret;
+}
+#endif
+weak_alias (__getrusage, getrusage)
diff --git a/sysdeps/unix/sysv/linux/tv32-compat.h b/sysdeps/unix/sysv/linux/tv32-compat.h
index 061a3539e2..574284fc8e 100644
--- a/sysdeps/unix/sysv/linux/tv32-compat.h
+++ b/sysdeps/unix/sysv/linux/tv32-compat.h
@@ -20,6 +20,7 @@
 #define _TV32_COMPAT_H 1
 
 #include <bits/types/time_t.h>
+#include <sys/resource.h>
 
 /* Structures containing 'struct timeval' with 32-bit time_t.  */
 struct __itimerval32
@@ -28,4 +29,50 @@ struct __itimerval32
   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 " */
+};
+
+static inline void
+rusage32_to_rusage64 (const struct __rusage32 *restrict r32,
+                    struct __rusage64 *restrict r64)
+{
+  /* Make sure the entire output structure is cleared, including
+     padding and reserved fields.  */
+  memset (r64, 0, sizeof *r64);
+
+  r64->ru_utime    = valid_timeval32_to_timeval64 (r32->ru_utime);
+  r64->ru_stime    = valid_timeval32_to_timeval64 (r32->ru_stime);
+  r64->ru_maxrss   = r32->ru_maxrss;
+  r64->ru_ixrss    = r32->ru_ixrss;
+  r64->ru_idrss    = r32->ru_idrss;
+  r64->ru_isrss    = r32->ru_isrss;
+  r64->ru_minflt   = r32->ru_minflt;
+  r64->ru_majflt   = r32->ru_majflt;
+  r64->ru_nswap    = r32->ru_nswap;
+  r64->ru_inblock  = r32->ru_inblock;
+  r64->ru_oublock  = r32->ru_oublock;
+  r64->ru_msgsnd   = r32->ru_msgsnd;
+  r64->ru_msgrcv   = r32->ru_msgrcv;
+  r64->ru_nsignals = r32->ru_nsignals;
+  r64->ru_nvcsw    = r32->ru_nvcsw;
+  r64->ru_nivcsw   = r32->ru_nivcsw;
+}
+
 #endif /* tv32-compat.h */
diff --git a/sysdeps/unix/sysv/linux/wait4.c b/sysdeps/unix/sysv/linux/wait4.c
index 3a8bed1169..d14bd4da27 100644
--- a/sysdeps/unix/sysv/linux/wait4.c
+++ b/sysdeps/unix/sysv/linux/wait4.c
@@ -18,13 +18,28 @@
 
 #include <sys/wait.h>
 #include <sys/resource.h>
+#include <sys/types.h>
 #include <sysdep-cancel.h>
+#include <tv32-compat.h>
 
 pid_t
-__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
+__wait4_time64 (pid_t pid, int *stat_loc, int options, struct __rusage64 *usage)
 {
 #ifdef __NR_wait4
+# if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
   return SYSCALL_CANCEL (wait4, pid, stat_loc, options, usage);
+# else
+  struct __rusage32 usage32;
+  pid_t ret = SYSCALL_CANCEL (wait4, pid, stat_loc, options, &usage32);
+
+  if (ret != 0)
+    return ret;
+
+  if (usage != NULL)
+    rusage32_to_rusage64 (&usage32, usage);
+
+  return ret;
+# endif
 #elif defined (__ASSUME_WAITID_PID0_P_PGID)
   idtype_t idtype = P_PID;
 
@@ -41,8 +56,19 @@ __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
   options |= WEXITED;
 
   siginfo_t infop;
+
+# if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
   if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, usage) < 0)
     return -1;
+# else
+  {
+    struct __rusage32 usage32;
+    if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, &usage32) < 0)
+      return -1;
+    if (usage != NULL)
+      rusage32_to_rusage64 (&usage32, usage);
+  }
+# endif
 
   if (stat_loc)
     {
@@ -71,7 +97,7 @@ __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
     }
 
   return infop.si_pid;
-# else
+#else
 /* Linux waitid prior kernel 5.4 does not support waiting for the current
    process.  It is possible to emulate wait4 it by calling getpgid for
    PID 0, however, it would require an additional syscall and it is inherent
@@ -81,5 +107,25 @@ __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
 # error "The kernel ABI does not provide a way to implement wait4"
 #endif
 }
+
+#if __TIMESIZE != 64
+libc_hidden_def (__wait4_time64)
+
+pid_t
+__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
+{
+  pid_t ret ;
+  struct __rusage64 usage64;
+
+  ret = __wait4_time64 (pid, stat_loc, options, &usage64);
+
+  if (ret != 0)
+    return ret;
+
+  rusage64_to_rusage (&usage64, usage);
+
+  return ret;
+}
+#endif
 libc_hidden_def (__wait4);
 weak_alias (__wait4, wait4)
--
2.26.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v7 5/5] sysv/alpha: Use generic __timeval32 and helpers

Sourceware - libc-alpha mailing list
In reply to this post by Sourceware - libc-alpha mailing list
Now there is a generic __timeval32 and helpers we can use them for Alpha
instead of the Alpha specific ones.

Reviewed-by: Lukasz Majewski <[hidden email]>
---
 .../unix/sysv/linux/alpha/alpha-tv32-compat.h | 124 ------------------
 sysdeps/unix/sysv/linux/alpha/osf_adjtime.c   |  15 ++-
 sysdeps/unix/sysv/linux/alpha/osf_getitimer.c |   9 +-
 sysdeps/unix/sysv/linux/alpha/osf_getrusage.c |  10 +-
 .../unix/sysv/linux/alpha/osf_gettimeofday.c  |   6 +-
 sysdeps/unix/sysv/linux/alpha/osf_setitimer.c |  15 ++-
 .../unix/sysv/linux/alpha/osf_settimeofday.c  |   6 +-
 sysdeps/unix/sysv/linux/alpha/osf_utimes.c    |   8 +-
 sysdeps/unix/sysv/linux/alpha/osf_wait4.c     |  10 +-
 sysdeps/unix/sysv/linux/tv32-compat.h         |  26 ++++
 10 files changed, 67 insertions(+), 162 deletions(-)
 delete mode 100644 sysdeps/unix/sysv/linux/alpha/alpha-tv32-compat.h

diff --git a/sysdeps/unix/sysv/linux/alpha/alpha-tv32-compat.h b/sysdeps/unix/sysv/linux/alpha/alpha-tv32-compat.h
deleted file mode 100644
index 3f80946a02..0000000000
--- a/sysdeps/unix/sysv/linux/alpha/alpha-tv32-compat.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* Compatibility definitions for `struct timeval' with 32-bit time_t.
-   Copyright (C) 2019-2020 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
-
-#define TV_USEC_MAX 999999 // 10**6 - 1
-
-/* 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, TV_USEC_MAX } to the output.  */
-
-static inline struct timeval
-alpha_valid_timeval32_to_timeval (const struct timeval32 tv)
-{
-  return (struct timeval) { tv.tv_sec, tv.tv_usec };
-}
-
-static inline struct timeval32
-alpha_valid_timeval_to_timeval32 (const struct timeval tv64)
-{
-  if (__glibc_unlikely (tv64.tv_sec > (time_t) INT32_MAX))
-    return (struct timeval32) { INT32_MAX, TV_USEC_MAX};
-  return (struct timeval32) { tv64.tv_sec, tv64.tv_usec };
-}
-
-static inline struct timespec
-alpha_valid_timeval32_to_timespec (const struct timeval32 tv)
-{
-  return (struct timespec) { tv.tv_sec, tv.tv_usec * 1000 };
-}
-
-static inline struct timeval32
-alpha_valid_timespec_to_timeval32 (const struct timespec ts)
-{
-  return (struct timeval32) { (time_t) ts.tv_sec, ts.tv_nsec / 1000 };
-}
-
-static inline void
-alpha_rusage64_to_rusage32 (struct rusage32 *restrict r32,
-                      const struct rusage *restrict r64)
-{
-  /* Make sure the entire output structure is cleared, including
-     padding and reserved fields.  */
-  memset (r32, 0, sizeof *r32);
-
-  r32->ru_utime    = alpha_valid_timeval_to_timeval32 (r64->ru_utime);
-  r32->ru_stime    = alpha_valid_timeval_to_timeval32 (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;
-}
-
-#endif /* alpha-tv32-compat.h  */
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c b/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c
index f0a1123639..95d646452e 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c
@@ -20,9 +20,10 @@
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
+#include <time.h>
 #include <sys/time.h>
 #include <sys/timex.h>
-#include <alpha-tv32-compat.h>
+#include <string.h>
 
 struct timex32 {
  unsigned int modes; /* mode selector */
@@ -36,7 +37,7 @@ struct timex32 {
  long tolerance; /* clock frequency tolerance (ppm)
  * (read only)
  */
- struct timeval32 time; /* (read only) */
+ struct __timeval32 time; /* (read only) */
  long tick; /* (modified) usecs between clock ticks */
 
  long ppsfreq;           /* pps frequency (scaled ppm) (ro) */
@@ -55,15 +56,15 @@ struct timex32 {
 
 int
 attribute_compat_text_section
-__adjtime_tv32 (const struct timeval32 *itv, struct timeval32 *otv)
+__adjtime_tv32 (const struct __timeval32 *itv, struct __timeval32 *otv)
 {
-  struct timeval itv64 = alpha_valid_timeval32_to_timeval (*itv);
+  struct timeval itv64 = valid_timeval32_to_timeval (*itv);
   struct timeval otv64;
 
   if (__adjtime (&itv64, &otv64) == -1)
     return -1;
 
-  *otv = alpha_valid_timeval_to_timeval32 (otv64);
+  *otv = valid_timeval_to_timeval32 (otv64);
   return 0;
 }
 
@@ -91,7 +92,7 @@ __adjtimex_tv32 (struct timex32 *tx)
   tx64.calcnt    = tx->calcnt;
   tx64.errcnt    = tx->errcnt;
   tx64.stbcnt    = tx->stbcnt;
-  tx64.time      = alpha_valid_timeval32_to_timeval (tx->time);
+  tx64.time      = valid_timeval32_to_timeval (tx->time);
 
   int status = __adjtimex (&tx64);
   if (status < 0)
@@ -116,7 +117,7 @@ __adjtimex_tv32 (struct timex32 *tx)
   tx->calcnt    = tx64.calcnt;
   tx->errcnt    = tx64.errcnt;
   tx->stbcnt    = tx64.stbcnt;
-  tx->time      = alpha_valid_timeval_to_timeval32 (tx64.time);
+  tx->time      = valid_timeval_to_timeval32 (tx64.time);
 
   return status;
 }
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c b/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
index 204d4ba796..4d25060e96 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
@@ -20,12 +20,13 @@
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
+#include <time.h>
 #include <sys/time.h>
-#include <alpha-tv32-compat.h>
+#include <tv32-compat.h>
 
 int
 attribute_compat_text_section
-__getitimer_tv32 (int which, struct itimerval32 *curr_value)
+__getitimer_tv32 (int which, struct __itimerval32 *curr_value)
 {
   struct itimerval curr_value_64;
   if (__getitimer (which, &curr_value_64) == -1)
@@ -33,9 +34,9 @@ __getitimer_tv32 (int which, struct itimerval32 *curr_value)
 
   /* Write all fields of 'curr_value' regardless of overflow.  */
   curr_value->it_interval
-    = alpha_valid_timeval_to_timeval32 (curr_value_64.it_interval);
+    = valid_timeval_to_timeval32 (curr_value_64.it_interval);
   curr_value->it_value
-    = alpha_valid_timeval_to_timeval32 (curr_value_64.it_value);
+    = valid_timeval_to_timeval32 (curr_value_64.it_value);
   return 0;
 }
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c b/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
index be81994654..95cedb0cf6 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
@@ -22,16 +22,16 @@
 
 #include <sys/time.h>
 #include <sys/resource.h>
-#include <alpha-tv32-compat.h>
+#include <tv32-compat.h>
 
 int
-__getrusage_tv32 (int who, struct rusage32 *usage32)
+__getrusage_tv32 (int who, struct __rusage32 *usage32)
 {
-  struct rusage usage64;
-  if (__getrusage (who, &usage64) == -1)
+  struct rusage usage;
+  if (__getrusage (who, &usage) == -1)
     return -1;
 
-  alpha_rusage64_to_rusage32 (usage32, &usage64);
+  rusage64_to_rusage32 (&usage, usage32);
   return 0;
 }
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c b/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
index 9ffda2fde3..8cf5d303f9 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
@@ -20,17 +20,17 @@
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
+#include <time.h>
 #include <string.h>
 #include <time.h>
 #include <sys/time.h>
-#include <alpha-tv32-compat.h>
 
 /* Get the current time of day and timezone information putting it
    into *TV and *TZ.  */
 
 int
 attribute_compat_text_section
-__gettimeofday_tv32 (struct timeval32 *restrict tv32, void *restrict tz)
+__gettimeofday_tv32 (struct __timeval32 *restrict tv32, void *restrict tz)
 {
   if (__glibc_unlikely (tz != 0))
     memset (tz, 0, sizeof (struct timezone));
@@ -38,7 +38,7 @@ __gettimeofday_tv32 (struct timeval32 *restrict tv32, void *restrict tz)
   struct timespec ts;
   __clock_gettime (CLOCK_REALTIME, &ts);
 
-  *tv32 = alpha_valid_timespec_to_timeval32 (ts);
+  *tv32 = valid_timespec_to_timeval32 (ts);
   return 0;
 }
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c b/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
index 726dfc8b0e..842ab5f64e 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
@@ -20,19 +20,20 @@
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
+#include <time.h>
 #include <sys/time.h>
-#include <alpha-tv32-compat.h>
+#include <tv32-compat.h>
 
 int
 attribute_compat_text_section
-__setitimer_tv32 (int which, const struct itimerval32 *restrict new_value,
-  struct itimerval32 *restrict old_value)
+__setitimer_tv32 (int which, const struct __itimerval32 *restrict new_value,
+  struct __itimerval32 *restrict old_value)
 {
   struct itimerval new_value_64;
   new_value_64.it_interval
-    = alpha_valid_timeval32_to_timeval (new_value->it_interval);
+    = valid_timeval32_to_timeval (new_value->it_interval);
   new_value_64.it_value
-    = alpha_valid_timeval32_to_timeval (new_value->it_value);
+    = valid_timeval32_to_timeval (new_value->it_value);
 
   if (old_value == NULL)
     return __setitimer (which, &new_value_64, NULL);
@@ -43,9 +44,9 @@ __setitimer_tv32 (int which, const struct itimerval32 *restrict new_value,
 
   /* Write all fields of 'old_value' regardless of overflow.  */
   old_value->it_interval
-     = alpha_valid_timeval_to_timeval32 (old_value_64.it_interval);
+     = valid_timeval_to_timeval32 (old_value_64.it_interval);
   old_value->it_value
-     = alpha_valid_timeval_to_timeval32 (old_value_64.it_value);
+     = valid_timeval_to_timeval32 (old_value_64.it_value);
   return 0;
 }
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
index 044363e079..5ea0a5afb7 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
@@ -20,16 +20,16 @@
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
+#include <time.h>
 #include <sys/time.h>
 #include <time.h>
 #include <errno.h>
-#include <alpha-tv32-compat.h>
 
 /* Set the current time of day and timezone information.
    This call is restricted to the super-user.  */
 int
 attribute_compat_text_section
-__settimeofday_tv32 (const struct timeval32 *tv32,
+__settimeofday_tv32 (const struct __timeval32 *tv32,
                      const struct timezone *tz)
 {
   if (__glibc_unlikely (tz != 0))
@@ -42,7 +42,7 @@ __settimeofday_tv32 (const struct timeval32 *tv32,
       return __settimezone (tz);
     }
 
-  struct timespec ts = alpha_valid_timeval32_to_timespec (*tv32);
+  struct timespec ts = valid_timeval32_to_timespec (*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
index 8ad9fb567c..8afbf12185 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_utimes.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_utimes.c
@@ -20,16 +20,16 @@
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
+#include <time.h>
 #include <sys/time.h>
-#include <alpha-tv32-compat.h>
 
 int
 attribute_compat_text_section
-__utimes_tv32 (const char *filename, const struct timeval32 times32[2])
+__utimes_tv32 (const char *filename, const struct __timeval32 times32[2])
 {
   struct timeval times[2];
-  times[0] = alpha_valid_timeval32_to_timeval (times32[0]);
-  times[1] = alpha_valid_timeval32_to_timeval (times32[1]);
+  times[0] = valid_timeval32_to_timeval (times32[0]);
+  times[1] = valid_timeval32_to_timeval (times32[1]);
   return __utimes (filename, times);
 }
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_wait4.c b/sysdeps/unix/sysv/linux/alpha/osf_wait4.c
index c664e8e93f..4242d5227f 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_wait4.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_wait4.c
@@ -23,17 +23,17 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/wait.h>
-#include <alpha-tv32-compat.h>
+#include <tv32-compat.h>
 
 pid_t
 attribute_compat_text_section
-__wait4_tv32 (pid_t pid, int *status, int options, struct rusage32 *usage32)
+__wait4_tv32 (pid_t pid, int *status, int options, struct __rusage32 *usage32)
 {
-  struct rusage usage64;
-  pid_t child = __wait4 (pid, status, options, &usage64);
+  struct rusage usage;
+  pid_t child = __wait4 (pid, status, options, &usage);
 
   if (child >= 0 && usage32 != NULL)
-    alpha_rusage64_to_rusage32 (usage32, &usage64);
+    rusage64_to_rusage32 (&usage, usage32);
   return child;
 }
 
diff --git a/sysdeps/unix/sysv/linux/tv32-compat.h b/sysdeps/unix/sysv/linux/tv32-compat.h
index 574284fc8e..d19b3b378d 100644
--- a/sysdeps/unix/sysv/linux/tv32-compat.h
+++ b/sysdeps/unix/sysv/linux/tv32-compat.h
@@ -75,4 +75,30 @@ rusage32_to_rusage64 (const struct __rusage32 *restrict r32,
   r64->ru_nivcsw   = r32->ru_nivcsw;
 }
 
+static inline void
+rusage64_to_rusage32 (const struct __rusage64 *restrict r64,
+                    struct __rusage32 *restrict r32)
+{
+  /* Make sure the entire output structure is cleared, including
+     padding and reserved fields.  */
+  memset (r32, 0, sizeof *r32);
+
+  r32->ru_utime    = valid_timeval64_to_timeval32 (r64->ru_utime);
+  r32->ru_stime    = valid_timeval64_to_timeval32 (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;
+}
+
 #endif /* tv32-compat.h */
--
2.26.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v7 1/5] sysv: Define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64

Sourceware - libc-alpha mailing list
In reply to this post by Sourceware - libc-alpha mailing list


On 31/03/2020 12:46, Alistair Francis via Libc-alpha wrote:

> On y2038 safe 32-bit systems the Linux kernel expects itimerval
> and rusage to use a 32-bit time_t, even though the other time_t's
> are 64-bit. There are currently no plans to make 64-bit time_t versions
> of these structs.
>
> There are also other occurrences where the time passed to the kernel via
> timeval doesn't match the wordsize.
>
> To handle these cases let's define a new macro
> __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64. This macro specifies if the
> kernel's old_timeval matches the new timeval64. This should be true for
> 64-bit architectures except for Alpha's old osf syscalls and x32.

On x32 time_t is 64-bit, so the define is 0 for 32 bits architectures
and alpha osf syscalls.

>
> Reviewed-by: Lukasz Majewski <[hidden email]>

LGTM, thanks.

Reviewed-by: Adhemerval Zanella  <[hidden email]>

> ---
>  bits/typesizes.h                                 | 6 ++++++
>  sysdeps/unix/sysv/linux/alpha/bits/typesizes.h   | 3 +++
>  sysdeps/unix/sysv/linux/generic/bits/typesizes.h | 6 ++++++
>  sysdeps/unix/sysv/linux/s390/bits/typesizes.h    | 6 ++++++
>  sysdeps/unix/sysv/linux/sparc/bits/typesizes.h   | 6 ++++++
>  sysdeps/unix/sysv/linux/x86/bits/typesizes.h     | 5 +++++
>  6 files changed, 32 insertions(+)
>
> diff --git a/bits/typesizes.h b/bits/typesizes.h
> index 599408973e..8f16903a21 100644
> --- a/bits/typesizes.h
> +++ b/bits/typesizes.h
> @@ -76,10 +76,16 @@
>  
>  /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
>  # define __STATFS_MATCHES_STATFS64  1
> +
> +/* And for getitimer, setitimer and rusage  */
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
>  #else
>  # define __RLIM_T_MATCHES_RLIM64_T 0
>  
>  # define __STATFS_MATCHES_STATFS64  0
> +
> +/* And for getitimer, setitimer and rusage  */
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
>  #endif
>  

Ok.

>  /* Number of descriptors that can fit in an `fd_set'.  */
> diff --git a/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h b/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
> index 28ee3e5920..1d1fd242dc 100644
> --- a/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
> +++ b/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
> @@ -73,6 +73,9 @@
>  /* Not for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
>  # define __STATFS_MATCHES_STATFS64  0
>  
> +/* And for getitimer, setitimer and rusage  */
> +#define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
> +
>  /* Number of descriptors that can fit in an `fd_set'.  */
>  #define __FD_SETSIZE 1024
>  

Ok.

> diff --git a/sysdeps/unix/sysv/linux/generic/bits/typesizes.h b/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
> index 7c963e523e..4fb246ac74 100644
> --- a/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
> +++ b/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
> @@ -77,11 +77,17 @@
>  
>  /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
>  # define __STATFS_MATCHES_STATFS64  1
> +
> +/* And for getitimer, setitimer and rusage  */
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
>  #else
>  # define __RLIM_T_MATCHES_RLIM64_T 0
>  
>  # define __STATFS_MATCHES_STATFS64  0
> +
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
>  #endif
> +
>  /* Number of descriptors that can fit in an `fd_set'.  */
>  #define __FD_SETSIZE 1024
>  

Ok.

> diff --git a/sysdeps/unix/sysv/linux/s390/bits/typesizes.h b/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
> index e775e460bb..2bc87c1079 100644
> --- a/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
> +++ b/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
> @@ -82,10 +82,16 @@
>  
>  /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
>  # define __STATFS_MATCHES_STATFS64  1
> +
> +/* And for getitimer, setitimer and rusage  */
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
>  #else
>  # define __RLIM_T_MATCHES_RLIM64_T 0
>  
>  # define __STATFS_MATCHES_STATFS64  0
> +
> +/* And for getitimer, setitimer and rusage  */
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
>  #endif
>  
>  /* Number of descriptors that can fit in an `fd_set'.  */

Ok.

> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h b/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
> index ac48c23e37..288a902b5f 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
> @@ -76,10 +76,16 @@
>  
>  /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
>  # define __STATFS_MATCHES_STATFS64  1
> +
> +/* And for getitimer, setitimer and rusage  */
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
>  #else
>  # define __RLIM_T_MATCHES_RLIM64_T 0
>  
>  # define __STATFS_MATCHES_STATFS64  0
> +
> +/* And for getitimer, setitimer and rusage  */
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
>  #endif
>  
>  /* Number of descriptors that can fit in an `fd_set'.  */

Ok.

> diff --git a/sysdeps/unix/sysv/linux/x86/bits/typesizes.h b/sysdeps/unix/sysv/linux/x86/bits/typesizes.h
> index 87c50a4f32..1bb4a1620c 100644
> --- a/sysdeps/unix/sysv/linux/x86/bits/typesizes.h
> +++ b/sysdeps/unix/sysv/linux/x86/bits/typesizes.h
> @@ -88,10 +88,15 @@
>  
>  /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t.  */
>  # define __STATFS_MATCHES_STATFS64  1
> +
> +/* And for getitimer, setitimer and rusage  */
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
>  #else
>  # define __RLIM_T_MATCHES_RLIM64_T 0
>  
>  # define __STATFS_MATCHES_STATFS64  0
> +
> +# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
>  #endif
>  
>  /* Number of descriptors that can fit in an `fd_set'.  */
>

Ok.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v7 2/5] linux: Use long time_t __getitimer/__setitimer

Sourceware - libc-alpha mailing list
In reply to this post by Sourceware - libc-alpha mailing list


On 31/03/2020 12:46, Alistair Francis wrote:

> The Linux kernel expects itimerval to use a 32-bit time_t, even on archs
> with a 64-bit time_t (like RV32). To address this let's convert
> itimerval to/from 32-bit and 64-bit to ensure the kernel always gets
> a 32-bit time_t.
>
> While we are converting these functions let's also convert them to be
> the y2038 safe versions. This means there is a *64 function that is
> called by a backwards compatible wrapper.
>
> Tested-by: Lukasz Majewski <[hidden email]>
> Reviewed-by: Adhemerval Zanella  <[hidden email]>

OK with the changes below.

> ---
>  include/time.h                        | 15 +++++
>  sysdeps/unix/syscalls.list            |  2 -
>  sysdeps/unix/sysv/linux/getitimer.c   | 61 +++++++++++++++++
>  sysdeps/unix/sysv/linux/setitimer.c   | 94 +++++++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/tv32-compat.h | 31 +++++++++
>  5 files changed, 201 insertions(+), 2 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/getitimer.c
>  create mode 100644 sysdeps/unix/sysv/linux/setitimer.c
>  create mode 100644 sysdeps/unix/sysv/linux/tv32-compat.h
>
> diff --git a/include/time.h b/include/time.h
> index 2523e0ff0d..4522fe9c4f 100644
> --- a/include/time.h
> +++ b/include/time.h
> @@ -6,6 +6,7 @@
>  # include <bits/types/locale_t.h>
>  # include <stdbool.h>
>  # include <time/mktime-internal.h>
> +# include <sys/time.h>
>  # include <endian.h>
>  # include <time-clockid.h>
>  # include <sys/time.h>
> @@ -127,6 +128,20 @@ struct __itimerval64
>  };
>  #endif
>  
> +#if __TIMESIZE == 64
> +# define __getitimer64 __getitimer
> +# define __setitimer64 __setitimer
> +#else
> +extern int __getitimer64 (enum __itimer_which __which,
> +                          struct __itimerval64 *__value);
> +
> +libc_hidden_proto (__getitimer64)
> +extern int __setitimer64 (enum __itimer_which __which,
> +                          const struct __itimerval64 *__restrict __new,
> +                          struct __itimerval64 *__restrict __old);
> +libc_hidden_proto (__setitimer64)
> +#endif
> +
>  #if __TIMESIZE == 64
>  # define __ctime64 ctime
>  #else
> diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
> index e28e801c7a..d249049d6e 100644
> --- a/sysdeps/unix/syscalls.list
> +++ b/sysdeps/unix/syscalls.list
> @@ -25,7 +25,6 @@ getgid - getgid Ei: __getgid getgid
>  getgroups - getgroups i:ip __getgroups getgroups
>  gethostid - gethostid i: gethostid
>  gethostname - gethostname i:bn __gethostname gethostname
> -getitimer - getitimer i:ip __getitimer getitimer
>  getpeername - getpeername i:ibN __getpeername getpeername
>  getpid - getpid Ei: __getpid getpid
>  getpriority - getpriority i:ii __getpriority getpriority
> @@ -67,7 +66,6 @@ setgid - setgid i:i __setgid setgid
>  setgroups - setgroups i:ip setgroups
>  sethostid - sethostid i:i sethostid
>  sethostname - sethostname i:pi sethostname
> -setitimer - setitimer i:ipp __setitimer setitimer
>  setpgid - setpgrp i:ii __setpgid setpgid
>  setpriority - setpriority i:iii __setpriority setpriority
>  setregid - setregid i:ii __setregid setregid
> diff --git a/sysdeps/unix/sysv/linux/getitimer.c b/sysdeps/unix/sysv/linux/getitimer.c
> new file mode 100644
> index 0000000000..cb894a5516
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/getitimer.c
> @@ -0,0 +1,61 @@
> +/* getitimer -- Get the state of an interval timer.  Linux/32 version.
> +   Copyright (C) 2020 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 <time.h>
> +#include <sys/time.h>
> +#include <sys/types.h>
> +#include <sysdep.h>
> +#include <tv32-compat.h>
> +
> +int
> +__getitimer64 (__itimer_which_t which, struct __itimerval64 *curr_value)
> +{
> +#if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
> +  return INLINE_SYSCALL_CALL (getitimer, which, curr_value);
> +#else
> +  struct __itimerval32 curr_value_32;
> +
> +  if (INLINE_SYSCALL_CALL (getitimer, which, &curr_value_32) == -1)
> +    return -1;
> +
> +  curr_value->it_interval
> +    = valid_timeval32_to_timeval64 (curr_value_32.it_interval);
> +  curr_value->it_value
> +    = valid_timeval32_to_timeval64 (curr_value_32.it_value);
> +  return 0;
> +#endif
> +}
> +
> +#if __TIMESIZE != 64
> +libc_hidden_def (__getitimer64)
> +int
> +__getitimer (__itimer_which_t which, struct itimerval *curr_value)
> +{
> +  struct __itimerval64 val64;
> +  if (__getitimer64 (which, &val64) != 0)
> +    return -1;
> +
> +  curr_value->it_interval
> +    = valid_timeval64_to_timeval (val64.it_interval);
> +  curr_value->it_value
> +    = valid_timeval64_to_timeval (val64.it_value);
> +
> +  return 0;
> +}
> +#endif
> +weak_alias (__getitimer, getitimer)
> diff --git a/sysdeps/unix/sysv/linux/setitimer.c b/sysdeps/unix/sysv/linux/setitimer.c
> new file mode 100644
> index 0000000000..c7597dfbd3
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/setitimer.c
> @@ -0,0 +1,94 @@
> +/* setitimer -- Set the state of an interval timer.  Linux/32 version.
> +   Copyright (C) 2020 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 <time.h>
> +#include <sys/time.h>
> +#include <sys/types.h>
> +#include <sysdep.h>
> +#include <tv32-compat.h>
> +
> +int
> +__setitimer64 (__itimer_which_t which,
> +               const struct __itimerval64 *restrict new_value,
> +               struct __itimerval64 *restrict old_value)
> +{
> +#if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
> +  return INLINE_SYSCALL_CALL (setitimer, which, new_value, old_value);
> +#else
> +  struct __itimerval32 new_value_32;
> +
> +  if (! in_time_t_range (new_value->it_interval.tv_sec))
> +  {
> +    __set_errno (EOVERFLOW);
> +    return -1;
> +  }
> +  new_value_32.it_interval
> +    = valid_timeval64_to_timeval32 (new_value->it_interval);
> +
> +  if (! in_time_t_range (new_value->it_value.tv_sec))
> +  {
> +    __set_errno (EOVERFLOW);
> +    return -1;
> +  }
> +  new_value_32.it_value
> +    = valid_timeval64_to_timeval32 (new_value->it_value);

You could simplify it:

  if (! in_time_t_range (new_value->it_interval.tv_sec)
      || ! in_time_t_range (new_value->it_value.tv_sec))
    {
      __set_errno (EOVERFLOW);
      return -1;
    }
  new_value_32.it_interval
    = valid_timeval64_to_timeval32 (new_value->it_interval);
  new_value_32.it_value
    = valid_timeval64_to_timeval32 (new_value->it_value);

> +
> +  if (old_value == NULL)
> +    return INLINE_SYSCALL_CALL (setitimer, which, &new_value_32, NULL);
> +
> +  struct __itimerval32 old_value_32;
> +  if (INLINE_SYSCALL_CALL (setitimer, which, &new_value_32, &old_value_32) == -1)
> +    return -1;

Line too long, use

  if (INLINE_SYSCALL_CALL (setitimer, which, &new_value_32, &old_value_32)
      == -1)
    return -1;

> +
> +  old_value->it_interval
> +     = valid_timeval32_to_timeval64 (old_value_32.it_interval);
> +  old_value->it_value
> +     = valid_timeval32_to_timeval64 (old_value_32.it_value);
> +  return 0;
> +#endif
> +}
> +
> +#if __TIMESIZE != 64
> +libc_hidden_def (__setitimer64)
> +int
> +__setitimer (__itimer_which_t which,
> +             const struct itimerval *restrict new_value,
> +             struct itimerval *restrict old_value)
> +{
> +  int ret;
> +  struct __itimerval64 new64, old64;
> +
> +  new64.it_interval
> +    = valid_timeval_to_timeval64 (new_value->it_interval);
> +  new64.it_value
> +    = valid_timeval_to_timeval64 (new_value->it_value);
> +
> +  ret = __setitimer64 (which, &new64, old_value ? &old64 : NULL);
> +
> +  if (ret == 0 && old_value)

No implicit check, use old_value != NULL.

> +    {
> +      old_value->it_interval
> +        = valid_timeval64_to_timeval (old64.it_interval);
> +      old_value->it_value
> +        = valid_timeval64_to_timeval (old64.it_value);
> +    }
> +
> +  return ret;
> +}
> +#endif
> +weak_alias (__setitimer, setitimer)
> diff --git a/sysdeps/unix/sysv/linux/tv32-compat.h b/sysdeps/unix/sysv/linux/tv32-compat.h
> new file mode 100644
> index 0000000000..061a3539e2
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tv32-compat.h
> @@ -0,0 +1,31 @@
> +/* Compatibility definitions for 'struct timeval' with 32-bit time_t.
> +   Copyright (C) 2020 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 <bits/types/time_t.h>
> +
> +/* Structures containing 'struct timeval' with 32-bit time_t.  */
> +struct __itimerval32
> +{
> +  struct __timeval32 it_interval;
> +  struct __timeval32 it_value;
> +};
> +
> +#endif /* tv32-compat.h */
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v7 3/5] resource: Add a __rusage64 struct

Sourceware - libc-alpha mailing list
In reply to this post by Sourceware - libc-alpha mailing list


On 31/03/2020 12:46, Alistair Francis wrote:
> Add a __rusage64 struct which always uses a 64-bit time_t.
>
> Reviewed-by: Lukasz Majewski <[hidden email]>
> Reviewed-by: Adhemerval Zanella  <[hidden email]>

Ok.

> ---
>  include/sys/resource.h | 110 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 110 insertions(+)
>
> diff --git a/include/sys/resource.h b/include/sys/resource.h
> index c55d4e63bd..9d604dfe3e 100644
> --- a/include/sys/resource.h
> +++ b/include/sys/resource.h
> @@ -2,6 +2,116 @@
>  #include <resource/sys/resource.h>
>  
>  #ifndef _ISOMAC
> +# include <time.h>
> +# include <string.h>
> +
> +/* Internal version of rusage with a 64-bit time_t. */
> +#if __TIMESIZE == 64
> +# define __rusage64 rusage
> +#else
> +struct __rusage64
> +  {
> +    struct __timeval64 ru_utime;
> +    struct __timeval64 ru_stime;
> +    __extension__ union
> +      {
> + long int ru_maxrss;
> + __syscall_slong_t __ru_maxrss_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_ixrss;
> + __syscall_slong_t __ru_ixrss_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_idrss;
> + __syscall_slong_t __ru_idrss_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_isrss;
> + __syscall_slong_t __ru_isrss_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_minflt;
> + __syscall_slong_t __ru_minflt_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_majflt;
> + __syscall_slong_t __ru_majflt_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_nswap;
> + __syscall_slong_t __ru_nswap_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_inblock;
> + __syscall_slong_t __ru_inblock_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_oublock;
> + __syscall_slong_t __ru_oublock_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_msgsnd;
> + __syscall_slong_t __ru_msgsnd_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_msgrcv;
> + __syscall_slong_t __ru_msgrcv_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_nsignals;
> + __syscall_slong_t __ru_nsignals_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_nvcsw;
> + __syscall_slong_t __ru_nvcsw_word;
> +      };
> +    __extension__ union
> +      {
> + long int ru_nivcsw;
> + __syscall_slong_t __ru_nivcsw_word;
> +      };
> +  };
> +#endif
> +
> +static inline void
> +rusage64_to_rusage (const struct __rusage64 *restrict r64,
> +                    struct rusage *restrict r)
> +{
> +  /* Make sure the entire output structure is cleared, including
> +     padding and reserved fields.  */
> +  memset (r, 0, sizeof *r);
> +
> +  r->ru_utime    = valid_timeval64_to_timeval (r64->ru_utime);
> +  r->ru_stime    = valid_timeval64_to_timeval (r64->ru_stime);
> +  r->ru_maxrss   = r64->ru_maxrss;
> +  r->ru_ixrss    = r64->ru_ixrss;
> +  r->ru_idrss    = r64->ru_idrss;
> +  r->ru_isrss    = r64->ru_isrss;
> +  r->ru_minflt   = r64->ru_minflt;
> +  r->ru_majflt   = r64->ru_majflt;
> +  r->ru_nswap    = r64->ru_nswap;
> +  r->ru_inblock  = r64->ru_inblock;
> +  r->ru_oublock  = r64->ru_oublock;
> +  r->ru_msgsnd   = r64->ru_msgsnd;
> +  r->ru_msgrcv   = r64->ru_msgrcv;
> +  r->ru_nsignals = r64->ru_nsignals;
> +  r->ru_nvcsw    = r64->ru_nvcsw;
> +  r->ru_nivcsw   = r64->ru_nivcsw;
> +}
> +
>  /* Prototypes repeated instead of using __typeof because
>     sys/resource.h is included in C++ tests, and declaring functions
>     with __typeof and __THROW doesn't work for C++.  */
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v7 4/5] linux: Use long time_t for wait4/getrusage

Sourceware - libc-alpha mailing list
In reply to this post by Sourceware - libc-alpha mailing list


On 31/03/2020 12:46, Alistair Francis via Libc-alpha wrote:

> The Linux kernel expects rusage to use a 32-bit time_t, even on archs
> with a 64-bit time_t (like RV32). To address this let's convert
> rusage to/from 32-bit and 64-bit to ensure the kernel always gets
> a 32-bit time_t.
>
> While we are converting these functions let's also convert them to be
> the y2038 safe versions. This means there is a *64 function that is
> called by a backwards compatible wrapper.
>
> Reviewed-by: Lukasz Majewski <[hidden email]>

LGTM, thanks.

Reviewed-by: Adhemerval Zanella  <[hidden email]>

> ---
>  include/sys/resource.h                | 11 +++++
>  sysdeps/unix/syscalls.list            |  1 -
>  sysdeps/unix/sysv/linux/getrusage.c   | 58 +++++++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/tv32-compat.h | 47 ++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/wait4.c       | 50 ++++++++++++++++++++++-
>  5 files changed, 164 insertions(+), 3 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/getrusage.c
>
> diff --git a/include/sys/resource.h b/include/sys/resource.h
> index 9d604dfe3e..64925f257c 100644
> --- a/include/sys/resource.h
> +++ b/include/sys/resource.h
> @@ -134,5 +134,16 @@ extern int __getrusage (enum __rusage_who __who, struct rusage *__usage)
>  extern int __setrlimit (enum __rlimit_resource __resource,
>   const struct rlimit *__rlimits);
>  libc_hidden_proto (__setrlimit);
> +
> +#if __TIMESIZE == 64
> +# define __getrusage64 __getrusage
> +# define __wait4_time64 __wait4
> +#else
> +extern int __getrusage64 (enum __rusage_who who, struct __rusage64 *usage);
> +libc_hidden_proto (__getrusage64)
> +extern pid_t __wait4_time64 (pid_t pid, int *stat_loc, int options,
> +                             struct __rusage64 *usage);
> +libc_hidden_proto (__wait4_time64)
> +#endif
>  #endif
>  #endif

Ok.

> diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
> index d249049d6e..01c4a0e6b1 100644
> --- a/sysdeps/unix/syscalls.list
> +++ b/sysdeps/unix/syscalls.list
> @@ -29,7 +29,6 @@ getpeername - getpeername i:ibN __getpeername getpeername
>  getpid - getpid Ei: __getpid getpid
>  getpriority - getpriority i:ii __getpriority getpriority
>  getrlimit - getrlimit i:ip __getrlimit getrlimit
> -getrusage - getrusage i:ip __getrusage getrusage
>  getsockname - getsockname i:ibN __getsockname getsockname
>  getsockopt - getsockopt i:iiiBN getsockopt
>  getuid - getuid Ei: __getuid getuid

Ok.

> diff --git a/sysdeps/unix/sysv/linux/getrusage.c b/sysdeps/unix/sysv/linux/getrusage.c
> new file mode 100644
> index 0000000000..a4e382ed53
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/getrusage.c
> @@ -0,0 +1,58 @@
> +/* getrusage -- get the rusage struct.  Linux version.
> +   Copyright (C) 2020 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/types.h>
> +#include <sysdep.h>
> +#include <tv32-compat.h>
> +
> +int
> +__getrusage64 (enum __rusage_who who, struct __rusage64 *usage)
> +{
> +#if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
> +  return INLINE_SYSCALL_CALL (getrusage, who, usage);
> +#else
> +  struct __rusage32 usage32;
> +  if (INLINE_SYSCALL_CALL (getrusage, who, &usage32) == -1)
> +    return -1;
> +
> +  rusage32_to_rusage64 (&usage32, usage);
> +  return 0;
> +#endif
> +}

Ok.

> +
> +#if __TIMESIZE != 64
> +libc_hidden_def (__getrusage64)
> +int
> +__getrusage (enum __rusage_who who, struct rusage *usage)
> +{
> +  int ret ;
> +  struct __rusage64 usage64;
> +
> +  ret = __getrusage64 (who, &usage64);
> +
> +  if (ret != 0)
> +    return ret;
> +
> +  rusage64_to_rusage (&usage64, usage);
> +
> +  return ret;
> +}
> +#endif

Ok.

> +weak_alias (__getrusage, getrusage)
> diff --git a/sysdeps/unix/sysv/linux/tv32-compat.h b/sysdeps/unix/sysv/linux/tv32-compat.h
> index 061a3539e2..574284fc8e 100644
> --- a/sysdeps/unix/sysv/linux/tv32-compat.h
> +++ b/sysdeps/unix/sysv/linux/tv32-compat.h
> @@ -20,6 +20,7 @@
>  #define _TV32_COMPAT_H 1
>  
>  #include <bits/types/time_t.h>
> +#include <sys/resource.h>
>  
>  /* Structures containing 'struct timeval' with 32-bit time_t.  */
>  struct __itimerval32
> @@ -28,4 +29,50 @@ struct __itimerval32
>    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 " */
> +};
> +
> +static inline void
> +rusage32_to_rusage64 (const struct __rusage32 *restrict r32,
> +                    struct __rusage64 *restrict r64)
> +{
> +  /* Make sure the entire output structure is cleared, including
> +     padding and reserved fields.  */
> +  memset (r64, 0, sizeof *r64);
> +
> +  r64->ru_utime    = valid_timeval32_to_timeval64 (r32->ru_utime);
> +  r64->ru_stime    = valid_timeval32_to_timeval64 (r32->ru_stime);
> +  r64->ru_maxrss   = r32->ru_maxrss;
> +  r64->ru_ixrss    = r32->ru_ixrss;
> +  r64->ru_idrss    = r32->ru_idrss;
> +  r64->ru_isrss    = r32->ru_isrss;
> +  r64->ru_minflt   = r32->ru_minflt;
> +  r64->ru_majflt   = r32->ru_majflt;
> +  r64->ru_nswap    = r32->ru_nswap;
> +  r64->ru_inblock  = r32->ru_inblock;
> +  r64->ru_oublock  = r32->ru_oublock;
> +  r64->ru_msgsnd   = r32->ru_msgsnd;
> +  r64->ru_msgrcv   = r32->ru_msgrcv;
> +  r64->ru_nsignals = r32->ru_nsignals;
> +  r64->ru_nvcsw    = r32->ru_nvcsw;
> +  r64->ru_nivcsw   = r32->ru_nivcsw;
> +}
> +
>  #endif /* tv32-compat.h */

Ok.

> diff --git a/sysdeps/unix/sysv/linux/wait4.c b/sysdeps/unix/sysv/linux/wait4.c
> index 3a8bed1169..d14bd4da27 100644
> --- a/sysdeps/unix/sysv/linux/wait4.c
> +++ b/sysdeps/unix/sysv/linux/wait4.c
> @@ -18,13 +18,28 @@
>  
>  #include <sys/wait.h>
>  #include <sys/resource.h>
> +#include <sys/types.h>
>  #include <sysdep-cancel.h>
> +#include <tv32-compat.h>
>  
>  pid_t
> -__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
> +__wait4_time64 (pid_t pid, int *stat_loc, int options, struct __rusage64 *usage)
>  {
>  #ifdef __NR_wait4
> +# if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
>    return SYSCALL_CANCEL (wait4, pid, stat_loc, options, usage);
> +# else
> +  struct __rusage32 usage32;
> +  pid_t ret = SYSCALL_CANCEL (wait4, pid, stat_loc, options, &usage32);
> +
> +  if (ret != 0)
> +    return ret;
> +
> +  if (usage != NULL)
> +    rusage32_to_rusage64 (&usage32, usage);
> +
> +  return ret;
> +# endif

Ok.

>  #elif defined (__ASSUME_WAITID_PID0_P_PGID)
>    idtype_t idtype = P_PID;
>  
> @@ -41,8 +56,19 @@ __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
>    options |= WEXITED;
>  
>    siginfo_t infop;
> +
> +# if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
>    if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, usage) < 0)
>      return -1;
> +# else
> +  {
> +    struct __rusage32 usage32;
> +    if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, &usage32) < 0)
> +      return -1;
> +    if (usage != NULL)
> +      rusage32_to_rusage64 (&usage32, usage);
> +  }
> +# endif
>  
>    if (stat_loc)
>      {

Ok.

> @@ -71,7 +97,7 @@ __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
>      }
>  
>    return infop.si_pid;
> -# else
> +#else
>  /* Linux waitid prior kernel 5.4 does not support waiting for the current
>     process.  It is possible to emulate wait4 it by calling getpgid for
>     PID 0, however, it would require an additional syscall and it is inherent
> @@ -81,5 +107,25 @@ __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
>  # error "The kernel ABI does not provide a way to implement wait4"
>  #endif
>  }
> +
> +#if __TIMESIZE != 64
> +libc_hidden_def (__wait4_time64)
> +
> +pid_t
> +__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
> +{
> +  pid_t ret ;
> +  struct __rusage64 usage64;
> +
> +  ret = __wait4_time64 (pid, stat_loc, options, &usage64);
> +
> +  if (ret != 0)
> +    return ret;
> +
> +  rusage64_to_rusage (&usage64, usage);
> +
> +  return ret;
> +}
> +#endif
>  libc_hidden_def (__wait4);
>  weak_alias (__wait4, wait4)
>

Ok.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v7 4/5] linux: Use long time_t for wait4/getrusage

Stepan Golosunov
In reply to this post by Sourceware - libc-alpha mailing list
31.03.2020 в 08:46:55 -0700 Alistair Francis написал:

> The Linux kernel expects rusage to use a 32-bit time_t, even on archs
> with a 64-bit time_t (like RV32). To address this let's convert
> rusage to/from 32-bit and 64-bit to ensure the kernel always gets
> a 32-bit time_t.
>
> While we are converting these functions let's also convert them to be
> the y2038 safe versions. This means there is a *64 function that is
> called by a backwards compatible wrapper.
>
> Reviewed-by: Lukasz Majewski <[hidden email]>
> ---
>  include/sys/resource.h                | 11 +++++
>  sysdeps/unix/syscalls.list            |  1 -
>  sysdeps/unix/sysv/linux/getrusage.c   | 58 +++++++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/tv32-compat.h | 47 ++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/wait4.c       | 50 ++++++++++++++++++++++-
>  5 files changed, 164 insertions(+), 3 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/getrusage.c

> --- a/sysdeps/unix/sysv/linux/wait4.c
> +++ b/sysdeps/unix/sysv/linux/wait4.c

>  pid_t
> -__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
> +__wait4_time64 (pid_t pid, int *stat_loc, int options, struct __rusage64 *usage)
>  {
>  #ifdef __NR_wait4
> +# if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64
>    return SYSCALL_CANCEL (wait4, pid, stat_loc, options, usage);
> +# else
> +  struct __rusage32 usage32;
> +  pid_t ret = SYSCALL_CANCEL (wait4, pid, stat_loc, options, &usage32);

pid_t? This makes the next check suspicious.

> +
> +  if (ret != 0)

(Looking into manual pages.)
Should this be
  if (ret < 0)
?

(Looking into
SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
                int, options, struct rusage __user *, ru)
{
        struct rusage r;
        long err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL);

        if (err > 0) {
                if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
                        return -EFAULT;
        }
        return err;
}
)

Or, more likely,
  if (ret <= 0)
?

Though

  if (ret > 0 && usage != NULL)
    rusage32_to_rusage64 (&usage32, usage);

seems to be more readable.

> +    return ret;
> +
> +  if (usage != NULL)
> +    rusage32_to_rusage64 (&usage32, usage);
> +
> +  return ret;
> +# endif
>  #elif defined (__ASSUME_WAITID_PID0_P_PGID)
>    idtype_t idtype = P_PID;
>  


>  # error "The kernel ABI does not provide a way to implement wait4"
>  #endif
>  }
> +
> +#if __TIMESIZE != 64
> +libc_hidden_def (__wait4_time64)
> +
> +pid_t
> +__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
> +{
> +  pid_t ret ;
> +  struct __rusage64 usage64;
> +
> +  ret = __wait4_time64 (pid, stat_loc, options, &usage64);
> +
> +  if (ret != 0)
> +    return ret;

Same problem here.
Additionally, usage != NULL check is missing.

> +
> +  rusage64_to_rusage (&usage64, usage);
> +
> +  return ret;
> +}
> +#endif
>  libc_hidden_def (__wait4);
>  weak_alias (__wait4, wait4)