[v2,6/7] y2038: linux: Provide __ntp_gettime64 implementation

Message ID 20200508145640.16336-7-lukma@denx.de
State Committed
Delegated to: Lukasz Majewski
Headers
Series y2038: Convert clock_adjtime related syscalls to support 64 bit time |

Commit Message

Lukasz Majewski May 8, 2020, 2:56 p.m. UTC
  This patch provides new __ntp_gettime64 explicit 64 bit function for getting
time parameters via NTP interface.

Internally, the __clock_adjtime64 syscall is used instead of __adjtimex. This
patch is necessary for having architectures with __WORDSIZE == 32 Y2038 safe.

Moreover, a 32 bit version - __ntp_gettime has been refactored to internally
use __ntp_gettime64.

The __ntp_gettime is now supposed to be used on systems still supporting 32
bit time (__TIMESIZE != 64) - hence the necessary conversions between struct
ntptimeval and 64 bit struct __ntptimeval64.

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

Above tests were performed with Y2038 redirection applied as well as without to
test the proper usage of both __ntp_gettime64 and __ntp_gettime.
---
 sysdeps/unix/sysv/linux/include/sys/timex.h |  4 ++++
 sysdeps/unix/sysv/linux/ntp_gettime.c       | 24 ++++++++++++++++++---
 2 files changed, 25 insertions(+), 3 deletions(-)
  

Comments

Adhemerval Zanella May 19, 2020, 7:18 p.m. UTC | #1
On 08/05/2020 11:56, Lukasz Majewski wrote:
> This patch provides new __ntp_gettime64 explicit 64 bit function for getting
> time parameters via NTP interface.
> 
> Internally, the __clock_adjtime64 syscall is used instead of __adjtimex. This
> patch is necessary for having architectures with __WORDSIZE == 32 Y2038 safe.
> 
> Moreover, a 32 bit version - __ntp_gettime has been refactored to internally
> use __ntp_gettime64.
> 
> The __ntp_gettime is now supposed to be used on systems still supporting 32
> bit time (__TIMESIZE != 64) - hence the necessary conversions between struct
> ntptimeval and 64 bit struct __ntptimeval64.
> 
> 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
> 
> Above tests were performed with Y2038 redirection applied as well as without to
> test the proper usage of both __ntp_gettime64 and __ntp_gettime.

Ok with a doubt below.

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

> ---
>  sysdeps/unix/sysv/linux/include/sys/timex.h |  4 ++++
>  sysdeps/unix/sysv/linux/ntp_gettime.c       | 24 ++++++++++++++++++---
>  2 files changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/sysdeps/unix/sysv/linux/include/sys/timex.h b/sysdeps/unix/sysv/linux/include/sys/timex.h
> index e762e03230..ef53515803 100644
> --- a/sysdeps/unix/sysv/linux/include/sys/timex.h
> +++ b/sysdeps/unix/sysv/linux/include/sys/timex.h
> @@ -33,6 +33,7 @@ libc_hidden_proto (__adjtimex)
>  #   define __clock_adjtime64 __clock_adjtime
>  #   define ___adjtimex64 ___adjtimex
>  #   define __ntptimeval64 ntptimeval
> +#   define __ntp_gettime64 __ntp_gettime
>  #  else
>  
>  struct __timex64
> @@ -91,6 +92,9 @@ struct __ntptimeval64
>    long int __glibc_reserved3;
>    long int __glibc_reserved4;
>  };
> +extern int __ntp_gettime64 (struct __ntptimeval64 *ntv);
> +libc_hidden_proto (__ntp_gettime64)
> +
>  #  endif
>  
>  /* Convert a known valid struct timex into a struct __timex64.  */

Ok.

