From patchwork Mon Feb 10 17:43:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Francis X-Patchwork-Id: 37863 Received: (qmail 56326 invoked by alias); 10 Feb 2020 17:50:28 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 56138 invoked by uid 89); 10 Feb 2020 17:50:28 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT autolearn=ham version=3.3.1 spammy=voluntary, 1922, resident, Structures X-HELO: esa2.hgst.iphmx.com DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1581357026; x=1612893026; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AIEuWvbbI4YmOlRoKwqAmCVnlvdWWE7KAdVycNDhqHA=; b=C+ugl9ujrHsj+j9oBp5+xBU1m32cTRJ7fSno6OonYsPT/e42D21aqUFq PBsqF0DIFjmDMTddycWgPrPkr6FNr0iMXplxOkDvDESEO8/Q5ZdOquhuh TgT7Z4UGN++DZZ8vfytnqdVasrfzGSInWMaf8fe6jGRJUPaUiV7O7aoLX 5bl32qH9ZJZtrM7r461veHZVi3ZwxDR8gPLQC15UY0FVTFhtQmal7fXJl 0/V/hcxoB7xBydlS0C6+Xc5EKsWDs/qlTKtqDiPicK2dwHnTKMdwFcEe1 KfRfsx9dWCY5Cb4pbG+mds4pNHrab9Ndv7GdLS9d0gJ/KEokjrgbU+iy6 w==; IronPort-SDR: X0TRvT+OU/dmIkuuQYE6yBtSbW5s2YhR9HWZmVDUNR4Ir4Lnq7l56H7ge8IgRFmFd7wGf3O4VK bcgwHVzU2wzHDfYeTfsQOuZz6dMsKZ4s4afbkjh4NEav/fFLOsVxiBI5q9TE7fpmXqrMrVLeCv YoN0RyuoKvz84wU9TbLtKyxbV73a6NkW4GIIEPP//FpOdroA1vyrGj5NG5I1MaofalHyn1trrF po+uQd1lJy6DIt3yAwdSW9BO3/XL+RC3h1Sww9apoZRS3tCg5WsSC/m0YW9Ob/bWEiqeUIPMef wcs= IronPort-SDR: KgR2oZ6kjTpCjT3FwRFeekQa/6WRt/ZvEDF0+cv5L4v+GniqN7ryCoCyT3mkA+Rbm5oGih38ff ZRctbDtLbyU9aEwqSvmGPnZNTG9S/iBcGzL7V0d+/Rvc57YF7O1gR+7uWNigPLHNWDf/A/o0F4 6StzzfCqQTb3fn8C2/qdjDu4Bek+PBCuiqXbrdaC8ATL6MqwLVC88dUr2fSnvotak9oy3cKZwA 9MrmDOMWHDnrTUgLdVPEHxJUnALkfcS1NQOtqcNGbLFwULP1G6z6llA5fS2oyUq+8D0t/t2bx8 2cg432ED3+gDyEovqsFHLiZr IronPort-SDR: 12M8vG0xQyqhvDilogrRN6BDPDlwfvAAUsutLRhQfQO90sWoNw8jCdBEQ4qCRgARbAyDlTfyGz s2PUhkE/1KhLmNacWCrYAXCDxsV0AU9QIkoJzAyK0mH9r73bDoVv3Ym9W0lM43J7J7wRi1rIj5 bccm4XgIUYLdH9U7KMnA6+EIW9/7Pu053fNYx9m1sijdExSH9NmUVAeshxkf/T9fUf+4wozxVy CbZVWa1htUUEM2InYzhHEZzoBGcLkeYOm3BvDqrrAP6t/VT9WLU94OC5JaWHAm1e7ZBiM1r6gz Ug8= WDCIronportException: Internal From: Alistair Francis To: libc-alpha@sourceware.org Cc: alistair23@gmail.com, Alistair Francis Subject: [PATCH v2 6/6] linux: Use long time_t for wait4/getrusage Date: Mon, 10 Feb 2020 09:43:25 -0800 Message-Id: <20200210174325.6566-7-alistair.francis@wdc.com> In-Reply-To: <20200210174325.6566-1-alistair.francis@wdc.com> References: <20200210174325.6566-1-alistair.francis@wdc.com> MIME-Version: 1.0 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. --- include/sys/resource.h | 10 +++++ sysdeps/unix/sysv/linux/getrusage.c | 53 +++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/tv32-compat.h | 47 ++++++++++++++++++++++++ sysdeps/unix/sysv/linux/wait4.c | 40 ++++++++++++++++++-- 4 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/getrusage.c diff --git a/include/sys/resource.h b/include/sys/resource.h index 9d604dfe3e..8e115b4df8 100644 --- a/include/sys/resource.h +++ b/include/sys/resource.h @@ -134,5 +134,15 @@ 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 __wait464 __wait4 +#else +extern int __getrusage64 (enum __rusage_who who, struct __rusage64 *usage); +libc_hidden_proto (__getrusage64) +pid_t __wait464 (pid_t pid, int *stat_loc, int options, struct __rusage64 *usage); +libc_hidden_proto (__wait464) +#endif #endif #endif diff --git a/sysdeps/unix/sysv/linux/getrusage.c b/sysdeps/unix/sysv/linux/getrusage.c new file mode 100644 index 0000000000..f8bcd3f9d0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/getrusage.c @@ -0,0 +1,53 @@ +/* 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 + . */ + +#include +#include +#include +#include + +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 +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 4eb6f216ea..c2231f042f 100644 --- a/sysdeps/unix/sysv/linux/tv32-compat.h +++ b/sysdeps/unix/sysv/linux/tv32-compat.h @@ -24,6 +24,7 @@ #include #include #include +#include /* 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/wait4.c b/sysdeps/unix/sysv/linux/wait4.c index 3a8bed1169..73f1c24269 100644 --- a/sysdeps/unix/sysv/linux/wait4.c +++ b/sysdeps/unix/sysv/linux/wait4.c @@ -19,12 +19,22 @@ #include #include #include +#include pid_t -__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage) +__wait464 (pid_t pid, int *stat_loc, int options, struct __rusage64 *usage) { + struct __rusage32 usage32; #ifdef __NR_wait4 - return SYSCALL_CANCEL (wait4, pid, stat_loc, options, usage); + 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; #elif defined (__ASSUME_WAITID_PID0_P_PGID) idtype_t idtype = P_PID; @@ -41,7 +51,7 @@ __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage) options |= WEXITED; siginfo_t infop; - if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, usage) < 0) + if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, &usage32) < 0) return -1; if (stat_loc) @@ -70,8 +80,11 @@ __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage) } } + if (usage != NULL) + rusage32_to_rusage64 (&usage32, 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 +94,24 @@ __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 } +libc_hidden_def (__wait464) + +#if __TIMESIZE != 64 +pid_t +__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage) +{ + pid_t ret ; + struct __rusage64 usage64; + + ret = __wait464 (pid, stat_loc, options, &usage64); + + if (ret != 0) + return ret; + + rusage64_to_rusage (&usage64, usage); + + return ret; +} libc_hidden_def (__wait4); +#endif weak_alias (__wait4, wait4)