[RFC,v6,05/23] linux: Use 32-bit time_t for rusage

Message ID 1d410ddd9672d470e0d776a1a6a8c2cf91821fbe.1578824547.git.alistair.francis@wdc.com
State New
Headers show
Series
  • RISC-V glibc port for the 32-bit
Related show

Commit Message

Alistair Francis Jan. 12, 2020, 10:33 a.m.
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.

This means that all 32-bit architectures with a 64-bit time_t will be
able to use this generic implementation.

This code is bsaed on similar code in alpha, but adjusted to pass the
32-bit time_t to the kernel.

We can't directly call __wait4 as it expects a structrusage but we have
to pass in and use a struct rusage32. The same appies to __getrusage.
---
 .../linux/generic/wordsize-32/getrusage.c     | 39 +++++++++
 .../linux/generic/wordsize-32/tv32-compat.h   | 47 +++++++++++
 .../sysv/linux/generic/wordsize-32/wait4.c    | 79 +++++++++++++++++++
 3 files changed, 165 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c
 create mode 100644 sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c

-- 
2.24.1

Comments

Lukasz Majewski Jan. 14, 2020, 11:58 a.m. | #1
Hi Alistair,

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

> 

> This means that all 32-bit architectures with a 64-bit time_t will be

> able to use this generic implementation.

> 

> This code is bsaed on similar code in alpha, but adjusted to pass the

	       ^^^^^ - based?

> 32-bit time_t to the kernel.

> 

> We can't directly call __wait4 as it expects a structrusage but we

						 ^^^^^^^^^^^^ - struct
						 rusage

> have to pass in and use a struct rusage32. The same appies to

> __getrusage. ---

>  .../linux/generic/wordsize-32/getrusage.c     | 39 +++++++++

>  .../linux/generic/wordsize-32/tv32-compat.h   | 47 +++++++++++

>  .../sysv/linux/generic/wordsize-32/wait4.c    | 79

> +++++++++++++++++++ 3 files changed, 165 insertions(+)

>  create mode 100644

> sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c create mode

> 100644 sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c

> 

> diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c

> b/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c new file

> mode 100644 index 0000000000..2ada94a954

> --- /dev/null

> +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c

> @@ -0,0 +1,39 @@

> +/* utimes -- change file timestamps.  Linux/RV32/tv32 version.

      
Please update the in-comment header.

> +   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 <sysdep.h>

> +#include <tv32-compat.h>

> +

> +int

> +__getrusage (int who, struct rusage *usage)

> +{

> +#if __TIMESIZE == 64

> +  struct rusage32 usage32;

> +  if (INLINE_SYSCALL_CALL (getrusage, who, &usage32) == -1)

> +    return -1;

> +

> +  rusage32_to_rusage64 (&usage32, usage);

> +  return 0;

> +#else

> +  return INLINE_SYSCALL_CALL (getrusage, who, usage);

> +#endif

> +}


This is the same issue as pointed out with __setitimer support.

Following the conversion convention (as in e.g. clock_settime.c) would
allow Y2038 safe 32 bit ports benefit from this patch.

> +

> +strong_alias (__getrusage, getrusage)

> diff --git

> a/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h

> b/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h index

> aa960a6632..8a4bd15002 100644 ---

> a/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h +++

> b/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h @@ -24,6

> +24,7 @@ #include <bits/types.h> #include <bits/types/time_t.h>

>  #include <bits/types/struct_timeval.h>

> +#include <bits/types/struct_rusage.h>

>  

>  /* Structures containing 'struct timeval' with 32-bit time_t.  */

>  struct itimerval32

> @@ -32,4 +33,50 @@ struct itimerval32

>    struct __timeval_long it_value;

>  };

>  

> +struct rusage32


struct __rusage32 ?

> +{

> +  struct __timeval_long ru_utime;	/* user time used */

> +  struct __timeval_long ru_stime;	/* system time used */

	
	    As pointed out in the other comment - maybe struct
	    __timeval32 would be more appropriate?

	This is the same convention as we already have with struct
	__timespec64 and __itimerspec64

> +  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 rusage *restrict r64)