> diff --git a/sysdeps/unix/sysv/linux/ntp_gettime.c b/sysdeps/unix/sysv/linux/ntp_gettime.c
> index c8d6a197dc..21aeffadeb 100644
> --- a/sysdeps/unix/sysv/linux/ntp_gettime.c
> +++ b/sysdeps/unix/sysv/linux/ntp_gettime.c
> @@ -17,6 +17,7 @@
>  
>  #define ntp_gettime ntp_gettime_redirect
>  
> +#include <time.h>
>  #include <sys/timex.h>
>  
>  #undef ntp_gettime
> @@ -27,15 +28,32 @@
>  
>  
>  int
> -ntp_gettime (struct ntptimeval *ntv)
> +__ntp_gettime64 (struct __ntptimeval64 *ntv)
>  {
> -  struct timex tntx;
> +  struct __timex64 tntx;
>    int result;
>  
>    tntx.modes = 0;
> -  result = __adjtimex (&tntx);
> +  result = __clock_adjtime64 (CLOCK_REALTIME, &tntx);
>    ntv->time = tntx.time;
>    ntv->maxerror = tntx.maxerror;
>    ntv->esterror = tntx.esterror;
>    return result;
>  }

Ok. Maybe add a comment stating that using CLOCK_REALTIME should
not make the function fail with EINVAL, ENODEV, or EOPNOTSUPP.
I am not sure about EPERM in this situation, should we check for
that and avoid seeting NTV in such situation?

> +
> +#if __TIMESIZE != 64
> +libc_hidden_def (__ntp_gettime64)
> +
> +int
> +__ntp_gettime (struct ntptimeval *ntv)
> +{
> +  struct __ntptimeval64 ntv64;
> +  int result;
> +
> +  result = __ntp_gettime64 (&ntv64);
> +  *ntv = valid_ntptimeval64_to_ntptimeval (ntv64);
> +
> +  return result;
> +}
> +#endif
> +strong_alias (__ntp_gettime, ntp_gettime)
> 

Ok.
  
Lukasz Majewski May 19, 2020, 8:20 p.m. UTC | #2
Hi Adhemerval,

> On 08/05/2020 11:56, Lukasz Majewski wrote:
> > This patch provides new __ntp_gettime64 explicit 64 bit function
> > for getting time parameters via NTP interface.
> > 
> > Internally, the __clock_adjtime64 syscall is used instead of
> > __adjtimex. This patch is necessary for having architectures with
> > __WORDSIZE == 32 Y2038 safe.
> > 
> > Moreover, a 32 bit version - __ntp_gettime has been refactored to
> > internally use __ntp_gettime64.
> > 
> > The __ntp_gettime is now supposed to be used on systems still
> > supporting 32 bit time (__TIMESIZE != 64) - hence the necessary
> > conversions between struct ntptimeval and 64 bit struct
> > __ntptimeval64.
> > 
> > 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
> > 
> > Above tests were performed with Y2038 redirection applied as well
> > as without to test the proper usage of both __ntp_gettime64 and
> > __ntp_gettime.  
> 
> Ok with a doubt below.
> 
> Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
> 
> > ---
> >  sysdeps/unix/sysv/linux/include/sys/timex.h |  4 ++++
> >  sysdeps/unix/sysv/linux/ntp_gettime.c       | 24
> > ++++++++++++++++++--- 2 files changed, 25 insertions(+), 3
> > deletions(-)
> > 
> > diff --git a/sysdeps/unix/sysv/linux/include/sys/timex.h
> > b/sysdeps/unix/sysv/linux/include/sys/timex.h index
> > e762e03230..ef53515803 100644 ---
> > a/sysdeps/unix/sysv/linux/include/sys/timex.h +++
> > b/sysdeps/unix/sysv/linux/include/sys/timex.h @@ -33,6 +33,7 @@
> > libc_hidden_proto (__adjtimex) #   define __clock_adjtime64
> > __clock_adjtime #   define ___adjtimex64 ___adjtimex
> >  #   define __ntptimeval64 ntptimeval
> > +#   define __ntp_gettime64 __ntp_gettime
> >  #  else
> >  
> >  struct __timex64
> > @@ -91,6 +92,9 @@ struct __ntptimeval64
> >    long int __glibc_reserved3;
> >    long int __glibc_reserved4;
> >  };
> > +extern int __ntp_gettime64 (struct __ntptimeval64 *ntv);
> > +libc_hidden_proto (__ntp_gettime64)
> > +
> >  #  endif
> >  
> >  /* Convert a known valid struct timex into a struct __timex64.  */
> >  
> 
> Ok.
> 
> > diff --git a/sysdeps/unix/sysv/linux/ntp_gettime.c
> > b/sysdeps/unix/sysv/linux/ntp_gettime.c index
> > c8d6a197dc..21aeffadeb 100644 ---
> > a/sysdeps/unix/sysv/linux/ntp_gettime.c +++
> > b/sysdeps/unix/sysv/linux/ntp_gettime.c @@ -17,6 +17,7 @@
> >  
> >  #define ntp_gettime ntp_gettime_redirect
> >  
> > +#include <time.h>
> >  #include <sys/timex.h>
> >  
> >  #undef ntp_gettime
> > @@ -27,15 +28,32 @@
> >  
> >  
> >  int
> > -ntp_gettime (struct ntptimeval *ntv)
> > +__ntp_gettime64 (struct __ntptimeval64 *ntv)
> >  {
> > -  struct timex tntx;
> > +  struct __timex64 tntx;
> >    int result;
> >  
> >    tntx.modes = 0;
> > -  result = __adjtimex (&tntx);
> > +  result = __clock_adjtime64 (CLOCK_REALTIME, &tntx);
> >    ntv->time = tntx.time;
> >    ntv->maxerror = tntx.maxerror;
> >    ntv->esterror = tntx.esterror;
> >    return result;
> >  }  
> 
> Ok. Maybe add a comment stating that using CLOCK_REALTIME should
> not make the function fail with EINVAL, ENODEV, or EOPNOTSUPP.
> I am not sure about EPERM in this situation, should we check for
> that and avoid seeting NTV in such situation?
> 

