[4/5] y2038: linux: Provide __timer_gettime64 implementation

Message ID 20191111214758.3677-5-lukma@denx.de
State Superseded
Headers

Commit Message

Lukasz Majewski Nov. 11, 2019, 9:47 p.m. UTC
  This patch provides new __timer_gettime64 explicit 64 bit function for reading
status of specified timer. To be more precise - the remaining time and interval
set with timer_settime.
Moreover, a 32 bit version - __timer_gettime has been refactored to internally
use __timer_gettime64.

The __timer_gettime is now supposed to be used on systems still supporting 32
bit time (__TIMESIZE != 64) - hence the necessary conversion from 64 bit struct
__timespec64 to struct timespec.

The new __timer_gettime64 syscall available from Linux 5.1+ has been used, when
applicable.

Build tests:
- The code has been tested on x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make check PARALLELMFLAGS="-j8" && \\
make xcheck PARALLELMFLAGS="-j8"

- The glibc has been build tested (make PARALLELMFLAGS="-j8") for
x86 (i386), x86_64-x32, and armv7

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

- Use of cross-test-ssh.sh for ARM (armv7):
  make PARALLELMFLAGS="-j8" test-wrapper='./cross-test-ssh.sh root@192.168.7.2' xcheck

Linux kernel, headers and minimal kernel version for glibc build test
matrix:
- Linux v5.1 (with timer_gettime64) 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 timer_gettime64
  syscall.

- Linux v4.19 (no timer_gettime64 support) with default minimal kernel version
  for contemporary glibc (3.2.0)
  This kernel doesn't support timer_gettime64 syscall, so the fallback to
  timer_gettime 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.
---
 include/time.h                          |  7 ++++
 sysdeps/unix/sysv/linux/timer_gettime.c | 44 ++++++++++++++++++++++---
 2 files changed, 47 insertions(+), 4 deletions(-)
  

Comments

Lukasz Majewski Nov. 27, 2019, 5 p.m. UTC | #1
Dear All,