> +{

> +  /* Make sure the entire output structure is cleared, including

> +     padding and reserved fields.  */

> +  memset (r64, 0, sizeof *r64);

> +

> +  r64->ru_utime    = valid_timeval_long_to_timeval64 (r32->ru_utime);

> +  r64->ru_stime    = valid_timeval_long_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/generic/wordsize-32/wait4.c

> b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c new file mode

> 100644 index 0000000000..a4a81a0587

> --- /dev/null

> +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c

> @@ -0,0 +1,79 @@

> +/* wait4 -- wait for process to change state.  Linux/RV32/tv32

> 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/wait.h>

> +#include <sys/resource.h>

> +#include <sysdep-cancel.h>

> +#include <tv32-compat.h>

> +

> +pid_t

> +__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)

> +{

> +  struct rusage32 usage32;

> +  idtype_t idtype = P_PID;

> +

> +  if (pid < -1)

> +    {

> +      idtype = P_PGID;

> +      pid *= -1;

> +    }

> +  else if (pid == -1)

> +    idtype = P_ALL;

> +  else if (pid == 0)

> +    idtype = P_PGID;

> +

> +  options |= WEXITED;

> +

> +  siginfo_t infop;

> +  if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options,

> &usage32) < 0)

> +    return -1;

> +

> +  if (stat_loc)

> +    {

> +      switch (infop.si_code)

> +        {

> +        case CLD_EXITED:

> +          *stat_loc = W_EXITCODE (infop.si_status, 0);

> +          break;

> +        case CLD_DUMPED:

> +          *stat_loc = WCOREFLAG | infop.si_status;

> +    break;

> +        case CLD_KILLED:

> +          *stat_loc = infop.si_status;

> +          break;

> +        case CLD_TRAPPED:

> +        case CLD_STOPPED:

> +          *stat_loc = W_STOPCODE (infop.si_status);

> +          break;

> +        case CLD_CONTINUED:

> +          *stat_loc = __W_CONTINUED;

> +          break;

> +  default:

> +    *stat_loc = 0;

> +    break;

> +        }

> +    }

> +

> +  if (usage != NULL)

> +    rusage32_to_rusage64 (&usage32, usage);

> +

> +  return infop.si_pid;

> +}

> +

> +libc_hidden_def (__wait4);

> +weak_alias (__wait4, wait4)


This wait4 implementation (as it doesn't use #define __TIMESIZE == 64)
could be used by all 32 bit ports. Am I right?


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
Alistair Francis Jan. 15, 2020, 11:42 p.m. | #2
On Tue, Jan 14, 2020 at 9:58 PM Lukasz Majewski <lukma@denx.de> wrote:
>

> Hi Alistair,

>

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

> >

> > This means that all 32-bit architectures with a 64-bit time_t will be

> > able to use this generic implementation.

> >

> > This code is bsaed on similar code in alpha, but adjusted to pass the

>                ^^^^^ - based?

>

> > 32-bit time_t to the kernel.

> >

> > We can't directly call __wait4 as it expects a structrusage but we

>                                                  ^^^^^^^^^^^^ - struct

>                                                  rusage

>

> > have to pass in and use a struct rusage32. The same appies to

> > __getrusage. ---

> >  .../linux/generic/wordsize-32/getrusage.c     | 39 +++++++++

> >  .../linux/generic/wordsize-32/tv32-compat.h   | 47 +++++++++++

> >  .../sysv/linux/generic/wordsize-32/wait4.c    | 79

> > +++++++++++++++++++ 3 files changed, 165 insertions(+)

> >  create mode 100644

> > sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c create mode

> > 100644 sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c

> >

> > diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c

> > b/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c new file

> > mode 100644 index 0000000000..2ada94a954

> > --- /dev/null

> > +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c

> > @@ -0,0 +1,39 @@

> > +/* utimes -- change file timestamps.  Linux/RV32/tv32 version.

>

> Please update the in-comment header.


Fixed!

>

> > +   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 <sysdep.h>

> > +#include <tv32-compat.h>

> > +

> > +int

> > +__getrusage (int who, struct rusage *usage)

> > +{

> > +#if __TIMESIZE == 64

> > +  struct rusage32 usage32;

> > +  if (INLINE_SYSCALL_CALL (getrusage, who, &usage32) == -1)

> > +    return -1;

> > +

> > +  rusage32_to_rusage64 (&usage32, usage);

> > +  return 0;

> > +#else

> > +  return INLINE_SYSCALL_CALL (getrusage, who, usage);

> > +#endif

> > +}

>

> This is the same issue as pointed out with __setitimer support.

>

> Following the conversion convention (as in e.g. clock_settime.c) would

> allow Y2038 safe 32 bit ports benefit from this patch.


I commented on the other patch, I'm not clear what you mean here.

>

> > +

> > +strong_alias (__getrusage, getrusage)

> > diff --git

> > a/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h

> > b/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h index

> > aa960a6632..8a4bd15002 100644 ---

> > a/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h +++

> > b/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h @@ -24,6

> > +24,7 @@ #include <bits/types.h> #include <bits/types/time_t.h>

> >  #include <bits/types/struct_timeval.h>

> > +#include <bits/types/struct_rusage.h>

> >

> >  /* Structures containing 'struct timeval' with 32-bit time_t.  */

> >  struct itimerval32

> > @@ -32,4 +33,50 @@ struct itimerval32

> >    struct __timeval_long it_value;

> >  };

