[RFC,v5,03/21] sysdeps/gettimeofday: Use clock_gettime64 if avaliable
Commit Message
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(-)
@@ -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)