> This patch provides new __timer_gettime64 explicit 64 bit function
> for reading status of specified timer. To be more precise - the
> remaining time and interval set with timer_settime.
> Moreover, a 32 bit version - __timer_gettime has been refactored to
> internally use __timer_gettime64.
> 
> The __timer_gettime is now supposed to be used on systems still
> supporting 32 bit time (__TIMESIZE != 64) - hence the necessary
> conversion from 64 bit struct __timespec64 to struct timespec.
> 
> The new __timer_gettime64 syscall available from Linux 5.1+ has been
> used, when applicable.
> 
> Build tests:
> - The code has been tested on x86_64/x86 (native compilation):
> make PARALLELMFLAGS="-j8" && make check PARALLELMFLAGS="-j8" && \\
> make xcheck PARALLELMFLAGS="-j8"
> 
> - The glibc has been build tested (make PARALLELMFLAGS="-j8") for
> x86 (i386), x86_64-x32, and armv7
> 
> 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
> 
> - Use of cross-test-ssh.sh for ARM (armv7):
>   make PARALLELMFLAGS="-j8" test-wrapper='./cross-test-ssh.sh
> root@192.168.7.2' xcheck
> 
> Linux kernel, headers and minimal kernel version for glibc build test
> matrix:
> - Linux v5.1 (with timer_gettime64) 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
> timer_gettime64 syscall.
> 
> - Linux v4.19 (no timer_gettime64 support) with default minimal
> kernel version for contemporary glibc (3.2.0)
>   This kernel doesn't support timer_gettime64 syscall, so the
> fallback to timer_gettime 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.
> ---
>  include/time.h                          |  7 ++++
>  sysdeps/unix/sysv/linux/timer_gettime.c | 44
> ++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 4
> deletions(-)
> 
> diff --git a/include/time.h b/include/time.h
> index 52ee213669..8b9a4b7a60 100644
> --- a/include/time.h
> +++ b/include/time.h
> @@ -179,6 +179,13 @@ extern int __futimens64 (int fd, const struct
> __timespec64 tsp[2]); libc_hidden_proto (__futimens64);
>  #endif
>  
> +#if __TIMESIZE == 64
> +# define __timer_gettime64 __timer_gettime
> +#else
> +extern int __timer_gettime64 (timer_t timerid, struct __itimerspec64
> *value); +libc_hidden_proto (__timer_gettime64);
> +#endif
> +
>  /* Compute the `struct tm' representation of T,
>     offset OFFSET seconds east of UTC,
>     and store year, yday, mon, mday, wday, hour, min, sec into *TP.
> diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c
> b/sysdeps/unix/sysv/linux/timer_gettime.c index
> 8d9bef9196..31bf5ce25b 100644 ---
> a/sysdeps/unix/sysv/linux/timer_gettime.c +++
> b/sysdeps/unix/sysv/linux/timer_gettime.c @@ -20,15 +20,51 @@
>  #include <stdlib.h>
>  #include <time.h>
>  #include <sysdep.h>
> +#include <kernel-features.h>
>  #include "kernel-posix-timers.h"
>  
>  int
> -timer_gettime (timer_t timerid, struct itimerspec *value)
> +__timer_gettime64 (timer_t timerid, struct __itimerspec64 *value)
>  {
>    struct timer *kt = (struct timer *) timerid;
>  
> -  /* Delete the kernel timer object.  */
> -  int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value);
> +#ifdef __ASSUME_TIME64_SYSCALLS
> +# ifndef __NR_timer_gettime64
> +#  define __NR_timer_gettime64 __NR_timer_gettime
> +# endif
> +  return INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);
> +#else
> +# ifdef __NR_timer_gettime64
> +  int ret = INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);
> +  if (ret == 0 || errno != ENOSYS)
> +    return ret;
> +# endif
> +  struct itimerspec its32;
> +  int retval = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid,
> &its32);
> +  if (! retval)
> +    {
> +      value->it_interval = valid_timespec_to_timespec64
> (its32.it_interval);
> +      value->it_value = valid_timespec_to_timespec64
> (its32.it_value);
> +    }
>  
> -  return res;
> +  return retval;
> +#endif
>  }
> +
> +#if __TIMESIZE != 64
> +int
> +__timer_gettime (timer_t timerid, struct itimerspec *value)
> +{
> +  struct __itimerspec64 its64;
> +  int retval = __timer_gettime64 (timerid, &its64);
> +  if (! retval)
> +    {
> +      value->it_interval = valid_timespec64_to_timespec
> (its64.it_interval);
> +      value->it_value = valid_timespec64_to_timespec
> (its64.it_value);
> +    }
> +
> +  return retval;
> +}
> +#endif
> +weak_alias (__timer_gettime, timer_gettime)
> +libc_hidden_def (timer_gettime)

Gentle ping,


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
  
Adhemerval Zanella Netto Dec. 4, 2019, 7:41 p.m. UTC | #2
On 11/11/2019 18:47, Lukasz Majewski wrote:
> This patch provides new __timer_gettime64 explicit 64 bit function for reading
> status of specified timer. To be more precise - the remaining time and interval
> set with timer_settime.
> Moreover, a 32 bit version - __timer_gettime has been refactored to internally
> use __timer_gettime64.
> 
> The __timer_gettime is now supposed to be used on systems still supporting 32
> bit time (__TIMESIZE != 64) - hence the necessary conversion from 64 bit struct
> __timespec64 to struct timespec.
> 
> The new __timer_gettime64 syscall available from Linux 5.1+ has been used, when
> applicable.
> 
> Build tests:
> - The code has been tested on x86_64/x86 (native compilation):
> make PARALLELMFLAGS="-j8" && make check PARALLELMFLAGS="-j8" && \\
> make xcheck PARALLELMFLAGS="-j8"
> 
> - The glibc has been build tested (make PARALLELMFLAGS="-j8") for
> x86 (i386), x86_64-x32, and armv7
> 
> 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

Does it have any additional coverage not present in glibc tests? If yes, would
be possible to enhance glibc tests?

> 
> - Use of cross-test-ssh.sh for ARM (armv7):
>   make PARALLELMFLAGS="-j8" test-wrapper='./cross-test-ssh.sh root@192.168.7.2' xcheck
> 
> Linux kernel, headers and minimal kernel version for glibc build test
> matrix:
> - Linux v5.1 (with timer_gettime64) 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 timer_gettime64
>   syscall.
> 
> - Linux v4.19 (no timer_gettime64 support) with default minimal kernel version
>   for contemporary glibc (3.2.0)
>   This kernel doesn't support timer_gettime64 syscall, so the fallback to
>   timer_gettime 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.

LGTM with some changes below.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