> >

> > +struct rusage32

>

> struct __rusage32 ?


Good idea, updated

>

> > +{

> > +  struct __timeval_long ru_utime;    /* user time used */

> > +  struct __timeval_long ru_stime;    /* system time used */

>

>             As pointed out in the other comment - maybe struct

>             __timeval32 would be more appropriate?

>

>         This is the same convention as we already have with struct

>         __timespec64 and __itimerspec64


Yeah, I think you are probably right. I'll wait and see what others
think of the other thread though.

>

> > +  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 rusage *restrict r64)

> > +{

> > +  /* Make sure the entire output structure is cleared, including

> > +     padding and reserved fields.  */

> > +  memset (r64, 0, sizeof *r64);

> > +

> > +  r64->ru_utime    = valid_timeval_long_to_timeval64 (r32->ru_utime);

> > +  r64->ru_stime    = valid_timeval_long_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/generic/wordsize-32/wait4.c

> > b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c new file mode

> > 100644 index 0000000000..a4a81a0587

> > --- /dev/null

> > +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c

> > @@ -0,0 +1,79 @@

> > +/* wait4 -- wait for process to change state.  Linux/RV32/tv32

> > 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/wait.h>

> > +#include <sys/resource.h>

> > +#include <sysdep-cancel.h>

> > +#include <tv32-compat.h>

> > +

> > +pid_t

> > +__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)

> > +{

> > +  struct rusage32 usage32;

> > +  idtype_t idtype = P_PID;

> > +

> > +  if (pid < -1)

> > +    {

> > +      idtype = P_PGID;

> > +      pid *= -1;

> > +    }

> > +  else if (pid == -1)

> > +    idtype = P_ALL;

> > +  else if (pid == 0)

> > +    idtype = P_PGID;

> > +

> > +  options |= WEXITED;

> > +

> > +  siginfo_t infop;

> > +  if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options,

> > &usage32) < 0)

> > +    return -1;

> > +

> > +  if (stat_loc)

> > +    {

> > +      switch (infop.si_code)

> > +        {

> > +        case CLD_EXITED:

> > +          *stat_loc = W_EXITCODE (infop.si_status, 0);

> > +          break;

> > +        case CLD_DUMPED:

> > +          *stat_loc = WCOREFLAG | infop.si_status;

> > +    break;

> > +        case CLD_KILLED:

> > +          *stat_loc = infop.si_status;

> > +          break;

> > +        case CLD_TRAPPED:

> > +        case CLD_STOPPED:

> > +          *stat_loc = W_STOPCODE (infop.si_status);

> > +          break;

> > +        case CLD_CONTINUED:

> > +          *stat_loc = __W_CONTINUED;

> > +          break;

> > +  default:

> > +    *stat_loc = 0;

> > +    break;

> > +        }

> > +    }

> > +

> > +  if (usage != NULL)

> > +    rusage32_to_rusage64 (&usage32, usage);

> > +

> > +  return infop.si_pid;

> > +}

> > +

> > +libc_hidden_def (__wait4);

> > +weak_alias (__wait4, wait4)

>

> This wait4 implementation (as it doesn't use #define __TIMESIZE == 64)

> could be used by all 32 bit ports. Am I right?


Yes, all of these changes apply to all 32-bit ports.

Alistair

>

>

> Best regards,

>

> Lukasz Majewski

>

> --

>

> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk

> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Patch

diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c
new file mode 100644
index 0000000000..2ada94a954
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c
@@ -0,0 +1,39 @@ 
+/* utimes -- change file timestamps.  Linux/RV32/tv32 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 <sysdep.h>
+#include <tv32-compat.h>
+
+int
+__getrusage (int who, struct rusage *usage)
+{
+#if __TIMESIZE == 64
+  struct rusage32 usage32;
+  if (INLINE_SYSCALL_CALL (getrusage, who, &usage32) == -1)
+    return -1;
+
+  rusage32_to_rusage64 (&usage32, usage);
+  return 0;
+#else
+  return INLINE_SYSCALL_CALL (getrusage, who, usage);
+#endif
+}
+
+strong_alias (__getrusage, getrusage)
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h b/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h
index aa960a6632..8a4bd15002 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h
@@ -24,6 +24,7 @@ 
 #include <bits/types.h>
 #include <bits/types/time_t.h>
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_rusage.h>
 
 /* Structures containing 'struct timeval' with 32-bit time_t.  */
 struct itimerval32
@@ -32,4 +33,50 @@  struct itimerval32
   struct __timeval_long it_value;
 };
 
