Message ID | d85f6611d45b6c7fea9e82ffcacde71e28625b49.1561421042.git.alistair.francis@wdc.com |
---|---|
State | New |
Headers | show |
Series | [RFC,v2,01/20] y2038: Introduce internal for glibc struct __timespec64 | expand |
There are quite a few style violations (here and in 08/20): braces on own line, but no braces for single statements; comment style without asterisks and no parens after functions; argument continuations to line up after the paren. Andreas.
On Tue, Jun 25, 2019 at 2:11 AM Alistair Francis <alistair.francis@wdc.com> wrote: > index f14ae565af..c2d6e2f766 100644 > --- a/sysdeps/unix/sysv/linux/nanosleep.c > +++ b/sysdeps/unix/sysv/linux/nanosleep.c > @@ -25,7 +25,19 @@ int > __nanosleep (const struct timespec *requested_time, > struct timespec *remaining) > { > + > +#ifdef __ASSUME_TIME64_SYSCALLS > + return SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0, > + requested_time, remaining); > +#else > +# ifdef __NR_clock_nanosleep_time64 > + long int ret = SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0, > + requested_time, remaining); > + if (ret == 0 || errno != ENOSYS) > + return ret; > +# endif > return SYSCALL_CANCEL (nanosleep, requested_time, remaining); > +#endif > } There has to be a type conversion in here somewhere: If timespec uses 32-bit time_t (on all existing 32-bit architectures), you must not pass it into __NR_clock_nanosleep_time64, while on builds with a 64-bit timespec you must not call nanosleep() without conversion. I suppose you need something like an internal __nanosleep64 (like your function above, but with the conversion added to the fallback path) and an internal __nanosleep32 (not calling clock_nanosleep_time64 or doing conversion). Architectures that have always had a 64-bit time_t don't need the latter of course. No idea how that fits into the rest of the glibc implementation. Arnd
On Tue, Jun 25, 2019 at 1:59 AM Arnd Bergmann <arnd@arndb.de> wrote: > > On Tue, Jun 25, 2019 at 2:11 AM Alistair Francis > <alistair.francis@wdc.com> wrote: > > > index f14ae565af..c2d6e2f766 100644 > > --- a/sysdeps/unix/sysv/linux/nanosleep.c > > +++ b/sysdeps/unix/sysv/linux/nanosleep.c > > @@ -25,7 +25,19 @@ int > > __nanosleep (const struct timespec *requested_time, > > struct timespec *remaining) > > { > > + > > +#ifdef __ASSUME_TIME64_SYSCALLS > > + return SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0, > > + requested_time, remaining); > > +#else > > +# ifdef __NR_clock_nanosleep_time64 > > + long int ret = SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0, > > + requested_time, remaining); > > + if (ret == 0 || errno != ENOSYS) > > + return ret; > > +# endif > > return SYSCALL_CANCEL (nanosleep, requested_time, remaining); > > +#endif > > } > > There has to be a type conversion in here somewhere: If timespec > uses 32-bit time_t (on all existing 32-bit architectures), you must not > pass it into __NR_clock_nanosleep_time64, while on builds with > a 64-bit timespec you must not call nanosleep() without conversion. > > I suppose you need something like an internal __nanosleep64 (like > your function above, but with the conversion added to the fallback > path) and an internal __nanosleep32 (not calling clock_nanosleep_time64 > or doing conversion). Architectures that have always had a 64-bit time_t > don't need the latter of course. Argh, this is a little messy but I think I have something working. Alistair > > No idea how that fits into the rest of the glibc implementation. > > Arnd
diff --git a/ChangeLog b/ChangeLog index 05291d7825..b90c5ab60c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2019-06-21 Alistair Francis <alistair.francis@wdc.com> + + * nptl/thrd_sleep.c: Use clock_nanosleep_time64 instead of nanosleep. + * sysdeps/unix/sysv/linux/nanosleep.c: Likewise. + * sysdeps/unix/sysv/linux/nanosleep_nocancel.c: Likewise. + 2019-06-20 Dmitry V. Levin <ldv@altlinux.org> Florian Weimer <fweimer@redhat.com> diff --git a/nptl/thrd_sleep.c b/nptl/thrd_sleep.c index 07a51808df..09f8c7159f 100644 --- a/nptl/thrd_sleep.c +++ b/nptl/thrd_sleep.c @@ -25,7 +25,24 @@ int thrd_sleep (const struct timespec* time_point, struct timespec* remaining) { INTERNAL_SYSCALL_DECL (err); - int ret = INTERNAL_SYSCALL_CANCEL (nanosleep, err, time_point, remaining); + int ret; + +#ifdef __ASSUME_TIME64_SYSCALLS + ret = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, + CLOCK_REALTIME, 0, time_point, remaining); +#else +# ifdef __NR_clock_nanosleep_time64 + long int ret_64 = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, + CLOCK_REALTIME, 0, time_point, remaining); + if (ret_64 == 0 || errno != ENOSYS) { + ret = ret_64; + } else { + ret = INTERNAL_SYSCALL_CANCEL (nanosleep, err, time_point, remaining); + } +# else + ret = INTERNAL_SYSCALL_CANCEL (nanosleep, err, time_point, remaining); +# endif +#endif if (INTERNAL_SYSCALL_ERROR_P (ret, err)) { /* C11 states thrd_sleep function returns -1 if it has been interrupted diff --git a/sysdeps/unix/sysv/linux/nanosleep.c b/sysdeps/unix/sysv/linux/nanosleep.c index f14ae565af..c2d6e2f766 100644 --- a/sysdeps/unix/sysv/linux/nanosleep.c +++ b/sysdeps/unix/sysv/linux/nanosleep.c @@ -25,7 +25,19 @@ int __nanosleep (const struct timespec *requested_time, struct timespec *remaining) { + +#ifdef __ASSUME_TIME64_SYSCALLS + return SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0, + requested_time, remaining); +#else +# ifdef __NR_clock_nanosleep_time64 + long int ret = SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0, + requested_time, remaining); + if (ret == 0 || errno != ENOSYS) + return ret; +# endif return SYSCALL_CANCEL (nanosleep, requested_time, remaining); +#endif } hidden_def (__nanosleep) weak_alias (__nanosleep, nanosleep) diff --git a/sysdeps/unix/sysv/linux/nanosleep_nocancel.c b/sysdeps/unix/sysv/linux/nanosleep_nocancel.c index 122ba627ff..f411a1c6c2 100644 --- a/sysdeps/unix/sysv/linux/nanosleep_nocancel.c +++ b/sysdeps/unix/sysv/linux/nanosleep_nocancel.c @@ -24,6 +24,17 @@ int __nanosleep_nocancel (const struct timespec *requested_time, struct timespec *remaining) { +#ifdef __ASSUME_TIME64_SYSCALLS + return INLINE_SYSCALL_CALL (clock_nanosleep_time64, CLOCK_REALTIME, 0, + requested_time, remaining); +#else +# ifdef __NR_clock_nanosleep_time64 + long int ret = INLINE_SYSCALL_CALL (clock_nanosleep_time64, CLOCK_REALTIME, 0, + requested_time, remaining); + if (ret == 0 || errno != ENOSYS) + return ret; +# endif return INLINE_SYSCALL_CALL (nanosleep, requested_time, remaining); +#endif } hidden_def (__nanosleep_nocancel)
The nanosleep syscall is not supported on newer 32-bit platforms (such as RV32). To fix this issue let's use clock_nanosleep_time64 if it is avaliable. Let's use CLOCK_REALTIME when calling clock_nanosleep_time64 as the Linux specification says: "POSIX.1 specifies that nanosleep() should measure time against the CLOCK_REALTIME clock. However, Linux measures the time using the CLOCK_MONOTONIC clock. This probably does not matter, since the POSIX.1 specification for clock_settime(2) says that discontinuous changes in CLOCK_REALTIME should not affect nanosleep()" Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- ChangeLog | 6 ++++++ nptl/thrd_sleep.c | 19 ++++++++++++++++++- sysdeps/unix/sysv/linux/nanosleep.c | 12 ++++++++++++ sysdeps/unix/sysv/linux/nanosleep_nocancel.c | 11 +++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-)