> ---
>  include/time.h                          |  7 ++++
>  sysdeps/unix/sysv/linux/timer_gettime.c | 44 ++++++++++++++++++++++---
>  2 files changed, 47 insertions(+), 4 deletions(-)
> 
> diff --git a/include/time.h b/include/time.h
> index 52ee213669..8b9a4b7a60 100644
> --- a/include/time.h
> +++ b/include/time.h
> @@ -179,6 +179,13 @@ extern int __futimens64 (int fd, const struct __timespec64 tsp[2]);
>  libc_hidden_proto (__futimens64);
>  #endif
>  
> +#if __TIMESIZE == 64
> +# define __timer_gettime64 __timer_gettime
> +#else
> +extern int __timer_gettime64 (timer_t timerid, struct __itimerspec64 *value);
> +libc_hidden_proto (__timer_gettime64);
> +#endif
> +
>  /* Compute the `struct tm' representation of T,
>     offset OFFSET seconds east of UTC,
>     and store year, yday, mon, mday, wday, hour, min, sec into *TP.

Ok, it follows current practice.

> diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c b/sysdeps/unix/sysv/linux/timer_gettime.c
> index 8d9bef9196..31bf5ce25b 100644
> --- a/sysdeps/unix/sysv/linux/timer_gettime.c
> +++ b/sysdeps/unix/sysv/linux/timer_gettime.c
> @@ -20,15 +20,51 @@
>  #include <stdlib.h>
>  #include <time.h>
>  #include <sysdep.h>
> +#include <kernel-features.h>
>  #include "kernel-posix-timers.h"
>  
>  int
> -timer_gettime (timer_t timerid, struct itimerspec *value)
> +__timer_gettime64 (timer_t timerid, struct __itimerspec64 *value)
>  {
>    struct timer *kt = (struct timer *) timerid;
>  
> -  /* Delete the kernel timer object.  */
> -  int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value);
> +#ifdef __ASSUME_TIME64_SYSCALLS
> +# ifndef __NR_timer_gettime64
> +#  define __NR_timer_gettime64 __NR_timer_gettime
> +# endif
> +  return INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);

Use INLINE_SYSCALL_CALL.

> +#else
> +# ifdef __NR_timer_gettime64
> +  int ret = INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);

Ditto.

> +  if (ret == 0 || errno != ENOSYS)
> +    return ret;
> +# endif
> +  struct itimerspec its32;
> +  int retval = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, &its32);

Ditto.

> +  if (! retval)

Please use an explicit comparison with == 0.

> +    {
> +      value->it_interval = valid_timespec_to_timespec64 (its32.it_interval);
> +      value->it_value = valid_timespec_to_timespec64 (its32.it_value);
> +    }
>  
> -  return res;
> +  return retval;
> +#endif
>  }
> +

Ok.

> +#if __TIMESIZE != 64
> +int
> +__timer_gettime (timer_t timerid, struct itimerspec *value)
> +{
> +  struct __itimerspec64 its64;
> +  int retval = __timer_gettime64 (timerid, &its64);
> +  if (! retval)

Please use an explicit comparison with == 0.

> +    {
> +      value->it_interval = valid_timespec64_to_timespec (its64.it_interval);
> +      value->it_value = valid_timespec64_to_timespec (its64.it_value);
> +    }
> +
> +  return retval;
> +}
> +#endif
> +weak_alias (__timer_gettime, timer_gettime)
> +libc_hidden_def (timer_gettime)
> 

Ok.
  
Lukasz Majewski Dec. 5, 2019, 9:42 a.m. UTC | #3
Hi Adhemerval,

Thank you for your review. I'm making those pointed out minor
adjustments, re-test the code and pull to master.

> On 11/11/2019 18:47, Lukasz Majewski wrote:
> > This patch provides new __timer_gettime64 explicit 64 bit function
> > for reading status of specified timer. To be more precise - the
> > remaining time and interval set with timer_settime.
> > Moreover, a 32 bit version - __timer_gettime has been refactored to
> > internally use __timer_gettime64.
> > 
> > The __timer_gettime is now supposed to be used on systems still
> > supporting 32 bit time (__TIMESIZE != 64) - hence the necessary
> > conversion from 64 bit struct __timespec64 to struct timespec.
> > 
> > The new __timer_gettime64 syscall available from Linux 5.1+ has
> > been used, when applicable.
> > 
> > Build tests:
> > - The code has been tested on x86_64/x86 (native compilation):
> > make PARALLELMFLAGS="-j8" && make check PARALLELMFLAGS="-j8" && \\
> > make xcheck PARALLELMFLAGS="-j8"
> > 
> > - The glibc has been build tested (make PARALLELMFLAGS="-j8") for
> > x86 (i386), x86_64-x32, and armv7
> > 
> > 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  
> 
> Does it have any additional coverage not present in glibc tests? If
> yes, would be possible to enhance glibc tests?