+struct rusage32
+{
+  struct __timeval_long ru_utime;	/* user time used */
+  struct __timeval_long 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 rusage *restrict r64)
+{
+  /* Make sure the entire output structure is cleared, including
+     padding and reserved fields.  */
+  memset (r64, 0, sizeof *r64);
+
+  r64->ru_utime    = valid_timeval_long_to_timeval64 (r32->ru_utime);
+  r64->ru_stime    = valid_timeval_long_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/generic/wordsize-32/wait4.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c
new file mode 100644
index 0000000000..a4a81a0587
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c
@@ -0,0 +1,79 @@ 
+/* wait4 -- wait for process to change state.  Linux/RV32/tv32 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/wait.h>
+#include <sys/resource.h>
+#include <sysdep-cancel.h>
+#include <tv32-compat.h>
+
+pid_t
+__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
+{
+  struct rusage32 usage32;
+  idtype_t idtype = P_PID;
+
+  if (pid < -1)
+    {
+      idtype = P_PGID;
+      pid *= -1;
+    }
+  else if (pid == -1)
+    idtype = P_ALL;
+  else if (pid == 0)
+    idtype = P_PGID;
+
+  options |= WEXITED;
+
+  siginfo_t infop;
+  if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, &usage32) < 0)
+    return -1;
+
+  if (stat_loc)
+    {
+      switch (infop.si_code)
+        {
+        case CLD_EXITED:
+          *stat_loc = W_EXITCODE (infop.si_status, 0);
+          break;
+        case CLD_DUMPED:
+          *stat_loc = WCOREFLAG | infop.si_status;
+    break;
+        case CLD_KILLED:
+          *stat_loc = infop.si_status;
+          break;
+        case CLD_TRAPPED:
+        case CLD_STOPPED:
+          *stat_loc = W_STOPCODE (infop.si_status);
+          break;
+        case CLD_CONTINUED:
+          *stat_loc = __W_CONTINUED;
+          break;
+  default:
+    *stat_loc = 0;
+    break;
+        }
+    }
+
+  if (usage != NULL)
+    rusage32_to_rusage64 (&usage32, usage);
+
+  return infop.si_pid;
+}
+
+libc_hidden_def (__wait4);
+weak_alias (__wait4, wait4)