summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>2017-08-09 12:07:41 +0200
committerAlbert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>2017-08-09 12:07:41 +0200
commitf9e14ae98e55911019d3a3d12c4bf05502a43e28 (patch)
treed26e218caf33edaf572290fc104d2c80d25535f5
parent161bce3da545ed806c269b28dbc8621dd432ae2b (diff)
downloadglibc-aaribaud/y2038-2.25-dev.tar.gz
Y2038: implement Y2038-ready adjtimex, ntp_adjtimeaaribaud/y2038-2.25-dev
-rw-r--r--include/time.h31
-rw-r--r--sysdeps/unix/sysv/linux/adjtime.c85
-rw-r--r--sysdeps/unix/sysv/linux/sys/timex.h17
-rw-r--r--time/Versions1
4 files changed, 134 insertions, 0 deletions
diff --git a/include/time.h b/include/time.h
index ead9ec488b..fdec7f0169 100644
--- a/include/time.h
+++ b/include/time.h
@@ -74,6 +74,37 @@ struct __ntptimeval_t64
long int __glibc_reserved4;
};
+/* 64-bit time version of the current struct timex */
+struct __timex_t64
+{
+ unsigned int modes; /* mode selector */
+ __syscall_slong_t offset; /* time offset (usec) */
+ __syscall_slong_t freq; /* frequency offset (scaled ppm) */
+ __syscall_slong_t maxerror; /* maximum error (usec) */
+ __syscall_slong_t esterror; /* estimated error (usec) */
+ int status; /* clock command/status */
+ __syscall_slong_t constant; /* pll time constant */
+ __syscall_slong_t precision; /* clock precision (usec) (ro) */
+ __syscall_slong_t tolerance; /* clock frequency tolerance (ppm) (ro) */
+ struct __timeval64 time; /* (read only, except for ADJ_SETOFFSET) */
+ __syscall_slong_t tick; /* (modified) usecs between clock ticks */
+ __syscall_slong_t ppsfreq; /* pps frequency (scaled ppm) (ro) */
+ __syscall_slong_t jitter; /* pps jitter (us) (ro) */
+ int shift; /* interval duration (s) (shift) (ro) */
+ __syscall_slong_t stabil; /* pps stability (scaled ppm) (ro) */
+ __syscall_slong_t jitcnt; /* jitter limit exceeded (ro) */
+ __syscall_slong_t calcnt; /* calibration intervals (ro) */
+ __syscall_slong_t errcnt; /* calibration errors (ro) */
+ __syscall_slong_t stbcnt; /* stability limit exceeded (ro) */
+
+ int tai; /* TAI offset (ro) */
+
+ /* ??? */
+ int :32; int :32; int :32; int :32;
+ int :32; int :32; int :32; int :32;
+ int :32; int :32; int :32;
+};
+
extern __typeof (clock_getres) __clock_getres;
extern __typeof (clock_gettime) __clock_gettime;
extern int __clock_getres64 (clockid_t __clock_id, struct __timespec64 *__res) __THROW;
diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
index 28a75a2e40..c405769e95 100644
--- a/sysdeps/unix/sysv/linux/adjtime.c
+++ b/sysdeps/unix/sysv/linux/adjtime.c
@@ -19,6 +19,7 @@
#include <limits.h>
#include <sys/time.h>
#include <sys/timex.h>
+#include <include/time.h>
#define MAX_SEC (INT_MAX / 1000000L - 2)
#define MIN_SEC (INT_MIN / 1000000L + 2)
@@ -133,3 +134,87 @@ int __adjtime_t64 (const struct __timeval64 *itv,
}
return 0;
}
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__adjtimex_t64(struct __timex_t64 *tx)
+{
+ struct timex tx32;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement with a 64-bit time syscall */
+ }
+
+ if (tx == NULL)
+ {
+ __set_errno (EFAULT);
+ return -1;
+ }
+
+ if ((tx->modes & ADJ_SETOFFSET) != 0 && tx->time.tv_sec > INT_MAX)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ /* Implement with existing 32-bit time syscall */
+
+ /* Just copy everything */
+ tx32.modes = tx->modes;
+ tx32.offset = tx->offset;
+ tx32.freq = tx->freq;
+ tx32.maxerror = tx->maxerror;
+ tx32.esterror = tx->esterror;
+ tx32.status = tx->status;
+ tx32.constant = tx->constant;
+ tx32.precision = tx->precision;
+ tx32.tolerance = tx->tolerance;
+ tx32.time.tv_sec = tx->time.tv_sec;
+ tx32.time.tv_usec = tx->time.tv_usec;
+ tx32.tick = tx->tick;
+ tx32.ppsfreq = tx->ppsfreq;
+ tx32.jitter = tx->jitter;
+ tx32.shift = tx->shift;
+ tx32.stabil = tx->stabil;
+ tx32.jitcnt = tx->jitcnt;
+ tx32.calcnt = tx->calcnt;
+ tx32.errcnt = tx->errcnt;
+ tx32.stbcnt = tx->stbcnt;
+
+ tx32.tai = tx->tai;
+ /* WARNING -- anonymous fields after TAI are not copied. */
+
+ int result = ADJTIMEX(&tx32);
+
+ if (result == 0)
+ {
+ /* Just copy back everything */
+ tx->modes = tx32.modes;
+ tx->offset = tx32.offset;
+ tx->freq = tx32.freq;
+ tx->maxerror = tx32.maxerror;
+ tx->esterror = tx32.esterror;
+ tx->status = tx32.status;
+ tx->constant = tx32.constant;
+ tx->precision = tx32.precision;
+ tx->tolerance = tx32.tolerance;
+ tx->time.tv_sec = tx32.time.tv_sec;
+ tx->time.tv_usec = tx32.time.tv_usec;
+ tx->tick = tx32.tick;
+ tx->ppsfreq = tx32.ppsfreq;
+ tx->jitter = tx32.jitter;
+ tx->shift = tx32.shift;
+ tx->stabil = tx32.stabil;
+ tx->jitcnt = tx32.jitcnt;
+ tx->calcnt = tx32.calcnt;
+ tx->errcnt = tx32.errcnt;
+ tx->stbcnt = tx32.stbcnt;
+ }
+
+ return result;
+}
+weak_alias (__adjtimex_t64, __ntp_adjtime_t64);
diff --git a/sysdeps/unix/sysv/linux/sys/timex.h b/sysdeps/unix/sysv/linux/sys/timex.h
index 4981d07016..e10c9870f0 100644
--- a/sysdeps/unix/sysv/linux/sys/timex.h
+++ b/sysdeps/unix/sysv/linux/sys/timex.h
@@ -55,6 +55,15 @@ struct ntptimeval
__BEGIN_DECLS
extern int __adjtimex (struct timex *__ntx) __THROW;
+
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (adjtimex, (struct timex *__ntx),
+ __adjtimex_t64) __THROW;
+# else
+# define adjtimex __adjtimex_t64
+# endif
+#endif
extern int adjtimex (struct timex *__ntx) __THROW;
#ifndef __USE_TIME_BITS64
@@ -75,6 +84,14 @@ extern time_t __REDIRECT (ntp_gettimex, (struct ntptimeval *__ntv),
# define ntp_gettime ntp_gettimex
#endif
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (ntp_adjtime, (struct timex *__tntx),
+ __ntp_adjtime_t64) __THROW;
+# else
+# define ntp_adjtime __ntp_adjtime_t64
+# endif
+#endif
extern int ntp_adjtime (struct timex *__tntx) __THROW;
__END_DECLS
diff --git a/time/Versions b/time/Versions
index 10b1ccea0b..947ba1e831 100644
--- a/time/Versions
+++ b/time/Versions
@@ -76,5 +76,6 @@ libc {
__nanosleep_t64;
__adjtime_t64;
__getitimer_t64; __setitimer_t64;
+ __adjtimex_t64;
}
}