Those tests are for 32 bit archs (ARM, x86, x86-x32, RISC-V) with set
-D_TIME_BITS=64 during the compilation (to check if the system is Y2038
safe).

As glibc is not yet supporting this flag, I don't add them to glibc's
tests.

I do plan to add them when we make "the big switch" and instantly add
-D_TIME_BITS64 support to glibc.

In the meanwhile I do rely on current glibc's setup to catch
regressions when I convert functions eligible for Y2038 enhancement
(which do support __ASSUME_TIME64_SYSCALLS flag).

> 
> > 
> > - Use of cross-test-ssh.sh for ARM (armv7):
> >   make PARALLELMFLAGS="-j8" test-wrapper='./cross-test-ssh.sh
> > root@192.168.7.2' xcheck
> > 
> > Linux kernel, headers and minimal kernel version for glibc build
> > test matrix:
> > - Linux v5.1 (with timer_gettime64) 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
> > timer_gettime64 syscall.
> > 
> > - Linux v4.19 (no timer_gettime64 support) with default minimal
> > kernel version for contemporary glibc (3.2.0)
> >   This kernel doesn't support timer_gettime64 syscall, so the
> > fallback to timer_gettime 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.  
> 
> LGTM with some changes below.
> 
> Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> 
> > ---
> >  include/time.h                          |  7 ++++
> >  sysdeps/unix/sysv/linux/timer_gettime.c | 44
> > ++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 4
> > deletions(-)
> > 
> > diff --git a/include/time.h b/include/time.h
> > index 52ee213669..8b9a4b7a60 100644
> > --- a/include/time.h
> > +++ b/include/time.h
> > @@ -179,6 +179,13 @@ extern int __futimens64 (int fd, const struct
> > __timespec64 tsp[2]); libc_hidden_proto (__futimens64);
> >  #endif
> >  
> > +#if __TIMESIZE == 64
> > +# define __timer_gettime64 __timer_gettime
> > +#else
> > +extern int __timer_gettime64 (timer_t timerid, struct
> > __itimerspec64 *value); +libc_hidden_proto (__timer_gettime64);
> > +#endif
> > +
> >  /* Compute the `struct tm' representation of T,
> >     offset OFFSET seconds east of UTC,
> >     and store year, yday, mon, mday, wday, hour, min, sec into *TP.
> >  
> 
> Ok, it follows current practice.
> 
> > diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c
> > b/sysdeps/unix/sysv/linux/timer_gettime.c index
> > 8d9bef9196..31bf5ce25b 100644 ---
> > a/sysdeps/unix/sysv/linux/timer_gettime.c +++
> > b/sysdeps/unix/sysv/linux/timer_gettime.c @@ -20,15 +20,51 @@
> >  #include <stdlib.h>
> >  #include <time.h>
> >  #include <sysdep.h>
> > +#include <kernel-features.h>
> >  #include "kernel-posix-timers.h"
> >  
> >  int
> > -timer_gettime (timer_t timerid, struct itimerspec *value)
> > +__timer_gettime64 (timer_t timerid, struct __itimerspec64 *value)
> >  {
> >    struct timer *kt = (struct timer *) timerid;
> >  
> > -  /* Delete the kernel timer object.  */
> > -  int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value);
> > +#ifdef __ASSUME_TIME64_SYSCALLS
> > +# ifndef __NR_timer_gettime64
> > +#  define __NR_timer_gettime64 __NR_timer_gettime
> > +# endif
> > +  return INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);
> >  
> 
> Use INLINE_SYSCALL_CALL.
> 
> > +#else
> > +# ifdef __NR_timer_gettime64
> > +  int ret = INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid,
> > value);  
> 
> Ditto.
> 
> > +  if (ret == 0 || errno != ENOSYS)
> > +    return ret;
> > +# endif
> > +  struct itimerspec its32;
> > +  int retval = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid,
> > &its32);  
> 
> Ditto.
> 
> > +  if (! retval)  
> 
> Please use an explicit comparison with == 0.
> 
> > +    {
> > +      value->it_interval = valid_timespec_to_timespec64
> > (its32.it_interval);
> > +      value->it_value = valid_timespec_to_timespec64
> > (its32.it_value);
> > +    }
> >  
> > -  return res;
> > +  return retval;
> > +#endif
> >  }
> > +  
> 
> Ok.
> 
> > +#if __TIMESIZE != 64
> > +int
> > +__timer_gettime (timer_t timerid, struct itimerspec *value)
> > +{
> > +  struct __itimerspec64 its64;
> > +  int retval = __timer_gettime64 (timerid, &its64);
> > +  if (! retval)  
> 
> Please use an explicit comparison with == 0.
> 
> > +    {
> > +      value->it_interval = valid_timespec64_to_timespec
> > (its64.it_interval);
> > +      value->it_value = valid_timespec64_to_timespec
> > (its64.it_value);
> > +    }
> > +
> > +  return retval;
> > +}
> > +#endif
> > +weak_alias (__timer_gettime, timer_gettime)
> > +libc_hidden_def (timer_gettime)
> >   
> 
> Ok.




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 Dec. 11, 2019, 5:51 p.m. UTC | #4
On Nov 11 2019, Lukasz Majewski wrote:

