From patchwork Fri Dec 10 11:02:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 48769 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2D37B3858C27 for ; Fri, 10 Dec 2021 11:03:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2D37B3858C27 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1639134182; bh=KcOD8c3pXxvqq9HwTiA7d8mZdrb6mdUL7t1NKPiSn/4=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=c6qrVOaIK4lVXDq3kFkOFCyhE8dKy8iF34EUVV3fuPWcX/2/WJ//nP6nNxx7hY6gz WIrEAJAFZIgm2q6whJ8yV34ejegaxWExtdLUCqN4BqphVrfvk/EkE0IsgAxVXdZ6rE qbexb9eUAH5BxMoGTz7MztNd78sHaAZTPxSRxYy8= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-ua1-x935.google.com (mail-ua1-x935.google.com [IPv6:2607:f8b0:4864:20::935]) by sourceware.org (Postfix) with ESMTPS id 6EB8B3858C27 for ; Fri, 10 Dec 2021 11:02:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6EB8B3858C27 Received: by mail-ua1-x935.google.com with SMTP id o1so16094114uap.4 for ; Fri, 10 Dec 2021 03:02:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=KcOD8c3pXxvqq9HwTiA7d8mZdrb6mdUL7t1NKPiSn/4=; b=UHbBjwZXuoZq0X9mu/ihRPZJNgfjTdSDrrMPjWMUAHlOF06jlrOUfTCwgpILT0NCV4 lUEWiapR9Dwq332CIrPrd1kErFvTuqSpEPHd1kNzYNgIH/x9nI3wgscgwGighnE+BryU F/O8pGFPr2F8WkcfmXqAkUoSjqNC98tfobPR3Xl6eVLDATzupci6jC31mMWWdhJzia7y xZTi9tuAXuoRvvCiCt1gz9q8xr9zDhuQQiM3Fr8CGIhUvtP+5f8o8NLbWBgFQxbPldWT IYhD+UlxOtKN+6Zok68l0UeumOZYq8Rt3FMmrKKS1PDQmef4J/lOW2W/W+PGag1TYxtB yiKA== X-Gm-Message-State: AOAM532k6HAo3rB/BPxm2qYmKvPZCodO2pk0GD7RctDmmHo5y6HY7Qxk 0OdbljN1gg/2pVVY5fyGBZ72jx3/SvZk4w== X-Google-Smtp-Source: ABdhPJykzM0REvJrLAf0Tu9hIRJO7ppRLiEb7/0resovOcBKwXMvrTJ4LGoaAJmEOoGcapJQwNolaA== X-Received: by 2002:a67:e3ca:: with SMTP id k10mr15182345vsm.45.1639134157307; Fri, 10 Dec 2021 03:02:37 -0800 (PST) Received: from birita.. ([2804:431:c7ca:a776:ce11:d591:8bd5:613f]) by smtp.gmail.com with ESMTPSA id y22sm1579425vsy.33.2021.12.10.03.02.36 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Dec 2021 03:02:37 -0800 (PST) To: libc-alpha@sourceware.org Subject: [PATCH v2] linux: Use 'long int' for timespec tv_nsec on x32 (BZ #16437) Date: Fri, 10 Dec 2021 08:02:33 -0300 Message-Id: <20211210110233.1401640-1-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 X-Spam-Status: No, score=-12.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" Although the kernel ABI uses 64-bit (so it can re-use the syscall logic from x86_64), POSIX states the type to be 'long int'. It requires to explicit signal extend the value on syscalls that take the value to avoid requiring bumping the minimum kernel version (ea2ce8f3514e ("time: Fix get_timespec64() for y2038 safe compat interfaces") got merged into v4.18, futex and recvmsg followed in v5.1, but v5.6 is considered 'complete'). The fix uses 'long long int' array to represent 'struct timespec', since it allows a simpler code than define a kernel specific timespec. There is no need to compat symbol, the now high-bits are not used to represent the nanoseconds and for some syscalls it only issues an error (which hardly indicates the need of compat symbol). Checked on x86_64-linux-gnu-x32 with kernel 4.4.0 and 5.13. --- Changes from v1: * Remove the usage of zero width bitfields. --- conform/data/signal.h-data | 3 +- conform/data/sys/select.h-data | 3 +- conform/data/sys/stat.h-data | 3 +- conform/data/time.h-data | 3 +- nptl/futex-internal.c | 10 +++++-- sysdeps/unix/sysv/linux/clock_nanosleep.c | 3 +- sysdeps/unix/sysv/linux/clock_settime.c | 3 +- sysdeps/unix/sysv/linux/mq_timedreceive.c | 8 +++++- sysdeps/unix/sysv/linux/mq_timedsend.c | 8 +++++- sysdeps/unix/sysv/linux/ppoll.c | 13 ++++----- sysdeps/unix/sysv/linux/pselect.c | 19 ++++++------- sysdeps/unix/sysv/linux/recvmmsg.c | 8 +++++- sysdeps/unix/sysv/linux/select.c | 31 ++++++++++----------- sysdeps/unix/sysv/linux/semtimedop.c | 10 +++++-- sysdeps/unix/sysv/linux/sigtimedwait.c | 10 +++++-- sysdeps/unix/sysv/linux/timer_settime.c | 7 +++-- sysdeps/unix/sysv/linux/timerfd_settime.c | 6 +++- sysdeps/unix/sysv/linux/utimensat.c | 19 +++++++++---- sysdeps/unix/sysv/linux/x86_64/x32/Makefile | 2 +- time/bits/types/struct_timespec.h | 24 ++++++---------- 20 files changed, 116 insertions(+), 77 deletions(-) diff --git a/conform/data/signal.h-data b/conform/data/signal.h-data index 674e5793db..d987affa28 100644 --- a/conform/data/signal.h-data +++ b/conform/data/signal.h-data @@ -32,8 +32,7 @@ xfail[powerpc32-linux]-element ucontext_t mcontext_t uc_mcontext type {struct timespec} element {struct timespec} __time_t tv_sec -// Bug 16437: tv_nsec has wrong type. -xfail[x86_64-x32-linux]-element {struct timespec} long tv_nsec +element {struct timespec} long tv_nsec #endif #if defined POSIX || defined UNIX98 || defined XOPEN2K || defined XOPEN2K8 || defined POSIX2008 diff --git a/conform/data/sys/select.h-data b/conform/data/sys/select.h-data index 44d63ebd2d..16e66b1527 100644 --- a/conform/data/sys/select.h-data +++ b/conform/data/sys/select.h-data @@ -10,8 +10,7 @@ type sigset_t type {struct timespec} element {struct timespec} time_t tv_sec -// Bug 16437: tv_nsec has wrong type. -xfail[x86_64-x32-linux]-element {struct timespec} long tv_nsec +element {struct timespec} long tv_nsec type fd_set #if defined XPG4 || defined XPG42 || defined UNIX98 diff --git a/conform/data/sys/stat.h-data b/conform/data/sys/stat.h-data index 03be4814ec..4eb1434ab1 100644 --- a/conform/data/sys/stat.h-data +++ b/conform/data/sys/stat.h-data @@ -63,8 +63,7 @@ element {struct stat} blkcnt_t st_blocks # if defined XOPEN2K8 || defined POSIX2008 type {struct timespec} element {struct timespec} time_t tv_sec -// Bug 16437: tv_nsec has wrong type. -xfail[x86_64-x32-linux]-element {struct timespec} long tv_nsec +element {struct timespec} long tv_nsec # endif #if !defined POSIX && !defined POSIX2008 diff --git a/conform/data/time.h-data b/conform/data/time.h-data index 9c1c19596e..d4cb6514f5 100644 --- a/conform/data/time.h-data +++ b/conform/data/time.h-data @@ -9,8 +9,7 @@ macro-int-constant TIME_UTC > 0 type {struct timespec} element {struct timespec} time_t tv_sec -// Bug 16437: tv_nsec has wrong type. -xfail[x86_64-x32-linux]-element {struct timespec} long tv_nsec +element {struct timespec} long tv_nsec #endif type size_t diff --git a/nptl/futex-internal.c b/nptl/futex-internal.c index 58605b2fca..050f38884b 100644 --- a/nptl/futex-internal.c +++ b/nptl/futex-internal.c @@ -53,13 +53,19 @@ __futex_abstimed_wait_common64 (unsigned int* futex_word, const struct __timespec64* abstime, int private, bool cancel) { + long long int ts[2]; + if (abstime != NULL) + { + ts[0] = abstime->tv_sec; + ts[1] = abstime->tv_nsec; + } if (cancel) return INTERNAL_SYSCALL_CANCEL (futex_time64, futex_word, op, expected, - abstime, NULL /* Unused. */, + abstime != NULL ? ts : NULL, NULL, FUTEX_BITSET_MATCH_ANY); else return INTERNAL_SYSCALL_CALL (futex_time64, futex_word, op, expected, - abstime, NULL /* Ununsed. */, + abstime != NULL ? ts : NULL, NULL, FUTEX_BITSET_MATCH_ANY); } diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c index 74e2407575..09ae954360 100644 --- a/sysdeps/unix/sysv/linux/clock_nanosleep.c +++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c @@ -45,7 +45,8 @@ __clock_nanosleep_time64 (clockid_t clock_id, int flags, int r; #ifdef __ASSUME_TIME64_SYSCALLS - r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, flags, req, + long long int ts[2] = { req->tv_sec, req->tv_nsec }; + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, flags, &ts, rem); #else if (!in_time_t_range (req->tv_sec)) diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c index 598d72b8b1..c57ae06311 100644 --- a/sysdeps/unix/sysv/linux/clock_settime.c +++ b/sysdeps/unix/sysv/linux/clock_settime.c @@ -35,7 +35,8 @@ __clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp) #ifndef __NR_clock_settime64 # define __NR_clock_settime64 __NR_clock_settime #endif - int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp); + long long int ts[2] = { tp->tv_sec, tp->tv_nsec }; + int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, ts); #ifndef __ASSUME_TIME64_SYSCALLS if (ret == 0 || errno != ENOSYS) diff --git a/sysdeps/unix/sysv/linux/mq_timedreceive.c b/sysdeps/unix/sysv/linux/mq_timedreceive.c index 7f3a112d7f..be7dc56c8b 100644 --- a/sysdeps/unix/sysv/linux/mq_timedreceive.c +++ b/sysdeps/unix/sysv/linux/mq_timedreceive.c @@ -32,8 +32,14 @@ ___mq_timedreceive_time64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len #endif #ifdef __ASSUME_TIME64_SYSCALLS + long long int ts[2]; + if (abs_timeout != NULL) + { + ts[0] = abs_timeout->tv_sec; + ts[1] = abs_timeout->tv_nsec; + } return SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, msg_len, - msg_prio, abs_timeout); + msg_prio, abs_timeout != NULL ? ts : NULL); #else bool need_time64 = abs_timeout != NULL && !in_time_t_range (abs_timeout->tv_sec); diff --git a/sysdeps/unix/sysv/linux/mq_timedsend.c b/sysdeps/unix/sysv/linux/mq_timedsend.c index f93f865721..dcbb1a00d5 100644 --- a/sysdeps/unix/sysv/linux/mq_timedsend.c +++ b/sysdeps/unix/sysv/linux/mq_timedsend.c @@ -32,8 +32,14 @@ ___mq_timedsend_time64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len, # endif #ifdef __ASSUME_TIME64_SYSCALLS + long long int ts[2]; + if (abs_timeout != NULL) + { + ts[0] = abs_timeout->tv_sec; + ts[1] = abs_timeout->tv_nsec; + } return SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, msg_len, - msg_prio, abs_timeout); + msg_prio, abs_timeout != NULL ? ts : NULL); #else bool need_time64 = abs_timeout != NULL && !in_time_t_range (abs_timeout->tv_sec); diff --git a/sysdeps/unix/sysv/linux/ppoll.c b/sysdeps/unix/sysv/linux/ppoll.c index 465dea623d..d01379ba2d 100644 --- a/sysdeps/unix/sysv/linux/ppoll.c +++ b/sysdeps/unix/sysv/linux/ppoll.c @@ -27,11 +27,11 @@ __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout, { /* The Linux kernel can in some situations update the timeout value. We do not want that so use a local variable. */ - struct __timespec64 tval; + long long int ts[2]; if (timeout != NULL) { - tval = *timeout; - timeout = &tval; + ts[0] = timeout->tv_sec; + ts[1] = timeout->tv_nsec; } #ifndef __NR_ppoll_time64 @@ -39,15 +39,14 @@ __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout, #endif #ifdef __ASSUME_TIME64_SYSCALLS - return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask, - __NSIG_BYTES); + return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout != NULL ? ts : NULL, + sigmask, __NSIG_BYTES); #else int ret; bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec); if (need_time64) { - ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask, - __NSIG_BYTES); + ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, ts, sigmask, __NSIG_BYTES); if (ret == 0 || errno != ENOSYS) return ret; __set_errno (EOVERFLOW); diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c index f58c01f25a..8cf22c8aa4 100644 --- a/sysdeps/unix/sysv/linux/pselect.c +++ b/sysdeps/unix/sysv/linux/pselect.c @@ -31,23 +31,22 @@ pselect64_syscall (int nfds, fd_set *readfds, fd_set *writefds, { (uintptr_t) sigmask, __NSIG_BYTES }; + /* The Linux kernel can in some situations update the timeout value. + We do not want that so use a local variable. */ + long long int ts[2]; + if (timeout != NULL) + { + ts[0] = timeout->tv_sec; + ts[1] = timeout->tv_nsec; + } return SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds, exceptfds, - timeout, data); + timeout != NULL ? ts : NULL, data); } int __pselect64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct __timespec64 *timeout, const sigset_t *sigmask) { - /* The Linux kernel can in some situations update the timeout value. - We do not want that so use a local variable. */ - struct __timespec64 tval; - if (timeout != NULL) - { - tval = *timeout; - timeout = &tval; - } - /* Note: the system call expects 7 values but on most architectures we can only pass in 6 directly. If there is an architecture with support for more parameters a new version of this file needs to diff --git a/sysdeps/unix/sysv/linux/recvmmsg.c b/sysdeps/unix/sysv/linux/recvmmsg.c index c214321e94..8d6cd238eb 100644 --- a/sysdeps/unix/sysv/linux/recvmmsg.c +++ b/sysdeps/unix/sysv/linux/recvmmsg.c @@ -26,8 +26,14 @@ __recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, #ifndef __NR_recvmmsg_time64 # define __NR_recvmmsg_time64 __NR_recvmmsg #endif + long long int ts[2]; + if (timeout != NULL) + { + ts[0] = timeout->tv_sec; + ts[1] = timeout->tv_nsec; + } int r = SYSCALL_CANCEL (recvmmsg_time64, fd, vmessages, vlen, flags, - timeout); + timeout != NULL ? ts : NULL); #ifndef __ASSUME_TIME64_SYSCALLS if (r >= 0 || errno != ENOSYS) return r; diff --git a/sysdeps/unix/sysv/linux/select.c b/sysdeps/unix/sysv/linux/select.c index da25b4b4cf..dd47238572 100644 --- a/sysdeps/unix/sysv/linux/select.c +++ b/sysdeps/unix/sysv/linux/select.c @@ -53,13 +53,7 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, ns = us * NSEC_PER_USEC; } - struct __timespec64 ts64, *pts64 = NULL; - if (timeout != NULL) - { - ts64.tv_sec = s; - ts64.tv_nsec = ns; - pts64 = &ts64; - } + long long int ts[2] = { s, ns }; #ifndef __NR_pselect6_time64 # define __NR_pselect6_time64 __NR_pselect6 @@ -67,19 +61,23 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, #ifdef __ASSUME_TIME64_SYSCALLS int r = SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds, exceptfds, - pts64, NULL); + timeout != NULL ? ts : NULL, NULL); if (timeout != NULL) - TIMESPEC_TO_TIMEVAL (timeout, pts64); + { + timeout->tv_sec = ts[0]; + timeout->tv_usec = ts[1] / 1000; + } return r; #else bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec); if (need_time64) { int r = SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds, - exceptfds, pts64, NULL); + exceptfds, ts, NULL); if ((r >= 0 || errno != ENOSYS) && timeout != NULL) { - TIMESPEC_TO_TIMEVAL (timeout, &ts64); + timeout->tv_sec = ts[0]; + timeout->tv_usec = ts[1] / 1000; } else __set_errno (EOVERFLOW); @@ -88,10 +86,10 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, # ifdef __ASSUME_PSELECT struct timespec ts32, *pts32 = NULL; - if (pts64 != NULL) + if (timeout != NULL) { - ts32.tv_sec = pts64->tv_sec; - ts32.tv_nsec = pts64->tv_nsec; + ts32.tv_sec = ts[0]; + ts32.tv_nsec = ts[1]; pts32 = &ts32; } @@ -102,9 +100,10 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, return r; # else struct timeval tv32, *ptv32 = NULL; - if (pts64 != NULL) + if (timeout != NULL) { - tv32 = valid_timespec64_to_timeval (*pts64); + tv32.tv_sec = ts[0]; + tv32.tv_usec = ts[1]; ptv32 = &tv32; } diff --git a/sysdeps/unix/sysv/linux/semtimedop.c b/sysdeps/unix/sysv/linux/semtimedop.c index 43577535ef..5816577a9f 100644 --- a/sysdeps/unix/sysv/linux/semtimedop.c +++ b/sysdeps/unix/sysv/linux/semtimedop.c @@ -22,7 +22,7 @@ static int semtimedop_syscall (int semid, struct sembuf *sops, size_t nsops, - const struct __timespec64 *timeout) + const void *timeout) { #ifdef __NR_semtimedop_time64 return INLINE_SYSCALL_CALL (semtimedop_time64, semid, sops, nsops, timeout); @@ -40,7 +40,13 @@ __semtimedop64 (int semid, struct sembuf *sops, size_t nsops, const struct __timespec64 *timeout) { #ifdef __ASSUME_TIME64_SYSCALLS - return semtimedop_syscall (semid, sops, nsops, timeout); + long long int ts[2]; + if (timeout != NULL) + { + ts[0] = timeout->tv_sec; + ts[1] = timeout->tv_nsec; + } + return semtimedop_syscall (semid, sops, nsops, timeout != NULL ? ts : NULL); #else bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec); if (need_time64) diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c index 607381a0a7..f08cc688db 100644 --- a/sysdeps/unix/sysv/linux/sigtimedwait.c +++ b/sysdeps/unix/sysv/linux/sigtimedwait.c @@ -28,8 +28,14 @@ __sigtimedwait64 (const sigset_t *set, siginfo_t *info, int result; #ifdef __ASSUME_TIME64_SYSCALLS - result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, timeout, - __NSIG_BYTES); + long long int ts[2]; + if (timeout != NULL) + { + ts[0] = timeout->tv_sec; + ts[1] = timeout->tv_nsec; + } + result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, + timeout != NULL ? ts : NULL, __NSIG_BYTES); #else bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec); if (need_time64) diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c index 24706e45d8..86199ebac5 100644 --- a/sysdeps/unix/sysv/linux/timer_settime.c +++ b/sysdeps/unix/sysv/linux/timer_settime.c @@ -35,8 +35,11 @@ ___timer_settime64 (timer_t timerid, int flags, # ifndef __NR_timer_settime64 # define __NR_timer_settime64 __NR_timer_settime # endif - return INLINE_SYSCALL_CALL (timer_settime64, ktimerid, flags, value, - ovalue); + long long int ts[4] = { value->it_interval.tv_sec, + value->it_interval.tv_nsec, + value->it_value.tv_sec, + value->it_value.tv_nsec }; + return INLINE_SYSCALL_CALL (timer_settime64, ktimerid, flags, ts, ovalue); # else # ifdef __NR_timer_settime64 int ret = INLINE_SYSCALL_CALL (timer_settime64, ktimerid, flags, value, diff --git a/sysdeps/unix/sysv/linux/timerfd_settime.c b/sysdeps/unix/sysv/linux/timerfd_settime.c index 0069e1374a..709d54d37c 100644 --- a/sysdeps/unix/sysv/linux/timerfd_settime.c +++ b/sysdeps/unix/sysv/linux/timerfd_settime.c @@ -31,7 +31,11 @@ __timerfd_settime64 (int fd, int flags, const struct __itimerspec64 *value, #endif #ifdef __ASSUME_TIME64_SYSCALLS - return INLINE_SYSCALL_CALL (timerfd_settime64, fd, flags, value, ovalue); + long long int ts[4] = { value->it_interval.tv_sec, + value->it_interval.tv_nsec, + value->it_value.tv_sec, + value->it_value.tv_nsec }; + return INLINE_SYSCALL_CALL (timerfd_settime64, fd, flags, ts, ovalue); #else bool need_time64 = !in_time_t_range (value->it_value.tv_sec) || !in_time_t_range (value->it_interval.tv_sec); diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c index e9061d2323..d64fb46899 100644 --- a/sysdeps/unix/sysv/linux/utimensat.c +++ b/sysdeps/unix/sysv/linux/utimensat.c @@ -22,6 +22,10 @@ #include #include +/* For UTIME_NOW and UTIME_OMIT the value of tv_sec field is ignored. */ +# define TS_SPECIAL(ts) \ + ((ts).tv_nsec == UTIME_NOW || (ts).tv_nsec == UTIME_OMIT) + /* Helper function defined for easy reusage of the code which calls utimensat and utimensat_time64 syscall. */ int @@ -33,12 +37,17 @@ __utimensat64_helper (int fd, const char *file, #endif #ifdef __ASSUME_TIME64_SYSCALLS - return INLINE_SYSCALL_CALL (utimensat_time64, fd, file, &tsp64[0], flags); + long long int ts[4]; + if (tsp64 != NULL) + { + ts[0] = !TS_SPECIAL(tsp64[0]) ? tsp64[0].tv_sec : 0; + ts[1] = tsp64[0].tv_nsec; + ts[2] = !TS_SPECIAL(tsp64[1]) ? tsp64[1].tv_sec : 0; + ts[3] = tsp64[1].tv_nsec; + } + return INLINE_SYSCALL_CALL (utimensat_time64, fd, file, + tsp64 != NULL ? ts : NULL, flags); #else - /* For UTIME_NOW and UTIME_OMIT the value of tv_sec field is ignored. */ -# define TS_SPECIAL(ts) \ - ((ts).tv_nsec == UTIME_NOW || (ts).tv_nsec == UTIME_OMIT) - bool need_time64 = tsp64 != NULL && ((!TS_SPECIAL (tsp64[0]) && !in_time_t_range (tsp64[0].tv_sec)) diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/Makefile b/sysdeps/unix/sysv/linux/x86_64/x32/Makefile index 16b768d8ba..74b3d30e2f 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/Makefile +++ b/sysdeps/unix/sysv/linux/x86_64/x32/Makefile @@ -6,6 +6,6 @@ sysdep_routines += arch_prctl endif ifeq ($(subdir),conform) -# For bugs 16437 and 21279. +# For bug 21279. conformtest-xfail-conds += x86_64-x32-linux endif diff --git a/time/bits/types/struct_timespec.h b/time/bits/types/struct_timespec.h index 489e81136d..923f8579e5 100644 --- a/time/bits/types/struct_timespec.h +++ b/time/bits/types/struct_timespec.h @@ -10,23 +10,15 @@ has nanoseconds instead of microseconds. */ struct timespec { -#ifdef __USE_TIME_BITS64 - __time64_t tv_sec; /* Seconds. */ -#else - __time_t tv_sec; /* Seconds. */ + time_t tv_sec; /* Seconds. */ +#if __WORDSIZE == 32 && (__TIMESIZE == 64 || defined __USE_TIME_BITS64) \ + && __BYTE_ORDER == __BIG_ENDIAN + int: 32; /* Padding. */ #endif -#if __WORDSIZE == 64 \ - || (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64) \ - || (__TIMESIZE == 32 && !defined __USE_TIME_BITS64) - __syscall_slong_t tv_nsec; /* Nanoseconds. */ -#else -# if __BYTE_ORDER == __BIG_ENDIAN - int: 32; /* Padding. */ - long int tv_nsec; /* Nanoseconds. */ -# else - long int tv_nsec; /* Nanoseconds. */ - int: 32; /* Padding. */ -# endif + long int tv_nsec; /* Nanoseconds. */ +#if __WORDSIZE == 32 && (__TIMESIZE == 64 || defined __USE_TIME_BITS64) \ + && __BYTE_ORDER == __LITTLE_ENDIAN + int: 32; /* Padding. */ #endif };