[6/6] linux: Use 32-bit time_t for rusage

Message ID 20200203183153.11635-7-alistair.francis@wdc.com
State New, archived
Headers

Commit Message

Alistair Francis Feb. 3, 2020, 6:31 p.m. UTC
  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 based 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 struct rusage but we have
to pass in and use a struct rusage32. The same appies to __getrusage.
---
 include/sys/resource.h                        |  6 ++
 .../linux/generic/wordsize-32/getrusage.c     | 52 ++++++++++++
 .../linux/generic/wordsize-32/tv32-compat.h   | 47 +++++++++++
 .../sysv/linux/generic/wordsize-32/wait4.c    | 83 +++++++++++++++++++
 4 files changed, 188 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
  

Comments

Lukasz Majewski Feb. 4, 2020, 2:23 p.m. UTC | #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 based 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 struct rusage but we
> have to pass in and use a struct rusage32. The same appies to
> __getrusage. ---
>  include/sys/resource.h                        |  6 ++
>  .../linux/generic/wordsize-32/getrusage.c     | 52 ++++++++++++

I wanted to test this code with ARM Y2038 test setup (yocto with qemu).

Unfortunately, for ARM32 (armv7) the path:
sysdeps/unix/sysv/linux/generic/wordsize-32/ is not reached at all.

In the build log (with make --debug) I do see following paths:

config_sysdirs='sysdeps/unix/sysv/linux/arm/le
sysdeps/unix/sysv/linux/arm sysdeps/arm/nptl sysdeps/unix/sysv/linux
sysdeps/nptl sysdeps/pthread sysdeps/gnu sysdeps/unix/inet
sysdeps/unix/sysv sysdeps/unix/arm sysdeps/unix sysdeps/posix
sysdeps/arm/le/armv7/multiarch sysdeps/arm/armv7/multiarch
sysdeps/arm/le/armv7 sysdeps/arm/armv7 sysdeps/arm/armv6t2
sysdeps/arm/armv6 sysdeps/arm/le sysdeps/arm sysdeps/wordsize-32
sysdeps/ieee754/flt-32 sysdeps/ieee754/dbl-64 sysdeps/ieee754
sysdeps/generic'

The "wordsize-32" only appears in ./sysdeps/wordsize-32 (and only
sysdeps/generic is defined for searching files to build).

How shall I tune my setup to also make
sysdeps/unix/sysv/linux/generic/wordsize-32/ accessible for glibc build?

Could you share output from yours build setup:

grep config-sysdir config.make