I will add following comment:

/* Using the CLOCK_REALTIME with __clock_adjtime64 (as a replacement
for Y2038 unsafe adjtimex) will not make the function fail with EINVAL,
ENODEV, or EOPNOTSUPP.  */

Regarding the EPERM:

The adjtimex also could return EPERM:
http://man7.org/linux/man-pages/man2/adjtimex.2.html

which would be propagated to caller of ntp_gettime. In this case the
ntv structure would get updated.

If we want to preserve the same behavior, it would be correct to leave
the code as is (and ntv would get updated anyway).

> > +
> > +#if __TIMESIZE != 64
> > +libc_hidden_def (__ntp_gettime64)
> > +
> > +int
> > +__ntp_gettime (struct ntptimeval *ntv)
> > +{
> > +  struct __ntptimeval64 ntv64;
> > +  int result;
> > +
> > +  result = __ntp_gettime64 (&ntv64);
> > +  *ntv = valid_ntptimeval64_to_ntptimeval (ntv64);
> > +
> > +  return result;
> > +}
> > +#endif
> > +strong_alias (__ntp_gettime, ntp_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
  
Adhemerval Zanella May 19, 2020, 8:25 p.m. UTC | #3
On 19/05/2020 17:20, Lukasz Majewski wrote:
> Hi Adhemerval,
> 
>> On 08/05/2020 11:56, Lukasz Majewski wrote:
>>> This patch provides new __ntp_gettime64 explicit 64 bit function
>>> for getting time parameters via NTP interface.
>>>
>>> Internally, the __clock_adjtime64 syscall is used instead of
>>> __adjtimex. This patch is necessary for having architectures with
>>> __WORDSIZE == 32 Y2038 safe.
>>>
>>> Moreover, a 32 bit version - __ntp_gettime has been refactored to
>>> internally use __ntp_gettime64.
>>>
>>> The __ntp_gettime is now supposed to be used on systems still
>>> supporting 32 bit time (__TIMESIZE != 64) - hence the necessary
>>> conversions between struct ntptimeval and 64 bit struct
>>> __ntptimeval64.
>>>
>>> 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
>>>
>>> Above tests were performed with Y2038 redirection applied as well
>>> as without to test the proper usage of both __ntp_gettime64 and
>>> __ntp_gettime.  
>>
>> Ok with a doubt below.
>>
>> Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
>>
>>> ---
>>>  sysdeps/unix/sysv/linux/include/sys/timex.h |  4 ++++
>>>  sysdeps/unix/sysv/linux/ntp_gettime.c       | 24
>>> ++++++++++++++++++--- 2 files changed, 25 insertions(+), 3
>>> deletions(-)
>>>
>>> diff --git a/sysdeps/unix/sysv/linux/include/sys/timex.h
>>> b/sysdeps/unix/sysv/linux/include/sys/timex.h index
>>> e762e03230..ef53515803 100644 ---
>>> a/sysdeps/unix/sysv/linux/include/sys/timex.h +++
>>> b/sysdeps/unix/sysv/linux/include/sys/timex.h @@ -33,6 +33,7 @@
>>> libc_hidden_proto (__adjtimex) #   define __clock_adjtime64
>>> __clock_adjtime #   define ___adjtimex64 ___adjtimex
>>>  #   define __ntptimeval64 ntptimeval
>>> +#   define __ntp_gettime64 __ntp_gettime
>>>  #  else
>>>  
>>>  struct __timex64
>>> @@ -91,6 +92,9 @@ struct __ntptimeval64
>>>    long int __glibc_reserved3;
>>>    long int __glibc_reserved4;
>>>  };
>>> +extern int __ntp_gettime64 (struct __ntptimeval64 *ntv);
>>> +libc_hidden_proto (__ntp_gettime64)
>>> +
>>>  #  endif
>>>  
>>>  /* Convert a known valid struct timex into a struct __timex64.  */
>>>  
>>
>> Ok.
>>
>>> diff --git a/sysdeps/unix/sysv/linux/ntp_gettime.c
>>> b/sysdeps/unix/sysv/linux/ntp_gettime.c index
>>> c8d6a197dc..21aeffadeb 100644 ---
>>> a/sysdeps/unix/sysv/linux/ntp_gettime.c +++
>>> b/sysdeps/unix/sysv/linux/ntp_gettime.c @@ -17,6 +17,7 @@
>>>  
>>>  #define ntp_gettime ntp_gettime_redirect
>>>  
>>> +#include <time.h>
>>>  #include <sys/timex.h>
>>>  
>>>  #undef ntp_gettime
>>> @@ -27,15 +28,32 @@
>>>  
>>>  
>>>  int
>>> -ntp_gettime (struct ntptimeval *ntv)
>>> +__ntp_gettime64 (struct __ntptimeval64 *ntv)
>>>  {
>>> -  struct timex tntx;
>>> +  struct __timex64 tntx;
>>>    int result;
>>>  
>>>    tntx.modes = 0;
>>> -  result = __adjtimex (&tntx);
>>> +  result = __clock_adjtime64 (CLOCK_REALTIME, &tntx);
>>>    ntv->time = tntx.time;
>>>    ntv->maxerror = tntx.maxerror;
>>>    ntv->esterror = tntx.esterror;
>>>    return result;
>>>  }  
>>
>> Ok. Maybe add a comment stating that using CLOCK_REALTIME should
>> not make the function fail with EINVAL, ENODEV, or EOPNOTSUPP.
>> I am not sure about EPERM in this situation, should we check for
>> that and avoid seeting NTV in such situation?
>>
> 
> I will add following comment:
> 
> /* Using the CLOCK_REALTIME with __clock_adjtime64 (as a replacement
> for Y2038 unsafe adjtimex) will not make the function fail with EINVAL,
> ENODEV, or EOPNOTSUPP.  */

