[PATCH 04/10] y2038: linux: Provide __clock_adjtime64 implementation

Alistair Francis alistair23@gmail.com
Mon Apr 27 22:12:05 GMT 2020


On Sun, Apr 26, 2020 at 6:31 AM Lukasz Majewski <lukma@denx.de> wrote:
>
> This patch replaces auto generated wrapper (as described in
> sysdeps/unix/sysv/linux/syscalls.list) for clock_adjtime with one which adds
> extra support for reading 64 bit time values on machines with __TIMESIZE != 64.
>
> To achieve this goal new __clock_adjtime64 explicit 64 bit function for
> adjusting Linux clock has been added.
> Moreover, a 32 bit version - __clock_adjtime has been refactored to internally
> use __clock_adjtime64.
>
> The __clock_adjtime is now supposed to be used on systems still supporting 32
> bit time (__TIMESIZE != 64) - hence the necessary conversions between 64 bit
> struct __timespec64 and struct timespec.
>
> The new __clock_adjtime64 syscall available from Linux 5.1+ has been used, when
> applicable.
> Up till v5.4 in the Linux kernel there was a bug preventing this call from
> obtaining correct struct's timex time.tv_sec time after time_t overflow
> (i.e. not being Y2038 safe).
>
> Build tests:
> - ./src/scripts/build-many-glibcs.py glibcs
>
> Run-time tests:
> - Run specific tests on ARM/x86 32bit systems (qemu):
>   https://github.com/lmajewski/meta-y2038 and run tests:
>   https://github.com/lmajewski/y2038-tests/commits/master
>
> Linux kernel, headers and minimal kernel version for glibc build test matrix:
> - Linux v5.1 (with clock_adjtime64) and glibc build with v5.1 as
>   minimal kernel version (--enable-kernel="5.1.0")
>   The __ASSUME_TIME64_SYSCALLS flag defined.
>
> - Linux v5.1 and default minimal kernel version
>   The __ASSUME_TIME64_SYSCALLS not defined, but kernel supports clock_adjtime64
>   syscall.
>
> - Linux v4.19 (no clock_adjtime64 support) with default minimal kernel version
>   for contemporary glibc (3.2.0)
>   This kernel doesn't support clock_adjtime64 syscall, so the fallback to
>   clock_adjtime is tested.
>
> Above tests were performed with Y2038 redirection applied as well as without
> (so the __TIMESIZE != 64 execution path is checked as well).
>
> No regressions were observed.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  sysdeps/unix/sysv/linux/Makefile            |  2 +-
>  sysdeps/unix/sysv/linux/clock_adjtime.c     | 64 +++++++++++++++++++++
>  sysdeps/unix/sysv/linux/include/sys/timex.h |  3 +
>  sysdeps/unix/sysv/linux/syscalls.list       |  1 -
>  4 files changed, 68 insertions(+), 2 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/clock_adjtime.c
>
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 089a4899d5..dfb200eccf 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -59,7 +59,7 @@ sysdep_routines += adjtimex clone umount umount2 readahead sysctl \
>                    eventfd eventfd_read eventfd_write prlimit \
>                    personality epoll_wait tee vmsplice splice \
>                    open_by_handle_at mlock2 pkey_mprotect pkey_set pkey_get \
> -                  timerfd_gettime timerfd_settime
> +                  timerfd_gettime timerfd_settime clock_adjtime
>
>  CFLAGS-gethostid.c = -fexceptions
>  CFLAGS-tee.c = -fexceptions -fasynchronous-unwind-tables
> diff --git a/sysdeps/unix/sysv/linux/clock_adjtime.c b/sysdeps/unix/sysv/linux/clock_adjtime.c
> new file mode 100644
> index 0000000000..cbab6bf345
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/clock_adjtime.c
> @@ -0,0 +1,64 @@
> +/* clock_adjtime -- tune kernel clock
> +   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; see the file COPYING.LIB.  If
> +   not, see <https://www.gnu.org/licenses/>.  */
> +
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <time.h>
> +#include <sysdep.h>
> +#include <sys/timex.h>
> +#include <kernel-features.h>
> +
> +int
> +__clock_adjtime64 (const clockid_t clock_id, struct __timex64 *tx64)
> +{
> +#ifdef __ASSUME_TIME64_SYSCALLS
> +# ifndef __NR_clock_adjtime64
> +#  define __NR_clock_adjtime64 __NR_clock_adjtime
> +# endif
> +       return INLINE_SYSCALL_CALL (clock_adjtime64, clock_id, tx64);
> +#else
> +  int ret = INLINE_SYSCALL_CALL (clock_adjtime64, clock_id, tx64);
> +  if ((ret >= TIME_OK && ret <= TIME_ERROR) || errno != ENOSYS)
> +    return ret;
> +
> +  struct timex tx32 = valid_timex64_to_timex (*tx64);
> +  int retval = INLINE_SYSCALL_CALL (clock_adjtime, clock_id, &tx32);
> +  *tx64 = valid_timex_to_timex64 (tx32);
> +
> +  return retval;
> +#endif
> +}
> +
> +#if __TIMESIZE != 64
> +libc_hidden_def (__clock_adjtime64)
> +
> +int
> +__clock_adjtime (const clockid_t clock_id, struct timex *tx)
> +{
> +       struct __timex64 tx64;
> +  int retval;
> +
> +  tx64 = valid_timex_to_timex64 (*tx);
> +  retval = __clock_adjtime64 (clock_id, &tx64);
> +  *tx = valid_timex64_to_timex (tx64);
> +
> +  return retval;
> +}
> +#endif
> +libc_hidden_def (__clock_adjtime);
> +strong_alias (__clock_adjtime, clock_adjtime)
> diff --git a/sysdeps/unix/sysv/linux/include/sys/timex.h b/sysdeps/unix/sysv/linux/include/sys/timex.h
> index bab6b28920..f1bb364db4 100644
> --- a/sysdeps/unix/sysv/linux/include/sys/timex.h
> +++ b/sysdeps/unix/sysv/linux/include/sys/timex.h
> @@ -30,6 +30,7 @@ libc_hidden_proto (__adjtimex)
>  /* Local definition of 64 bit time supporting timex struct */
>  #  if __TIMESIZE == 64
>  #   define __timex64 timex
> +#   define __clock_adjtime64 __clock_adjtime
>  #  else
>
>  struct __timex64
> @@ -63,6 +64,8 @@ struct __timex64
>    int  :32; int  :32; int  :32; int  :32;
>    int  :32; int  :32; int  :32;
>  };
> +extern int __clock_adjtime64 (const clockid_t clock_id, struct __timex64 *tx64);
> +libc_hidden_proto (__clock_adjtime64);
>  #  endif
>
>  /* Convert a known valid struct timex into a struct __timex64.  */
> diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
> index e40f993495..d7d73e8fcb 100644
> --- a/sysdeps/unix/sysv/linux/syscalls.list
> +++ b/sysdeps/unix/sysv/linux/syscalls.list
> @@ -4,7 +4,6 @@ alarm           -       alarm           i:i     alarm
>  bdflush                EXTRA   bdflush         i:ii    __compat_bdflush        bdflush@GLIBC_2.0:GLIBC_2.23
>  capget         EXTRA   capget          i:pp    capget
>  capset         EXTRA   capset          i:pp    capset
> -clock_adjtime  EXTRA   clock_adjtime   i:ip    __clock_adjtime         clock_adjtime
>  create_module  EXTRA   create_module   3       __compat_create_module  create_module@GLIBC_2.0:GLIBC_2.23
>  delete_module  EXTRA   delete_module   3       delete_module
>  epoll_create   EXTRA   epoll_create    i:i     epoll_create
> --
> 2.20.1
>


More information about the Libc-alpha mailing list