>  .../linux/generic/wordsize-32/tv32-compat.h   | 47 +++++++++++
>  .../sysv/linux/generic/wordsize-32/wait4.c    | 83
> +++++++++++++++++++ 4 files changed, 188 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/include/sys/resource.h b/include/sys/resource.h
> index 9d604dfe3e..fcba56303a 100644
> --- a/include/sys/resource.h
> +++ b/include/sys/resource.h
> @@ -134,5 +134,11 @@ 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
> +#else
> +extern int __getrusage64 (enum __rusage_who who, struct __rusage64

Please add libc_hidden_proto (__getrusage64)

> *usage); +#endif
>  #endif
>  #endif
> 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..a495cc6c8b
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c
> @@ -0,0 +1,52 @@
> +/* getrusage -- get the rusage struct.  Linux/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
> +__getrusage64 (enum __rusage_who who, struct __rusage64 *usage)
> +{
> +  struct __rusage32 usage32;
> +  if (INLINE_SYSCALL_CALL (getrusage, who, &usage32) == -1)
> +    return -1;
> +
> +  rusage32_to_rusage64 (&usage32, usage);
> +  return 0;
> +}
> +
> +#if __TIMESIZE != 64

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

Ok.

> 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
> 4eb6f216ea..c2231f042f 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 <sys/resource.h>
>  
>  /* Structures containing 'struct timeval' with 32-bit time_t.  */
>  struct __itimerval32
> @@ -32,4 +33,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/generic/wordsize-32/wait4.c
> b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c new file mode
> 100644 index 0000000000..ae42b2ecbb
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c
> @@ -0,0 +1,83 @@
> +/* 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)

If I may have one "small" remark - it seems like wait4 uses here struct
rusage.

Would it be a big problem if you provide 64 bit conversion for this
function as well?

I mean the conversion code for it:

pid_t
__wait4_time64 (pid_t pid, int *stat_loc, int options, struct __rusage64
*usage)
{

}

#if __TIMESIZE != 64

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

//conversions

ret = __wait4_time64 ()

//conversions

}

#endif

> +{
> +  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)
> +    {
> +      struct __rusage64 usage64;
> +      rusage32_to_rusage64 (&usage32, &usage64);
> +      rusage64_to_rusage (&usage64, usage);
> +    }
> +
> +  return infop.si_pid;
> +}
> +
> +libc_hidden_def (__wait4);
> +weak_alias (__wait4, wait4)

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
  
Andreas Schwab Feb. 4, 2020, 2:39 p.m. UTC | #2
On Feb 04 2020, Lukasz Majewski wrote:

> Unfortunately, for ARM32 (armv7) the path:
> sysdeps/unix/sysv/linux/generic/wordsize-32/ is not reached at all.

unix/linux/generic/wordsize-32 cannot be used for armv7, since it
doesn't use asm-generic syscalls.

Andreas.
  
Lukasz Majewski Feb. 4, 2020, 4:11 p.m. UTC | #3
Hi Andreas,

> On Feb 04 2020, Lukasz Majewski wrote:
> 
> > Unfortunately, for ARM32 (armv7) the path:
> > sysdeps/unix/sysv/linux/generic/wordsize-32/ is not reached at all.
> >  
> 
> unix/linux/generic/wordsize-32 cannot be used for armv7, since it
> doesn't use asm-generic syscalls.

Could you elaborate on this?

I though that for ARM32 glibc wrappers for syscalls were generated from
sysdeps/unix/syscalls.list. And those syscalls were matching ones from
uapi headers generated from
https://elixir.bootlin.com/linux/v5.3-rc5/source/arch/arm/tools/syscall.tbl#L420

However for ARM linux (5.1):
kernel-build-artifacts/include/generated/uapi/linux
 only has version.h [*]

and all relevant headers are available in:
kernel-build-artifacts/arch/arm/include/generated/uapi/asm/  {unistd*.h}


So I guess that you refer to the almost empty [*] directory ?
(And this means the lack of asm-generic syscalls in this case)?

> 
> Andreas.
> 




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
  
Andreas Schwab Feb. 4, 2020, 4:26 p.m. UTC | #4
On Feb 04 2020, Lukasz Majewski wrote:

> I though that for ARM32 glibc wrappers for syscalls were generated from
> sysdeps/unix/syscalls.list.

But linux/generic/wordsize-32/fstatfs.c would override that, for
example.

Andreas.
  
Lukasz Majewski Feb. 4, 2020, 11:49 p.m. UTC | #5
Hi Andreas,

> On Feb 04 2020, Lukasz Majewski wrote:
> 
> > I though that for ARM32 glibc wrappers for syscalls were generated
> > from sysdeps/unix/syscalls.list.  
> 
> But linux/generic/wordsize-32/fstatfs.c would override that, for
> example.

And this is IMHO the issue. Giving ARM32 full access to code located in
linux/generic/wordsize-32 is fragile as it will override wrappers
generated automatically.

In fact for ARM32 one would need either to locate the [sg]etitimer.c and
getrusage.c in e.g. sysdeps/unix/sysv/linux or allow compiling only
mentioned above files in linux/generic/wordsize-32.

The latter option would be possible with hack as:

introduce in sysdeps/unix/sysv/linux/arm/getitimer.c
#include <sysdeps/unix/sysv/linux/generic/wordsize-32/getitimer.c>


When following this idiom for setitimer and getrusage, the arm32 port
seems to compile with those files.

Is it the recommended way?

> 
> Andreas.
> 




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
  
Lukasz Majewski Feb. 5, 2020, 10:06 a.m. UTC | #6
Dear community,

> Hi Andreas,
> 
> > On Feb 04 2020, Lukasz Majewski wrote:
> >   
> > > I though that for ARM32 glibc wrappers for syscalls were generated
> > > from sysdeps/unix/syscalls.list.    
> > 
> > But linux/generic/wordsize-32/fstatfs.c would override that, for
> > example.  
> 
> And this is IMHO the issue. Giving ARM32 full access to code located
> in linux/generic/wordsize-32 is fragile as it will override wrappers
> generated automatically.
> 
> In fact for ARM32 one would need either to locate the [sg]etitimer.c
> and getrusage.c in e.g. sysdeps/unix/sysv/linux or allow compiling
> only mentioned above files in linux/generic/wordsize-32.
> 
> The latter option would be possible with hack as:
> 
> introduce in sysdeps/unix/sysv/linux/arm/getitimer.c
> #include <sysdeps/unix/sysv/linux/generic/wordsize-32/getitimer.c>
> 
> 
> When following this idiom for setitimer and getrusage, the arm32 port
> seems to compile with those files.
> 
> Is it the recommended way?

Any thoughts ?


Just a tester's note:
---------------------

I've run tested this approach with the QEMU + Yocto Y2038 setup [*] and
it seems like this approach (recreation of files with only 
#include <linux/generic/wordsize-32/*.c> in
sysdeps/unix/sysv/linux) works seamlessly when/without Y2038
redirection code applied.


(The only problem is with __setitimer() not handling "old_value" as
NULL properly, but I've pointed it out in the other answer for this
patch).

Moreover, as the path sysdeps/unix/sysv/linux/arm is searched earlier
than sysdeps/unix, there is no need to remove [gs]etitimer and
getrusage from sysdeps/unix/syscalls.list.
(But the same approach would be needed if for example ppc32 or mips32
will need the Y2038 safe conversion for this function).




Links:

[*] - https://github.com/lmajewski/meta-y2038

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




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
  
Andreas Schwab Feb. 5, 2020, 11 a.m. UTC | #7
Why can't the implementation be put in sysdeps/unix/sysv/linux?

Andreas.
  
Lukasz Majewski Feb. 5, 2020, 12:38 p.m. UTC | #8
Hi Andreas,

> Why can't the implementation be put in sysdeps/unix/sysv/linux?
> 

I would opt for putting the implementation there.

However, Alistair shall say if such move would work for e.g. RV32 (or
maybe there are some issues).

> Andreas.
> 




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
  
Joseph Myers Feb. 6, 2020, 9:15 p.m. UTC | #9
On Tue, 4 Feb 2020, Lukasz Majewski wrote:

> > unix/linux/generic/wordsize-32 cannot be used for armv7, since it
> > doesn't use asm-generic syscalls.
> 
> Could you elaborate on this?

There was a long discussion on the linux-kernel mailing list in 2008, much 
of which was under the subject "microblaze syscall list".

The conclusion of that discussion was that, whereas architectures for 
which support was added to the Linux kernel up to that point each had 
their own syscall ABI (their own syscall numbers, their own set of 
associated structure layouts and constants - those layouts and constants 
often following those used by some older proprietary Unix on the same 
architecture, in the cases of the oldest Linux kernel ports), newer Linux 
kernel ports would share a common syscall ABI as far as possible, meaning 
the same syscall numbers, constants and structure layouts.  This common 
ABI is known as the generic or asm-generic ABI.

In glibc, sysdeps/unix/sysv/linux/generic is for architectures using the 
asm-generic syscall ABI, and *only* for such architectures (which, in the 
end, did not include microblaze).  This should not be confused with other 
uses of the word "generic" in the glibc context, in particular 
sysdeps/generic/.

As the Linux kernel arm port was added before 2008, it does not use the 
generic ABI and so cannot use sysdeps/unix/sysv/linux/generic.
  
Lukasz Majewski Feb. 7, 2020, 8:51 a.m. UTC | #10
Hi Joseph,

> On Tue, 4 Feb 2020, Lukasz Majewski wrote:
> 
> > > unix/linux/generic/wordsize-32 cannot be used for armv7, since it
> > > doesn't use asm-generic syscalls.  
> > 
> > Could you elaborate on this?  
> 
> There was a long discussion on the linux-kernel mailing list in 2008,
> much of which was under the subject "microblaze syscall list".
> 
> The conclusion of that discussion was that, whereas architectures for 
> which support was added to the Linux kernel up to that point each had 
> their own syscall ABI (their own syscall numbers, their own set of 
> associated structure layouts and constants - those layouts and
> constants often following those used by some older proprietary Unix
> on the same architecture, in the cases of the oldest Linux kernel
> ports), newer Linux kernel ports would share a common syscall ABI as
> far as possible, meaning the same syscall numbers, constants and
> structure layouts.  This common ABI is known as the generic or
> asm-generic ABI.
> 
> In glibc, sysdeps/unix/sysv/linux/generic is for architectures using
> the asm-generic syscall ABI, and *only* for such architectures
> (which, in the end, did not include microblaze).  This should not be
> confused with other uses of the word "generic" in the glibc context,
> in particular sysdeps/generic/.
> 
> As the Linux kernel arm port was added before 2008, it does not use
> the generic ABI and so cannot use sysdeps/unix/sysv/linux/generic.
> 

Thank you for the explanation.

Considering the above - it would be best to place
setitimer/getitimer/getrusage code into sysdeps/unix/sysv/linux , so
all Linux glibc ports could use them.


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 Feb. 7, 2020, 7:48 p.m. UTC | #11
On Tue, Feb 4, 2020 at 6:23 AM 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 based 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 struct rusage but we
> > have to pass in and use a struct rusage32. The same appies to
> > __getrusage. ---
> >  include/sys/resource.h                        |  6 ++
> >  .../linux/generic/wordsize-32/getrusage.c     | 52 ++++++++++++
>
> I wanted to test this code with ARM Y2038 test setup (yocto with qemu).

Thanks for doing that!

>
> Unfortunately, for ARM32 (armv7) the path:
> sysdeps/unix/sysv/linux/generic/wordsize-32/ is not reached at all.
>
> In the build log (with make --debug) I do see following paths:
>
> config_sysdirs='sysdeps/unix/sysv/linux/arm/le
> sysdeps/unix/sysv/linux/arm sysdeps/arm/nptl sysdeps/unix/sysv/linux
> sysdeps/nptl sysdeps/pthread sysdeps/gnu sysdeps/unix/inet
> sysdeps/unix/sysv sysdeps/unix/arm sysdeps/unix sysdeps/posix
> sysdeps/arm/le/armv7/multiarch sysdeps/arm/armv7/multiarch
> sysdeps/arm/le/armv7 sysdeps/arm/armv7 sysdeps/arm/armv6t2
> sysdeps/arm/armv6 sysdeps/arm/le sysdeps/arm sysdeps/wordsize-32
> sysdeps/ieee754/flt-32 sysdeps/ieee754/dbl-64 sysdeps/ieee754
> sysdeps/generic'
>
> The "wordsize-32" only appears in ./sysdeps/wordsize-32 (and only
> sysdeps/generic is defined for searching files to build).
>
> How shall I tune my setup to also make
> sysdeps/unix/sysv/linux/generic/wordsize-32/ accessible for glibc build?
>
> Could you share output from yours build setup:
>
> grep config-sysdir config.make

I'll comment on this in a later reply as there has been some
discussion in this thread.

>
>
> >  .../linux/generic/wordsize-32/tv32-compat.h   | 47 +++++++++++
> >  .../sysv/linux/generic/wordsize-32/wait4.c    | 83
> > +++++++++++++++++++ 4 files changed, 188 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/include/sys/resource.h b/include/sys/resource.h
> > index 9d604dfe3e..fcba56303a 100644
> > --- a/include/sys/resource.h
> > +++ b/include/sys/resource.h
> > @@ -134,5 +134,11 @@ 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
> > +#else
> > +extern int __getrusage64 (enum __rusage_who who, struct __rusage64
>
> Please add libc_hidden_proto (__getrusage64)

Done

>
> > *usage); +#endif
> >  #endif
> >  #endif
> > 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..a495cc6c8b
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c
> > @@ -0,0 +1,52 @@
> > +/* getrusage -- get the rusage struct.  Linux/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
> > +__getrusage64 (enum __rusage_who who, struct __rusage64 *usage)
> > +{
> > +  struct __rusage32 usage32;
> > +  if (INLINE_SYSCALL_CALL (getrusage, who, &usage32) == -1)
> > +    return -1;
> > +
> > +  rusage32_to_rusage64 (&usage32, usage);
> > +  return 0;
> > +}
> > +
> > +#if __TIMESIZE != 64
>
> Please add libc_hidden_def (__getrusage64)

Done

>
> > +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)
>
> Ok.
>
> > 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
> > 4eb6f216ea..c2231f042f 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 <sys/resource.h>
> >
> >  /* Structures containing 'struct timeval' with 32-bit time_t.  */
> >  struct __itimerval32
> > @@ -32,4 +33,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/generic/wordsize-32/wait4.c
> > b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c new file mode
> > 100644 index 0000000000..ae42b2ecbb
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c
> > @@ -0,0 +1,83 @@
> > +/* 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)
>
> If I may have one "small" remark - it seems like wait4 uses here struct
> rusage.
>
> Would it be a big problem if you provide 64 bit conversion for this
> function as well?
>
> I mean the conversion code for it:
>
> pid_t
> __wait4_time64 (pid_t pid, int *stat_loc, int options, struct __rusage64
> *usage)
> {
>
> }
>
> #if __TIMESIZE != 64
>
> pid_t
> __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage)
> {
>
> //conversions
>
> ret = __wait4_time64 ()
>
> //conversions
>
> }
>
> #endif

Yep, I have added this.

Alistair

>
> > +{
> > +  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)
> > +    {
> > +      struct __rusage64 usage64;
> > +      rusage32_to_rusage64 (&usage32, &usage64);
> > +      rusage64_to_rusage (&usage64, usage);
> > +    }
> > +
> > +  return infop.si_pid;
> > +}
> > +
> > +libc_hidden_def (__wait4);
> > +weak_alias (__wait4, wait4)
>
> 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 Feb. 10, 2020, 5:45 p.m. UTC | #12
On Fri, Feb 7, 2020 at 12:51 AM Lukasz Majewski <lukma@denx.de> wrote:
>
> Hi Joseph,
>
> > On Tue, 4 Feb 2020, Lukasz Majewski wrote:
> >
> > > > unix/linux/generic/wordsize-32 cannot be used for armv7, since it
> > > > doesn't use asm-generic syscalls.
> > >
> > > Could you elaborate on this?
> >
> > There was a long discussion on the linux-kernel mailing list in 2008,
> > much of which was under the subject "microblaze syscall list".
> >
> > The conclusion of that discussion was that, whereas architectures for
> > which support was added to the Linux kernel up to that point each had
> > their own syscall ABI (their own syscall numbers, their own set of
> > associated structure layouts and constants - those layouts and
> > constants often following those used by some older proprietary Unix
> > on the same architecture, in the cases of the oldest Linux kernel
> > ports), newer Linux kernel ports would share a common syscall ABI as
> > far as possible, meaning the same syscall numbers, constants and
> > structure layouts.  This common ABI is known as the generic or
> > asm-generic ABI.
> >
> > In glibc, sysdeps/unix/sysv/linux/generic is for architectures using
> > the asm-generic syscall ABI, and *only* for such architectures
> > (which, in the end, did not include microblaze).  This should not be
> > confused with other uses of the word "generic" in the glibc context,
> > in particular sysdeps/generic/.
> >
> > As the Linux kernel arm port was added before 2008, it does not use
> > the generic ABI and so cannot use sysdeps/unix/sysv/linux/generic.
> >
>
> Thank you for the explanation.
>
> Considering the above - it would be best to place
> setitimer/getitimer/getrusage code into sysdeps/unix/sysv/linux , so
> all Linux glibc ports could use them.

I just sent a v2 that does exactly that.

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/include/sys/resource.h b/include/sys/resource.h
index 9d604dfe3e..fcba56303a 100644
--- a/include/sys/resource.h
+++ b/include/sys/resource.h
@@ -134,5 +134,11 @@  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
+#else
+extern int __getrusage64 (enum __rusage_who who, struct __rusage64 *usage);
+#endif
 #endif
 #endif
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..a495cc6c8b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/getrusage.c
@@ -0,0 +1,52 @@ 
+/* getrusage -- get the rusage struct.  Linux/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
+__getrusage64 (enum __rusage_who who, struct __rusage64 *usage)
+{
+  struct __rusage32 usage32;
+  if (INLINE_SYSCALL_CALL (getrusage, who, &usage32) == -1)
+    return -1;
+
+  rusage32_to_rusage64 (&usage32, usage);
+  return 0;
+}
+
+#if __TIMESIZE != 64
+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/generic/wordsize-32/tv32-compat.h b/sysdeps/unix/sysv/linux/generic/wordsize-32/tv32-compat.h
index 4eb6f216ea..c2231f042f 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 <sys/resource.h>
 
 /* Structures containing 'struct timeval' with 32-bit time_t.  */
 struct __itimerval32
@@ -32,4 +33,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/generic/wordsize-32/wait4.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c
new file mode 100644
index 0000000000..ae42b2ecbb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/wait4.c
@@ -0,0 +1,83 @@ 
+/* 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)
+    {
+      struct __rusage64 usage64;
+      rusage32_to_rusage64 (&usage32, &usage64);
+      rusage64_to_rusage (&usage64, usage);
+    }
+
+  return infop.si_pid;
+}
+
+libc_hidden_def (__wait4);
+weak_alias (__wait4, wait4)