Message ID | 20210617115104.1359598-19-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | More y2038 fixes | expand |
Hi Adhemerval, > For !__ASSUME_TIME64_SYSCALLS there is no need to issue a 64-bit > syscall if the provided timeout fits in a 32-bit one. The 64-bit > usage should be rare since the timeout is a relative one. I'm not sure if the above description is correct. As fair as I understand this patch set - we check if timeout fits into 32-bit if: - We want to use legacy (32 bit) syscall when __ASSUME_TIME64_SYSCALLS is not defined to avoid calling syscalls twice. The problem with relative 64 bit timeouts will be apparent after we pass Y2038 year threshold. > > Checked on i686-linux-gnu on a 4.15 kernel and on a 5.11 kernel > (with and without --enable-kernel=5.1) and on x86_64-linux-gnu. > --- > sysdeps/unix/sysv/linux/clock_nanosleep.c | 47 > +++++++++++++---------- time/Makefile | > 9 +++++ time/tst-clock_nanosleep.c | 40 > +++++++++++-------- 3 files changed, 60 insertions(+), 36 deletions(-) > > diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c > b/sysdeps/unix/sysv/linux/clock_nanosleep.c index > 007f1736cb..46b0f1e269 100644 --- > a/sysdeps/unix/sysv/linux/clock_nanosleep.c +++ > b/sysdeps/unix/sysv/linux/clock_nanosleep.c @@ -27,8 +27,9 @@ > /* We can simply use the syscall. The CPU clocks are not supported > with this function. */ > int > -__clock_nanosleep_time64 (clockid_t clock_id, int flags, const > struct __timespec64 *req, > - struct __timespec64 *rem) > +__clock_nanosleep_time64 (clockid_t clock_id, int flags, > + const struct __timespec64 *req, > + struct __timespec64 *rem) > { > if (clock_id == CLOCK_THREAD_CPUTIME_ID) > return EINVAL; > @@ -37,33 +38,37 @@ __clock_nanosleep_time64 (clockid_t clock_id, int > flags, const struct __timespec > /* If the call is interrupted by a signal handler or encounters an > error, it returns a positive value similar to errno. */ > + > #ifndef __NR_clock_nanosleep_time64 > # define __NR_clock_nanosleep_time64 __NR_clock_nanosleep > #endif > - int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, > - flags, req, rem); > - > -#ifndef __ASSUME_TIME64_SYSCALLS > - if (r == 0 || r != -ENOSYS) > - return -r; > > - if (! in_time_t_range (req->tv_sec)) > + int r; > +#ifdef __ASSUME_TIME64_SYSCALLS > + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, > flags, req, > + rem); > +#else > + bool is32bit = in_time_t_range (req->tv_sec); > + if (!is32bit) > { > - __set_errno (EOVERFLOW); > - return -1; > + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, > flags, > + req, rem); > + if (r == -ENOSYS) > + r = -EOVERFLOW; > } > - > - struct timespec tr32; > - struct timespec ts32 = valid_timespec64_to_timespec (*req); > - r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, clock_id, flags, > - &ts32, &tr32); > - if (INTERNAL_SYSCALL_ERROR_P (r)) > + else > { > - if (r == -EINTR && rem != NULL && (flags & TIMER_ABSTIME) == 0) > - *rem = valid_timespec_to_timespec64 (tr32); > + struct timespec tr32; > + struct timespec ts32 = valid_timespec64_to_timespec (*req); > + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, clock_id, flags, > &ts32, > + &tr32); > + if (INTERNAL_SYSCALL_ERROR_P (r)) > + { > + if (r == -EINTR && rem != NULL && (flags & TIMER_ABSTIME) > == 0) > + *rem = valid_timespec_to_timespec64 (tr32); > + } > } > -#endif /* __ASSUME_TIME64_SYSCALLS */ > - > +#endif > return -r; > } > > diff --git a/time/Makefile b/time/Makefile > index c84bd5d3ec..0bea84966c 100644 > --- a/time/Makefile > +++ b/time/Makefile > @@ -86,6 +86,15 @@ $(objpfx)tst-strftime2.out: $(gen-locales) > $(objpfx)tst-strftime3.out: $(gen-locales) > endif > > +ifeq (yes,$(build-shared)) > +librt = $(common-objpfx)rt/librt.so > +else > +librt = $(common-objpfx)rt/librt.a > +endif > + > +$(objpfx)tst-clock_nanosleep: $(librt) > +$(objpfx)tst-clock_nanosleep-time64: $(librt) > + > tz-cflags = -DTZDIR='"$(zonedir)"' \ > -DTZDEFAULT='"$(localtime-file)"' \ > -DTZDEFRULES='"$(posixrules-file)"' > diff --git a/time/tst-clock_nanosleep.c b/time/tst-clock_nanosleep.c > index 47537435c1..a5a7f9430a 100644 > --- a/time/tst-clock_nanosleep.c > +++ b/time/tst-clock_nanosleep.c > @@ -20,38 +20,48 @@ > #include <unistd.h> > #include <sys/time.h> > #include <time.h> > - > +#include <intprops.h> > +#include <support/support.h> > +#include <support/check.h> > > /* Test that clock_nanosleep() does sleep. */ > -static int > -do_test (void) > +static void > +clock_nanosleep_test (void) > { > /* Current time. */ > struct timeval tv1; > - (void) gettimeofday (&tv1, NULL); > + gettimeofday (&tv1, NULL); > > - struct timespec ts; > - ts.tv_sec = 1; > - ts.tv_nsec = 0; > + struct timespec ts = { 1, 0 }; > TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts)); > > /* At least one second must have passed. */ > struct timeval tv2; > - (void) gettimeofday (&tv2, NULL); > + gettimeofday (&tv2, NULL); > > tv2.tv_sec -= tv1.tv_sec; > tv2.tv_usec -= tv1.tv_usec; > if (tv2.tv_usec < 0) > --tv2.tv_sec; > > - if (tv2.tv_sec < 1) > - { > - puts ("clock_nanosleep didn't sleep long enough"); > - return 1; > - } > + TEST_VERIFY (tv2.tv_sec >= 1); > +} > + > +static void > +clock_nanosleep_large_timeout (void) > +{ Please correct me if I'm wrong: > + support_create_timer (0, 100000000, false, NULL); You create timer with 100ms timeout > + struct timespec ts = { TYPE_MAXIMUM (time_t), 0 }; ts is created to have maximal value for time_t seconds. > + int r = clock_nanosleep (CLOCK_REALTIME, 0, &ts, NULL); The clock_nanosleep is called (64 or 32 bit version - with proper in-glibc aliasing). > + TEST_VERIFY (r == EINTR || r == EOVERFLOW); We check if: - return is EOVERFLOW - this means that we want to use 64 bit time on machine which is only supporting 64 bit time. - return is EINTR - as the timer's (introduced in the earlier patch in this set) alarm triggers. Am I right that this check is to find out if the syscall is correctly executed by the kernel? Or is there any other issue? > +} > > +static int > +do_test (void) > +{ > + clock_nanosleep_test (); > + clock_nanosleep_large_timeout (); > return 0; > } > > -#define TEST_FUNCTION do_test () > -#include "../test-skeleton.c" > +#include <support/test-driver.c> Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
On 17/06/2021 12:11, Lukasz Majewski wrote: > Hi Adhemerval, > >> For !__ASSUME_TIME64_SYSCALLS there is no need to issue a 64-bit >> syscall if the provided timeout fits in a 32-bit one. The 64-bit >> usage should be rare since the timeout is a relative one. > > I'm not sure if the above description is correct. > > As fair as I understand this patch set - we check if timeout fits into > 32-bit if: > > - We want to use legacy (32 bit) syscall when __ASSUME_TIME64_SYSCALLS > is not defined to avoid calling syscalls twice. > > The problem with relative 64 bit timeouts will be apparent after we > pass Y2038 year threshold. Yes, but 64-bit relative timeout means that caller is passing a *very* large timeout. It is possible indeed, but I don't think it the usual way. > >> >> Checked on i686-linux-gnu on a 4.15 kernel and on a 5.11 kernel >> (with and without --enable-kernel=5.1) and on x86_64-linux-gnu. >> --- >> sysdeps/unix/sysv/linux/clock_nanosleep.c | 47 >> +++++++++++++---------- time/Makefile | >> 9 +++++ time/tst-clock_nanosleep.c | 40 >> +++++++++++-------- 3 files changed, 60 insertions(+), 36 deletions(-) >> >> diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c >> b/sysdeps/unix/sysv/linux/clock_nanosleep.c index >> 007f1736cb..46b0f1e269 100644 --- >> a/sysdeps/unix/sysv/linux/clock_nanosleep.c +++ >> b/sysdeps/unix/sysv/linux/clock_nanosleep.c @@ -27,8 +27,9 @@ >> /* We can simply use the syscall. The CPU clocks are not supported >> with this function. */ >> int >> -__clock_nanosleep_time64 (clockid_t clock_id, int flags, const >> struct __timespec64 *req, >> - struct __timespec64 *rem) >> +__clock_nanosleep_time64 (clockid_t clock_id, int flags, >> + const struct __timespec64 *req, >> + struct __timespec64 *rem) >> { >> if (clock_id == CLOCK_THREAD_CPUTIME_ID) >> return EINVAL; >> @@ -37,33 +38,37 @@ __clock_nanosleep_time64 (clockid_t clock_id, int >> flags, const struct __timespec >> /* If the call is interrupted by a signal handler or encounters an >> error, it returns a positive value similar to errno. */ >> + >> #ifndef __NR_clock_nanosleep_time64 >> # define __NR_clock_nanosleep_time64 __NR_clock_nanosleep >> #endif >> - int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, >> - flags, req, rem); >> - >> -#ifndef __ASSUME_TIME64_SYSCALLS >> - if (r == 0 || r != -ENOSYS) >> - return -r; >> >> - if (! in_time_t_range (req->tv_sec)) >> + int r; >> +#ifdef __ASSUME_TIME64_SYSCALLS >> + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, >> flags, req, >> + rem); >> +#else >> + bool is32bit = in_time_t_range (req->tv_sec); >> + if (!is32bit) >> { >> - __set_errno (EOVERFLOW); >> - return -1; >> + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, >> flags, >> + req, rem); >> + if (r == -ENOSYS) >> + r = -EOVERFLOW; >> } >> - >> - struct timespec tr32; >> - struct timespec ts32 = valid_timespec64_to_timespec (*req); >> - r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, clock_id, flags, >> - &ts32, &tr32); >> - if (INTERNAL_SYSCALL_ERROR_P (r)) >> + else >> { >> - if (r == -EINTR && rem != NULL && (flags & TIMER_ABSTIME) == 0) >> - *rem = valid_timespec_to_timespec64 (tr32); >> + struct timespec tr32; >> + struct timespec ts32 = valid_timespec64_to_timespec (*req); >> + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, clock_id, flags, >> &ts32, >> + &tr32); >> + if (INTERNAL_SYSCALL_ERROR_P (r)) >> + { >> + if (r == -EINTR && rem != NULL && (flags & TIMER_ABSTIME) >> == 0) >> + *rem = valid_timespec_to_timespec64 (tr32); >> + } >> } >> -#endif /* __ASSUME_TIME64_SYSCALLS */ >> - >> +#endif >> return -r; >> } >> >> diff --git a/time/Makefile b/time/Makefile >> index c84bd5d3ec..0bea84966c 100644 >> --- a/time/Makefile >> +++ b/time/Makefile >> @@ -86,6 +86,15 @@ $(objpfx)tst-strftime2.out: $(gen-locales) >> $(objpfx)tst-strftime3.out: $(gen-locales) >> endif >> >> +ifeq (yes,$(build-shared)) >> +librt = $(common-objpfx)rt/librt.so >> +else >> +librt = $(common-objpfx)rt/librt.a >> +endif >> + >> +$(objpfx)tst-clock_nanosleep: $(librt) >> +$(objpfx)tst-clock_nanosleep-time64: $(librt) >> + >> tz-cflags = -DTZDIR='"$(zonedir)"' \ >> -DTZDEFAULT='"$(localtime-file)"' \ >> -DTZDEFRULES='"$(posixrules-file)"' >> diff --git a/time/tst-clock_nanosleep.c b/time/tst-clock_nanosleep.c >> index 47537435c1..a5a7f9430a 100644 >> --- a/time/tst-clock_nanosleep.c >> +++ b/time/tst-clock_nanosleep.c >> @@ -20,38 +20,48 @@ >> #include <unistd.h> >> #include <sys/time.h> >> #include <time.h> >> - >> +#include <intprops.h> >> +#include <support/support.h> >> +#include <support/check.h> >> >> /* Test that clock_nanosleep() does sleep. */ >> -static int >> -do_test (void) >> +static void >> +clock_nanosleep_test (void) >> { >> /* Current time. */ >> struct timeval tv1; >> - (void) gettimeofday (&tv1, NULL); >> + gettimeofday (&tv1, NULL); >> >> - struct timespec ts; >> - ts.tv_sec = 1; >> - ts.tv_nsec = 0; >> + struct timespec ts = { 1, 0 }; >> TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts)); >> >> /* At least one second must have passed. */ >> struct timeval tv2; >> - (void) gettimeofday (&tv2, NULL); >> + gettimeofday (&tv2, NULL); >> >> tv2.tv_sec -= tv1.tv_sec; >> tv2.tv_usec -= tv1.tv_usec; >> if (tv2.tv_usec < 0) >> --tv2.tv_sec; >> >> - if (tv2.tv_sec < 1) >> - { >> - puts ("clock_nanosleep didn't sleep long enough"); >> - return 1; >> - } >> + TEST_VERIFY (tv2.tv_sec >= 1); >> +} >> + >> +static void >> +clock_nanosleep_large_timeout (void) >> +{ > > Please correct me if I'm wrong: > >> + support_create_timer (0, 100000000, false, NULL); > > You create timer with 100ms timeout > >> + struct timespec ts = { TYPE_MAXIMUM (time_t), 0 }; > > ts is created to have maximal value for time_t seconds. > >> + int r = clock_nanosleep (CLOCK_REALTIME, 0, &ts, NULL); > > The clock_nanosleep is called (64 or 32 bit version - with proper > in-glibc aliasing). > >> + TEST_VERIFY (r == EINTR || r == EOVERFLOW); > > We check if: > > - return is EOVERFLOW - this means that we want to use 64 bit time on > machine which is only supporting 64 bit time. We want to use a 64-bit relative timeout on a machine where __NR_clock_nanosleep_time64 failed with ENOSYS, meaning a pre v5.1 kernel without 64-bit time_t support. > > - return is EINTR - as the timer's (introduced in the earlier patch in > this set) alarm triggers. Am I right that this check is to find out > if the syscall is correctly executed by the kernel? Yes, the EINTR means that syscall was interrupted by the alarm. > > Or is there any other issue? I think these are the two possible situations. > >> +} >> >> +static int >> +do_test (void) >> +{ >> + clock_nanosleep_test (); >> + clock_nanosleep_large_timeout (); >> return 0; >> } >> >> -#define TEST_FUNCTION do_test () >> -#include "../test-skeleton.c" >> +#include <support/test-driver.c> > > > > Best regards, > > Lukasz Majewski > > -- > > DENX Software Engineering GmbH, Managing Director: Wolfgang Denk > HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany > Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de >
On Thu, 17 Jun 2021 08:51:04 -0300 Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote: > For !__ASSUME_TIME64_SYSCALLS there is no need to issue a 64-bit > syscall if the provided timeout fits in a 32-bit one. The 64-bit > usage should be rare since the timeout is a relative one. > > Checked on i686-linux-gnu on a 4.15 kernel and on a 5.11 kernel > (with and without --enable-kernel=5.1) and on x86_64-linux-gnu. > --- > sysdeps/unix/sysv/linux/clock_nanosleep.c | 47 > +++++++++++++---------- time/Makefile | > 9 +++++ time/tst-clock_nanosleep.c | 40 > +++++++++++-------- 3 files changed, 60 insertions(+), 36 deletions(-) > > diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c > b/sysdeps/unix/sysv/linux/clock_nanosleep.c index > 007f1736cb..46b0f1e269 100644 --- > a/sysdeps/unix/sysv/linux/clock_nanosleep.c +++ > b/sysdeps/unix/sysv/linux/clock_nanosleep.c @@ -27,8 +27,9 @@ > /* We can simply use the syscall. The CPU clocks are not supported > with this function. */ > int > -__clock_nanosleep_time64 (clockid_t clock_id, int flags, const > struct __timespec64 *req, > - struct __timespec64 *rem) > +__clock_nanosleep_time64 (clockid_t clock_id, int flags, > + const struct __timespec64 *req, > + struct __timespec64 *rem) > { > if (clock_id == CLOCK_THREAD_CPUTIME_ID) > return EINVAL; > @@ -37,33 +38,37 @@ __clock_nanosleep_time64 (clockid_t clock_id, int > flags, const struct __timespec > /* If the call is interrupted by a signal handler or encounters an > error, it returns a positive value similar to errno. */ > + > #ifndef __NR_clock_nanosleep_time64 > # define __NR_clock_nanosleep_time64 __NR_clock_nanosleep > #endif > - int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, > - flags, req, rem); > - > -#ifndef __ASSUME_TIME64_SYSCALLS > - if (r == 0 || r != -ENOSYS) > - return -r; > > - if (! in_time_t_range (req->tv_sec)) > + int r; > +#ifdef __ASSUME_TIME64_SYSCALLS > + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, > flags, req, > + rem); > +#else > + bool is32bit = in_time_t_range (req->tv_sec); > + if (!is32bit) > { > - __set_errno (EOVERFLOW); > - return -1; > + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, > flags, > + req, rem); > + if (r == -ENOSYS) > + r = -EOVERFLOW; > } > - > - struct timespec tr32; > - struct timespec ts32 = valid_timespec64_to_timespec (*req); > - r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, clock_id, flags, > - &ts32, &tr32); > - if (INTERNAL_SYSCALL_ERROR_P (r)) > + else > { > - if (r == -EINTR && rem != NULL && (flags & TIMER_ABSTIME) == 0) > - *rem = valid_timespec_to_timespec64 (tr32); > + struct timespec tr32; > + struct timespec ts32 = valid_timespec64_to_timespec (*req); > + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, clock_id, flags, > &ts32, > + &tr32); > + if (INTERNAL_SYSCALL_ERROR_P (r)) > + { > + if (r == -EINTR && rem != NULL && (flags & TIMER_ABSTIME) > == 0) > + *rem = valid_timespec_to_timespec64 (tr32); > + } > } > -#endif /* __ASSUME_TIME64_SYSCALLS */ > - > +#endif > return -r; > } > > diff --git a/time/Makefile b/time/Makefile > index c84bd5d3ec..0bea84966c 100644 > --- a/time/Makefile > +++ b/time/Makefile > @@ -86,6 +86,15 @@ $(objpfx)tst-strftime2.out: $(gen-locales) > $(objpfx)tst-strftime3.out: $(gen-locales) > endif > > +ifeq (yes,$(build-shared)) > +librt = $(common-objpfx)rt/librt.so > +else > +librt = $(common-objpfx)rt/librt.a > +endif > + > +$(objpfx)tst-clock_nanosleep: $(librt) > +$(objpfx)tst-clock_nanosleep-time64: $(librt) > + > tz-cflags = -DTZDIR='"$(zonedir)"' \ > -DTZDEFAULT='"$(localtime-file)"' \ > -DTZDEFRULES='"$(posixrules-file)"' > diff --git a/time/tst-clock_nanosleep.c b/time/tst-clock_nanosleep.c > index 47537435c1..a5a7f9430a 100644 > --- a/time/tst-clock_nanosleep.c > +++ b/time/tst-clock_nanosleep.c > @@ -20,38 +20,48 @@ > #include <unistd.h> > #include <sys/time.h> > #include <time.h> > - > +#include <intprops.h> > +#include <support/support.h> > +#include <support/check.h> > > /* Test that clock_nanosleep() does sleep. */ > -static int > -do_test (void) > +static void > +clock_nanosleep_test (void) > { > /* Current time. */ > struct timeval tv1; > - (void) gettimeofday (&tv1, NULL); > + gettimeofday (&tv1, NULL); > > - struct timespec ts; > - ts.tv_sec = 1; > - ts.tv_nsec = 0; > + struct timespec ts = { 1, 0 }; > TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts)); > > /* At least one second must have passed. */ > struct timeval tv2; > - (void) gettimeofday (&tv2, NULL); > + gettimeofday (&tv2, NULL); > > tv2.tv_sec -= tv1.tv_sec; > tv2.tv_usec -= tv1.tv_usec; > if (tv2.tv_usec < 0) > --tv2.tv_sec; > > - if (tv2.tv_sec < 1) > - { > - puts ("clock_nanosleep didn't sleep long enough"); > - return 1; > - } > + TEST_VERIFY (tv2.tv_sec >= 1); > +} > + > +static void > +clock_nanosleep_large_timeout (void) > +{ > + support_create_timer (0, 100000000, false, NULL); > + struct timespec ts = { TYPE_MAXIMUM (time_t), 0 }; > + int r = clock_nanosleep (CLOCK_REALTIME, 0, &ts, NULL); > + TEST_VERIFY (r == EINTR || r == EOVERFLOW); > +} > > +static int > +do_test (void) > +{ > + clock_nanosleep_test (); > + clock_nanosleep_large_timeout (); > return 0; > } > > -#define TEST_FUNCTION do_test () > -#include "../test-skeleton.c" > +#include <support/test-driver.c> Reviewed-by: Lukasz Majewski <lukma@denx.de> Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c index 007f1736cb..46b0f1e269 100644 --- a/sysdeps/unix/sysv/linux/clock_nanosleep.c +++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c @@ -27,8 +27,9 @@ /* We can simply use the syscall. The CPU clocks are not supported with this function. */ int -__clock_nanosleep_time64 (clockid_t clock_id, int flags, const struct __timespec64 *req, - struct __timespec64 *rem) +__clock_nanosleep_time64 (clockid_t clock_id, int flags, + const struct __timespec64 *req, + struct __timespec64 *rem) { if (clock_id == CLOCK_THREAD_CPUTIME_ID) return EINVAL; @@ -37,33 +38,37 @@ __clock_nanosleep_time64 (clockid_t clock_id, int flags, const struct __timespec /* If the call is interrupted by a signal handler or encounters an error, it returns a positive value similar to errno. */ + #ifndef __NR_clock_nanosleep_time64 # define __NR_clock_nanosleep_time64 __NR_clock_nanosleep #endif - int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, - flags, req, rem); - -#ifndef __ASSUME_TIME64_SYSCALLS - if (r == 0 || r != -ENOSYS) - return -r; - if (! in_time_t_range (req->tv_sec)) + int r; +#ifdef __ASSUME_TIME64_SYSCALLS + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, flags, req, + rem); +#else + bool is32bit = in_time_t_range (req->tv_sec); + if (!is32bit) { - __set_errno (EOVERFLOW); - return -1; + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, flags, + req, rem); + if (r == -ENOSYS) + r = -EOVERFLOW; } - - struct timespec tr32; - struct timespec ts32 = valid_timespec64_to_timespec (*req); - r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, clock_id, flags, - &ts32, &tr32); - if (INTERNAL_SYSCALL_ERROR_P (r)) + else { - if (r == -EINTR && rem != NULL && (flags & TIMER_ABSTIME) == 0) - *rem = valid_timespec_to_timespec64 (tr32); + struct timespec tr32; + struct timespec ts32 = valid_timespec64_to_timespec (*req); + r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, clock_id, flags, &ts32, + &tr32); + if (INTERNAL_SYSCALL_ERROR_P (r)) + { + if (r == -EINTR && rem != NULL && (flags & TIMER_ABSTIME) == 0) + *rem = valid_timespec_to_timespec64 (tr32); + } } -#endif /* __ASSUME_TIME64_SYSCALLS */ - +#endif return -r; } diff --git a/time/Makefile b/time/Makefile index c84bd5d3ec..0bea84966c 100644 --- a/time/Makefile +++ b/time/Makefile @@ -86,6 +86,15 @@ $(objpfx)tst-strftime2.out: $(gen-locales) $(objpfx)tst-strftime3.out: $(gen-locales) endif +ifeq (yes,$(build-shared)) +librt = $(common-objpfx)rt/librt.so +else +librt = $(common-objpfx)rt/librt.a +endif + +$(objpfx)tst-clock_nanosleep: $(librt) +$(objpfx)tst-clock_nanosleep-time64: $(librt) + tz-cflags = -DTZDIR='"$(zonedir)"' \ -DTZDEFAULT='"$(localtime-file)"' \ -DTZDEFRULES='"$(posixrules-file)"' diff --git a/time/tst-clock_nanosleep.c b/time/tst-clock_nanosleep.c index 47537435c1..a5a7f9430a 100644 --- a/time/tst-clock_nanosleep.c +++ b/time/tst-clock_nanosleep.c @@ -20,38 +20,48 @@ #include <unistd.h> #include <sys/time.h> #include <time.h> - +#include <intprops.h> +#include <support/support.h> +#include <support/check.h> /* Test that clock_nanosleep() does sleep. */ -static int -do_test (void) +static void +clock_nanosleep_test (void) { /* Current time. */ struct timeval tv1; - (void) gettimeofday (&tv1, NULL); + gettimeofday (&tv1, NULL); - struct timespec ts; - ts.tv_sec = 1; - ts.tv_nsec = 0; + struct timespec ts = { 1, 0 }; TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts)); /* At least one second must have passed. */ struct timeval tv2; - (void) gettimeofday (&tv2, NULL); + gettimeofday (&tv2, NULL); tv2.tv_sec -= tv1.tv_sec; tv2.tv_usec -= tv1.tv_usec; if (tv2.tv_usec < 0) --tv2.tv_sec; - if (tv2.tv_sec < 1) - { - puts ("clock_nanosleep didn't sleep long enough"); - return 1; - } + TEST_VERIFY (tv2.tv_sec >= 1); +} + +static void +clock_nanosleep_large_timeout (void) +{ + support_create_timer (0, 100000000, false, NULL); + struct timespec ts = { TYPE_MAXIMUM (time_t), 0 }; + int r = clock_nanosleep (CLOCK_REALTIME, 0, &ts, NULL); + TEST_VERIFY (r == EINTR || r == EOVERFLOW); +} +static int +do_test (void) +{ + clock_nanosleep_test (); + clock_nanosleep_large_timeout (); return 0; } -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" +#include <support/test-driver.c>