Maybe:

  /* clock_adjtime64 with CLOCK_REALTIME does not trigger EINVAL,
     ENODEV, or EOPNOTSUPP.  It might still trigger EPERM.  */

> 
> Regarding the EPERM:
> 
> The adjtimex also could return EPERM:
> http://man7.org/linux/man-pages/man2/adjtimex.2.html
> 
> which would be propagated to caller of ntp_gettime. In this case the
> ntv structure would get updated.
> 
> If we want to preserve the same behavior, it would be correct to leave
> the code as is (and ntv would get updated anyway).

Alight, we can track this in another patch.

> 
>>> +
>>> +#if __TIMESIZE != 64
>>> +libc_hidden_def (__ntp_gettime64)
>>> +
>>> +int
>>> +__ntp_gettime (struct ntptimeval *ntv)
>>> +{
>>> +  struct __ntptimeval64 ntv64;
>>> +  int result;
>>> +
>>> +  result = __ntp_gettime64 (&ntv64);
>>> +  *ntv = valid_ntptimeval64_to_ntptimeval (ntv64);
>>> +
>>> +  return result;
>>> +}
>>> +#endif
>>> +strong_alias (__ntp_gettime, ntp_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
>
  
Joseph Myers May 20, 2020, 3:23 p.m. UTC | #4
I'm seeing build failures from build-many-glibcs.py for hppa, mips (n32), 
sh4, sparcv8, sparcv9, that appear to arise from one of these patches.

../sysdeps/unix/sysv/linux/ntp_gettime.c: In function '__ntp_gettime':
../sysdeps/unix/sysv/linux/ntp_gettime.c:56:10: error: 'ntv64.tai' is used uninitialized in this function [-Werror=uninitialized]
   56 |   *ntv = valid_ntptimeval64_to_ntptimeval (ntv64);
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

https://sourceware.org/pipermail/libc-testresults/2020q2/006191.html
  
Lukasz Majewski May 20, 2020, 5:08 p.m. UTC | #5
Hi Joseph,

> I'm seeing build failures from build-many-glibcs.py for hppa, mips
> (n32), sh4, sparcv8, sparcv9, that appear to arise from one of these
> patches.
> 
> ../sysdeps/unix/sysv/linux/ntp_gettime.c: In function '__ntp_gettime':
> ../sysdeps/unix/sysv/linux/ntp_gettime.c:56:10: error: 'ntv64.tai' is
> used uninitialized in this function [-Werror=uninitialized] 56 |
> *ntv = valid_ntptimeval64_to_ntptimeval (ntv64); |
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> https://sourceware.org/pipermail/libc-testresults/2020q2/006191.html
> 

Thanks for spotting it.

I'm wondering if those archs use different set of gcc switches for
compilation?

And another question (I think related) - after updating the the glibc
-master (there was a switch to gcc 10 for build-many-glibc.py) I do have
an issue with "check-compilers" task on those archs.

Joseph, do you use updated setup?


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 May 20, 2020, 5:21 p.m. UTC | #6
On Wed, 20 May 2020, Lukasz Majewski wrote:

> I'm wondering if those archs use different set of gcc switches for
> compilation?

No.  But there are various architecture-specific aspects to optimization 
that may result in warnings showing up on only some architectures.

Florian has fixed this bug.

> And another question (I think related) - after updating the the glibc
> -master (there was a switch to gcc 10 for build-many-glibc.py) I do have
> an issue with "check-compilers" task on those archs.

A check-compilers failure simply means that one of the tasks from the 
"compilers" run failed.

In general, if you did a "compilers" run when the build was broken, you 
will have an incomplete set of compilers that isn't good for testing 
subsequent glibc changes and will need to rerun "compilers" with the 
source trees in an unbroken state.

> Joseph, do you use updated setup?

My bots using GCC release branches only rebuild "compilers" once a week.  
That means a short-lived glibc build breakage is likely to show up as a 
failure in "glibcs" rather than "compilers" (but if the build is broken at 
the wrong time, when "compilers" runs, the "glibcs" builds will be using 
the broken compilers for a week).

My bot using GCC master rebuilds the compilers every time (but only runs 
once a day, whereas the ones using GCC release branches will run more 
frequently if there are new glibc changes to test).
  
Lukasz Majewski May 21, 2020, 10:31 a.m. UTC | #7
Hi Joseph,

> On Wed, 20 May 2020, Lukasz Majewski wrote:
> 
> > I'm wondering if those archs use different set of gcc switches for
> > compilation?  
> 
> No.  But there are various architecture-specific aspects to
> optimization that may result in warnings showing up on only some
> architectures.
> 
> Florian has fixed this bug.
> 
> > And another question (I think related) - after updating the the
> > glibc -master (there was a switch to gcc 10 for
> > build-many-glibc.py) I do have an issue with "check-compilers" task
> > on those archs.  
> 
> A check-compilers failure simply means that one of the tasks from the 
> "compilers" run failed.
> 
> In general, if you did a "compilers" run when the build was broken,
> you will have an incomplete set of compilers that isn't good for
> testing subsequent glibc changes and will need to rerun "compilers"
> with the source trees in an unbroken state.

Yes, you are 100% correct. That was the case - I wanted to rebuild
compilers after update to gcc 10 for build-many-glibc.py.

As a result I used the broken glibc for building compilers.

Thanks for explanation.

> 
> > Joseph, do you use updated setup?  
> 
> My bots using GCC release branches only rebuild "compilers" once a
> week. That means a short-lived glibc build breakage is likely to show
> up as a failure in "glibcs" rather than "compilers" (but if the build
> is broken at the wrong time, when "compilers" runs, the "glibcs"
> builds will be using the broken compilers for a week).
> 
> My bot using GCC master rebuilds the compilers every time (but only
> runs once a day, whereas the ones using GCC release branches will run
> more frequently if there are new glibc changes to test).
> 


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/sysdeps/unix/sysv/linux/include/sys/timex.h b/sysdeps/unix/sysv/linux/include/sys/timex.h
index e762e03230..ef53515803 100644
--- a/sysdeps/unix/sysv/linux/include/sys/timex.h
+++ b/sysdeps/unix/sysv/linux/include/sys/timex.h
@@ -33,6 +33,7 @@  libc_hidden_proto (__adjtimex)
 #   define __clock_adjtime64 __clock_adjtime
 #   define ___adjtimex64 ___adjtimex
 #   define __ntptimeval64 ntptimeval
+#   define __ntp_gettime64 __ntp_gettime
 #  else
 
 struct __timex64
@@ -91,6 +92,9 @@  struct __ntptimeval64
   long int __glibc_reserved3;
   long int __glibc_reserved4;
 };
