Message ID | 84b269f1c4a8633e01bd623c07080143c70b785e.1565398513.git.alistair.francis@wdc.com |
---|---|
State | New |
Headers | show |
Series | RISC-V glibc port for the 32-bit | expand |
On Fri, 9 Aug 2019, Alistair Francis wrote: > /* Get current value of CLOCK and store it in TP. */ > + > int > __clock_gettime (clockid_t clock_id, struct timespec *tp) > { > - return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); > + > +#ifdef __ASSUME_TIME64_SYSCALLS > + return INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); > +#else This has the usual problems with missing conversions.
On Mon, Aug 12, 2019 at 12:46 PM Joseph Myers <joseph@codesourcery.com> wrote: > > On Fri, 9 Aug 2019, Alistair Francis wrote: > > > /* Get current value of CLOCK and store it in TP. */ > > + > > int > > __clock_gettime (clockid_t clock_id, struct timespec *tp) > > { > > - return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); > > + > > +#ifdef __ASSUME_TIME64_SYSCALLS > > + return INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); > > +#else > > This has the usual problems with missing conversions. I was under the impression (although possibly incorrectly) that if __ASSUME_TIME64_SYSCALLS is defined we would have a 64-bit time_t. Is __ASSUME_TIME64_SYSCALLS going to be defined on 32-bit architectures that are still using a 32-bit time_t? Alistair > > -- > Joseph S. Myers > joseph@codesourcery.com
On Tue, 13 Aug 2019, Alistair Francis wrote: > I was under the impression (although possibly incorrectly) that if > __ASSUME_TIME64_SYSCALLS is defined we would have a 64-bit time_t. Is > __ASSUME_TIME64_SYSCALLS going to be defined on 32-bit architectures > that are still using a 32-bit time_t? Yes. --enable-kernel=5.1.0 is not an ABI-changing option; it only affects what syscalls glibc can assume to be present at runtime in the kernel it runs on. __ASSUME_TIME64_SYSCALLS means only that certain syscalls using 64-bit time are assumed to be available: either suffixed versions such as __NR_clock_gettime64, or corresponding unsuffixed versions such as __NR_clock_gettime in the case where those use 64-bit time and have exactly the same semantics and so "#define __NR_clock_gettime64 __NR_clock_gettime" is OK. (Because the kernel headers must be at least as recent as the minimum kernel version used at runtime, it also implies that the kernel headers do define the syscall numbers - but as noted, the syscalls might be __NR_clock_gettime etc. rather than the suffixed versions.) All four combinations of __ASSUME_TIME64_SYSCALLS and __TIMESIZE are valid. 1. __TIMESIZE == 64 and __ASSUME_TIME64_SYSCALLS defined means a glibc port does not support anything other than 64-bit time *as its userspace ABI*, with the minimum kernel version ensuring appropriate syscalls are available. Cases of this include: (a) Classic 64-bit systems (__WORDSIZE == 64, unsuffixed syscalls). (b) x32 (__WORDSIZE == 32, __SYSCALL_WORDSIZE == 64, unsuffixed syscalls). (c) New glibc ports with 32-bit "long int" in the syscall interface (__WORDSIZE == 32 and __SYSCALL_WORDSIZE == 32) but only supporting 64-bit time as its userspace ABI and with the configured minimum kernel version (5.1 or later) ensuring appropriate (suffixed) syscalls are available (and unsuffixed ones don't exist at all). This is the case that applies to RV32. 2. __TIMESIZE == 64 and __ASSUME_TIME64_SYSCALLS not defined means a glibc port that does not support anything other than 64-bit time *as its userspace ABI*, but with the minimum kernel version not ensuring appropriate syscalls are available. This implies __WORDSIZE == 32 and __SYSCALL_WORDSIZE == 32. This is a hypothetical case, if a new glibc port were added for a 32-bit architecture that was supported in the Linux kernel before 5.1, and if it were chosen to have 64-bit time as the userspace ABI for this port but to support using kernels before 5.1. As it's hypothetical, it's not something you're expected to test unless adding such a port - but most of the support for it should naturally fall out from the Y2038 implementation anyway (the support for 64-bit interfaces to use 32-bit syscalls when run on older kernels). 3. __TIMESIZE == 32 and __ASSUME_TIME64_SYSCALLS defined means a 32-bit glibc port, where the unsuffixed time-related ABIs in glibc use 32-bit time but the Y2038 work will add corresponding suffixed ABIs (and _TIME_BITS headers support) that use 64-bit time - and where the minimum kernel version ensures 64-bit-time (suffixed) syscalls are available. So the suffixed ABIs for 64-bit time can call those suffixed syscalls unconditionally, but the unsuffixed ABIs need to do appropriate translation between 32-bit and 64-bit time to call those syscalls (and the expected design is that the unsuffixed ABIs will generally be thin wrappers that do such translation and call the suffixed ones). 4. __TIMESIZE == 32 and __ASSUME_TIME64_SYSCALLS not defined means a 32-bit glibc port, where the unsuffixed time-related ABIs in glibc use 32-bit time but the Y2038 work will add corresponding suffixed ABIs (and _TIME_BITS headers support) that use 64-bit time - and where the minimum kernel version does not ensure that 64-bit-time (suffixed) syscalls are available. Thus, the suffixed ABIs for 64-bit time need to have support for falling back to the 32-bit syscalls when the 64-bit ones are not available.
On Wed, Aug 14, 2019 at 9:37 AM Joseph Myers <joseph@codesourcery.com> wrote: > > On Tue, 13 Aug 2019, Alistair Francis wrote: > > > I was under the impression (although possibly incorrectly) that if > > __ASSUME_TIME64_SYSCALLS is defined we would have a 64-bit time_t. Is > > __ASSUME_TIME64_SYSCALLS going to be defined on 32-bit architectures > > that are still using a 32-bit time_t? > > Yes. --enable-kernel=5.1.0 is not an ABI-changing option; it only affects > what syscalls glibc can assume to be present at runtime in the kernel it > runs on. > > __ASSUME_TIME64_SYSCALLS means only that certain syscalls using 64-bit > time are assumed to be available: either suffixed versions such as > __NR_clock_gettime64, or corresponding unsuffixed versions such as > __NR_clock_gettime in the case where those use 64-bit time and have > exactly the same semantics and so "#define __NR_clock_gettime64 > __NR_clock_gettime" is OK. (Because the kernel headers must be at least > as recent as the minimum kernel version used at runtime, it also implies > that the kernel headers do define the syscall numbers - but as noted, the > syscalls might be __NR_clock_gettime etc. rather than the suffixed > versions.) > > All four combinations of __ASSUME_TIME64_SYSCALLS and __TIMESIZE are > valid. > > 1. __TIMESIZE == 64 and __ASSUME_TIME64_SYSCALLS defined means a glibc > port does not support anything other than 64-bit time *as its userspace > ABI*, with the minimum kernel version ensuring appropriate syscalls are > available. Cases of this include: > > (a) Classic 64-bit systems (__WORDSIZE == 64, unsuffixed syscalls). > > (b) x32 (__WORDSIZE == 32, __SYSCALL_WORDSIZE == 64, unsuffixed syscalls). > > (c) New glibc ports with 32-bit "long int" in the syscall interface > (__WORDSIZE == 32 and __SYSCALL_WORDSIZE == 32) but only supporting 64-bit > time as its userspace ABI and with the configured minimum kernel version > (5.1 or later) ensuring appropriate (suffixed) syscalls are available (and > unsuffixed ones don't exist at all). This is the case that applies to > RV32. > > 2. __TIMESIZE == 64 and __ASSUME_TIME64_SYSCALLS not defined means a glibc > port that does not support anything other than 64-bit time *as its > userspace ABI*, but with the minimum kernel version not ensuring > appropriate syscalls are available. This implies __WORDSIZE == 32 and > __SYSCALL_WORDSIZE == 32. This is a hypothetical case, if a new glibc > port were added for a 32-bit architecture that was supported in the Linux > kernel before 5.1, and if it were chosen to have 64-bit time as the > userspace ABI for this port but to support using kernels before 5.1. As > it's hypothetical, it's not something you're expected to test unless > adding such a port - but most of the support for it should naturally fall > out from the Y2038 implementation anyway (the support for 64-bit > interfaces to use 32-bit syscalls when run on older kernels). > > 3. __TIMESIZE == 32 and __ASSUME_TIME64_SYSCALLS defined means a 32-bit > glibc port, where the unsuffixed time-related ABIs in glibc use 32-bit > time but the Y2038 work will add corresponding suffixed ABIs (and > _TIME_BITS headers support) that use 64-bit time - and where the minimum > kernel version ensures 64-bit-time (suffixed) syscalls are available. So > the suffixed ABIs for 64-bit time can call those suffixed syscalls > unconditionally, but the unsuffixed ABIs need to do appropriate > translation between 32-bit and 64-bit time to call those syscalls (and the > expected design is that the unsuffixed ABIs will generally be thin > wrappers that do such translation and call the suffixed ones). Ok, I didn't realise that this was a possible case, I will update the series. Alistair > > 4. __TIMESIZE == 32 and __ASSUME_TIME64_SYSCALLS not defined means a > 32-bit glibc port, where the unsuffixed time-related ABIs in glibc use > 32-bit time but the Y2038 work will add corresponding suffixed ABIs (and > _TIME_BITS headers support) that use 64-bit time - and where the minimum > kernel version does not ensure that 64-bit-time (suffixed) syscalls are > available. Thus, the suffixed ABIs for 64-bit time need to have support > for falling back to the 32-bit syscalls when the 64-bit ones are not > available. > > -- > Joseph S. Myers > joseph@codesourcery.com
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c index 5fc47fb7dc7..c090797e461 100644 --- a/sysdeps/unix/sysv/linux/clock_gettime.c +++ b/sysdeps/unix/sysv/linux/clock_gettime.c @@ -27,10 +27,70 @@ #include <sysdep-vdso.h> /* Get current value of CLOCK and store it in TP. */ + int __clock_gettime (clockid_t clock_id, struct timespec *tp) { - return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); + +#ifdef __ASSUME_TIME64_SYSCALLS + return INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); +#else + int ret; +# ifdef __NR_clock_gettime64 +# if __TIMESIZE == 64 + ret = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); + + if (ret == 0 || errno != ENOSYS) + { + return ret; + } +# else + struct __timespec64 tp64; + ret = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, &tp64); + + if (ret == 0 || errno != ENOSYS) + { + tp->tv_sec = tp64.tv_sec; + tp->tv_nsec = tp64.tv_nsec; + if (! in_time_t_range (tp->tv_sec)) + { + __set_errno (EOVERFLOW); + return -1; + } + + return 0; + } +# endif /* __TIMESIZE == 64 */ +# endif /* __NR_clock_gettime64 */ +# if __TIMESIZE == 64 + struct timespec ts32; + + if (! in_time_t_range (tp->tv_sec)) + { + __set_errno (EOVERFLOW); + return -1; + } + + ret = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32); + + if (ret == 0 || errno != ENOSYS) + { + tp->tv_sec = ts32.tv_sec; + tp->tv_nsec = ts32.tv_nsec; + if (! in_time_t_range (tp->tv_sec)) + { + __set_errno (EOVERFLOW); + return -1; + } + + return 0; + } + return ret; +# else + return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); +# endif /* __TIMESIZE == 64 */ +#endif /* __ASSUME_TIME64_SYSCALLS */ } + weak_alias (__clock_gettime, clock_gettime) libc_hidden_def (__clock_gettime)
Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- sysdeps/unix/sysv/linux/clock_gettime.c | 62 ++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-)