@@ -32,8 +32,65 @@
int
__gettimeofday (struct timeval *tv, struct timezone *tz)
{
- return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+ long int ret_64;
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_clock_gettime64
+# define __NR_clock_gettime64 __NR_clock_gettime
+# endif
+ struct timespec now;
+
+ ret_64 = INLINE_VSYSCALL (clock_gettime64, 2, CLOCK_REALTIME,
+ &now);
+
+ if (ret_64 == 0 || errno != ENOSYS)
+ valid_timespec64_to_timeval((struct __timespec64*) &now, tv);
+
+ return ret_64;
+#else
+# ifdef __NR_clock_gettime64
+ ret_64 = INLINE_VSYSCALL (clock_gettime64, 2, CLOCK_REALTIME,
+ &now);
+
+ if (ret_64 == 0 || errno != ENOSYS)
+ {
+ valid_timespec64_to_timeval((struct __timespec64*) &now, tv);
+ return ret_64;
+ }
+# endif /* __NR_clock_gettime64 */
+ int ret = INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+
+ if (! in_time_t_range (tv->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ return ret;
+#endif
}
+
+#if __TIMESIZE != 64
+int
+__gettimeofday (struct timeval *tv, struct timezone *tz)
+{
+ int ret;
+ timeval64 tv64;
+ struct __timespec64 now;
+
+ ret = __gettimeofday (&tv64, tz);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ /* Convert from timespec to timeval */
+ tv->tv_sec = tv64.tv_sec;
+ tv->tv_usec = tv64.tv_nsec;
+ return ret;
+ }
+
+ return ret;
+}
+#endif
+
libc_hidden_def (__gettimeofday)
weak_alias (__gettimeofday, gettimeofday)
libc_hidden_weak (gettimeofday)
Not all architectures support the obsolete gettimeofday so use the newer clock_gettime64 syscall if it is avaliable. This fixes RV32 build issues. This has the side effect of not setting the struct timezone *tz variable if __ASSUME_TIME64_SYSCALLS or __NR_clock_gettime64 is defined!!! The struct timezone *tz variable contaions information on the current timezone, in this structure: struct timezone { int tz_minuteswest; /* minutes west of Greenwich */ int tz_dsttime; /* type of DST correction */ }; On 32-bit systems with __ARCH_WANT_TIME32_SYSCALLS not defined there is no way way to get the struct timezone via a syscall. AFAIK there are no plans to add suppor to a future kernel. Most callers of gettimeofday() don't use the timezone data, see example code from Debian below. If __ASSUME_TIME64_SYSCALLS and __NR_clock_gettime64 are not defined then struct timezone *tz will be set as usual. Example code from Debian: struct timeval my_gettime(void) { struct timezone tz_ignored; struct timeval tv; gettimeofday(&tv, &tz_ignored); return tv; } Arnd used Debian code search and found the following uses of struct timezone: drivers/media/platform/vivid/vivid-rds-gen.c: (sys_tz.tz_minuteswest >= 0 ? 0x20 : 0) | drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c: record->end_utc_bias = cpu_to_le16(sys_tz.tz_minuteswest * 60); drivers/scsi/3w-9xxx.c: local_time = (u32)(ktime_get_real_seconds() - (sys_tz.tz_minuteswest * 60)); drivers/scsi/3w-sas.c: local_time = (u32)(ktime_get_real_seconds() - (sys_tz.tz_minuteswest * 60)); drivers/scsi/aacraid/commsup.c: local_time = (now->tv_sec - (sys_tz.tz_minuteswest * 60)); drivers/scsi/arcmsr/arcmsr_hba.c: time64_to_tm(ktime_get_real_seconds(), -sys_tz.tz_minuteswest * 60, &tm); drivers/scsi/mvumi.c: local_time = (time - (sys_tz.tz_minuteswest * 60)); drivers/scsi/smartpqi/smartpqi_init.c: time64_to_tm(local_time, -sys_tz.tz_minuteswest * 60, &tm); fs/affs/amigaffs.c: secs -= sys_tz.tz_minuteswest * 60 + ((8 * 365 + 2) * 24 * 60 * 60); fs/affs/inode.c: sys_tz.tz_minuteswest * 60; fs/fat/misc.c: sys_tz.tz_minuteswest) * SECS_PER_MIN; fs/hfs/hfs_fs.h: return ut + sys_tz.tz_minuteswest * 60; fs/hfs/inode.c: HFS_I(inode)->tz_secondswest = sys_tz.tz_minuteswest * 60; fs/hfs/sysdep.c: diff = sys_tz.tz_minuteswest * 60 - HFS_I(inode)->tz_secondswest; fs/hpfs/hpfs_fn.h: return t + sys_tz.tz_minuteswest * 60 + hpfs_sb(s)->sb_timeshift; fs/udf/udftime.c: offset = -sys_tz.tz_minuteswest; kernel/debug/kdb/kdb_main.c: sys_tz.tz_minuteswest); kernel/time/ntp.c: adjust.tv_sec -= (sys_tz.tz_minuteswest * 60); kernel/time/timekeeping.c: if (sys_tz.tz_minuteswest != 0) { kernel/time/vsyscall.c: vdata[CS_HRES_COARSE].tz_minuteswest = sys_tz.tz_minuteswest; lib/vdso/gettimeofday.c: tz->tz_minuteswest = vd[CS_HRES_COARSE].tz_minuteswest; net/netfilter/xt_time.c: stamp -= 60 * sys_tz.tz_minuteswest; Signed-off-by: Alistair Francis <alistair.francis@wdc.com> * sysdeps/unix/sysv/linux/gettimeofday.c: Use clock_gettime64 syscall for gettimeofday. --- sysdeps/unix/sysv/linux/gettimeofday.c | 59 +++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-)