+extern int __ntp_gettime64 (struct __ntptimeval64 *ntv);
+libc_hidden_proto (__ntp_gettime64)
+
 #  endif
 
 /* Convert a known valid struct timex into a struct __timex64.  */
diff --git a/sysdeps/unix/sysv/linux/ntp_gettime.c b/sysdeps/unix/sysv/linux/ntp_gettime.c
index c8d6a197dc..21aeffadeb 100644
--- a/sysdeps/unix/sysv/linux/ntp_gettime.c
+++ b/sysdeps/unix/sysv/linux/ntp_gettime.c
@@ -17,6 +17,7 @@ 
 
 #define ntp_gettime ntp_gettime_redirect
 
+#include <time.h>
 #include <sys/timex.h>
 
 #undef ntp_gettime
@@ -27,15 +28,32 @@ 
 
 
 int
-ntp_gettime (struct ntptimeval *ntv)
+__ntp_gettime64 (struct __ntptimeval64 *ntv)
 {
-  struct timex tntx;
+  struct __timex64 tntx;
   int result;
 
   tntx.modes = 0;
-  result = __adjtimex (&tntx);
+  result = __clock_adjtime64 (CLOCK_REALTIME, &tntx);
   ntv->time = tntx.time;
   ntv->maxerror = tntx.maxerror;
   ntv->esterror = tntx.esterror;
   return result;
 }
+
+#if __TIMESIZE != 64
+libc_hidden_def (__ntp_gettime64)
+
+int
+__ntp_gettime (struct ntptimeval *ntv)
+{
+  struct __ntptimeval64 ntv64;
+  int result;
+
+  result = __ntp_gettime64 (&ntv64);
+  *ntv = valid_ntptimeval64_to_ntptimeval (ntv64);
+
+  return result;
+}
+#endif
+strong_alias (__ntp_gettime, ntp_gettime)