> diff --git a/include/time.h b/include/time.h
> index 52ee213669..8b9a4b7a60 100644
> --- a/include/time.h
> +++ b/include/time.h
> @@ -179,6 +179,13 @@ extern int __futimens64 (int fd, const struct __timespec64 tsp[2]);
>  libc_hidden_proto (__futimens64);
>  #endif
>  
> +#if __TIMESIZE == 64
> +# define __timer_gettime64 __timer_gettime
> +#else
> +extern int __timer_gettime64 (timer_t timerid, struct __itimerspec64 *value);
> +libc_hidden_proto (__timer_gettime64);

This libc_hidden_proto is wrong since timer_gettime64 lives in librt.

Andreas.
  
Lukasz Majewski Dec. 11, 2019, 10:26 p.m. UTC | #5
Hi Andreas,

> On Nov 11 2019, Lukasz Majewski wrote:
> 
> > diff --git a/include/time.h b/include/time.h
> > index 52ee213669..8b9a4b7a60 100644
> > --- a/include/time.h
> > +++ b/include/time.h
> > @@ -179,6 +179,13 @@ extern int __futimens64 (int fd, const struct
> > __timespec64 tsp[2]); libc_hidden_proto (__futimens64);
> >  #endif
> >  
> > +#if __TIMESIZE == 64
> > +# define __timer_gettime64 __timer_gettime
> > +#else
> > +extern int __timer_gettime64 (timer_t timerid, struct
> > __itimerspec64 *value); +libc_hidden_proto (__timer_gettime64);  
> 
> This libc_hidden_proto is wrong since timer_gettime64 lives in librt.
> 

I may be not so experienced glibc developer, but isn't the
libc_hidden_proto macro used to bypass plt access to this function when
it is used internally in glibc?

For librt there is the same symbol (and stub function defined) for
backward compatibility.

Or am I missing something important? Thanks in advance for the
explanation.

> 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 Dec. 12, 2019, 3:26 p.m. UTC | #6
On Dez 11 2019, Lukasz Majewski wrote:

> I may be not so experienced glibc developer, but isn't the
> libc_hidden_proto macro used to bypass plt access to this function when
> it is used internally in glibc?

But there is no timer_gettime in libc.

> For librt there is the same symbol (and stub function defined) for
> backward compatibility.

??? The implementation in librt is not a stub function.

Andreas.
  
Lukasz Majewski Dec. 12, 2019, 3:33 p.m. UTC | #7
Hi Andreas,

> On Dez 11 2019, Lukasz Majewski wrote:
> 
> > I may be not so experienced glibc developer, but isn't the
> > libc_hidden_proto macro used to bypass plt access to this function
> > when it is used internally in glibc?  
> 
> But there is no timer_gettime in libc.

Please find below link:
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/timer_gettime.c;h=20d34dbfa97de7e9d8e4071426fa463bb524e863;hb=HEAD

> 
> > For librt there is the same symbol (and stub function defined) for
> > backward compatibility.  
> 
> ??? The implementation in librt is not a stub function.
> 

Please find following link:
https://sourceware.org/git/?p=glibc.git;a=tree;f=rt;h=8187c0183ec2a9ef1a71fc7916e37e6242ef83ca;hb=HEAD

> 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 Dec. 12, 2019, 3:46 p.m. UTC | #8
On Dez 12 2019, Lukasz Majewski wrote:

> Please find below link:
> https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/timer_gettime.c;h=20d34dbfa97de7e9d8e4071426fa463bb524e863;hb=HEAD

What does that show?

> Please find following link:
> https://sourceware.org/git/?p=glibc.git;a=tree;f=rt;h=8187c0183ec2a9ef1a71fc7916e37e6242ef83ca;hb=HEAD

What does that show?

Andreas.
  
Lukasz Majewski Dec. 12, 2019, 4:05 p.m. UTC | #9
On Thu, 12 Dec 2019 16:46:50 +0100
Andreas Schwab <schwab@suse.de> wrote:

> On Dez 12 2019, Lukasz Majewski wrote:
> 
> > Please find below link:
> > https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/timer_gettime.c;h=20d34dbfa97de7e9d8e4071426fa463bb524e863;hb=HEAD
> >  
> 
> What does that show?
> 
> > Please find following link:
> > https://sourceware.org/git/?p=glibc.git;a=tree;f=rt;h=8187c0183ec2a9ef1a71fc7916e37e6242ef83ca;hb=HEAD
> >  
> 
> What does that show?


It shows that for rt you have one version of timer_gettime (with
stub_warning) in /rt and another one in the Linux specific one for
glibc.

At least from the directory structure POV. However, I don't know how it
is resolved with compatibility symbols.

> 
> 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 Dec. 12, 2019, 4:08 p.m. UTC | #10
There is only one timer_gettime, and that lives in librt.  The source
file rt/timer_gettime.c is not used.

Andreas.
  

Patch

diff --git a/include/time.h b/include/time.h
index 52ee213669..8b9a4b7a60 100644
--- a/include/time.h
+++ b/include/time.h
@@ -179,6 +179,13 @@  extern int __futimens64 (int fd, const struct __timespec64 tsp[2]);
 libc_hidden_proto (__futimens64);
 #endif
 
+#if __TIMESIZE == 64
+# define __timer_gettime64 __timer_gettime
+#else
+extern int __timer_gettime64 (timer_t timerid, struct __itimerspec64 *value);
+libc_hidden_proto (__timer_gettime64);
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c b/sysdeps/unix/sysv/linux/timer_gettime.c
index 8d9bef9196..31bf5ce25b 100644
--- a/sysdeps/unix/sysv/linux/timer_gettime.c
+++ b/sysdeps/unix/sysv/linux/timer_gettime.c
@@ -20,15 +20,51 @@ 
 #include <stdlib.h>
 #include <time.h>
 #include <sysdep.h>
+#include <kernel-features.h>
 #include "kernel-posix-timers.h"
 
 int
-timer_gettime (timer_t timerid, struct itimerspec *value)
+__timer_gettime64 (timer_t timerid, struct __itimerspec64 *value)
 {
   struct timer *kt = (struct timer *) timerid;
 
-  /* Delete the kernel timer object.  */
-  int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value);
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_timer_gettime64
+#  define __NR_timer_gettime64 __NR_timer_gettime
+# endif
+  return INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);
+#else
+# ifdef __NR_timer_gettime64
+  int ret = INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);
+  if (ret == 0 || errno != ENOSYS)
+    return ret;
+# endif
+  struct itimerspec its32;
+  int retval = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, &its32);
+  if (! retval)
+    {
+      value->it_interval = valid_timespec_to_timespec64 (its32.it_interval);
+      value->it_value = valid_timespec_to_timespec64 (its32.it_value);
+    }
 
-  return res;
+  return retval;
+#endif
 }
+
+#if __TIMESIZE != 64
+int
+__timer_gettime (timer_t timerid, struct itimerspec *value)
+{
+  struct __itimerspec64 its64;
+  int retval = __timer_gettime64 (timerid, &its64);
+  if (! retval)
+    {
+      value->it_interval = valid_timespec64_to_timespec (its64.it_interval);
+      value->it_value = valid_timespec64_to_timespec (its64.it_value);
+    }
+
+  return retval;
+}
+#endif
+weak_alias (__timer_gettime, timer_gettime)
+libc_hidden_def (timer_gettime)