This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[RFC v5 02/21] sysdeps/nanosleep: Use clock_nanosleep_time64 if avaliable
- From: Alistair Francis <alistair dot francis at wdc dot com>
- To: libc-alpha at sourceware dot org
- Cc: arnd at arndb dot de, adhemerval dot zanella at linaro dot org, fweimer at redhat dot com, palmer at sifive dot com, macro at wdc dot com, zongbox at gmail dot com, alistair dot francis at wdc dot com, alistair23 at gmail dot com
- Date: Thu, 29 Aug 2019 09:50:05 -0700
- Subject: [RFC v5 02/21] sysdeps/nanosleep: Use clock_nanosleep_time64 if avaliable
- Ironport-sdr: cCxkEKolq6/T8bvOaPNBzeU6iobB1v3tTs32BXyUCVChe+0IoXIRDgpBQ5CeNWo889rh7rGjKB 2Tff1rv+1mGWKt54ZuiiMAXC3HSnMjWae91urVFADBb7Bcu7I799ki9LxlYogiI5+/Uk/ykese pGIaiRoPJm2TymkJ62jwJqmmiccbucS3ty0blRPUuq/dks2TZe7MMrJWT/6U7i+QZbGwyPgF5i jG9qWL09JPQwPmMlmCsHVqqt0JzZX33ZzfeiQZpW7sTlwwOnWtfk7Ac1nmmnZBEfawPHSbDjH0 E54=
- Ironport-sdr: IT39w0vCNzL5KcgTXU9M+VlmeHye5M/P4W4fNXoXhjPkGDGrQUEO9Z3Rs357GFie9FDTnT1H4a aZnlxeJajiqj04GsvPj4NbLpNJolmYRaIp9LgaXZxYnwR7xBocyiSS17S7DvNpR/xI70YEKCn5 7TVL/DGN1Othts5a8HLvNM7nkDODViw+XrPVnoLEgJwBthuEoCAxCvcg3EVDYYGo+nzZrigCnL wEepI2wobzxfchA2TWsl+xTxZT908mmf7k2b96Bd5CX6/TMkA6uUJnu3UMaMUQr6zZG+CL9Djm gMXEuov1QswqSJj0M66fhpq0
- Ironport-sdr: /ct55jVDfVqrKehMxc8cpaOuaBb3SJ5kNfRQ8GTjgBJG1tkkxRPIrBcO3Q89TMOV+WpO3JoHOP URrIjcktCN94fFNp4rELyktyT1BAgZQUpjeuFyOaQDb+aF6dnDHG1A2X12LOBSba0k49J7qrj+ JWSq7QnB1Nizq98sNg/f2hbfCfe9cpQ0eolMK1Vilq5PiYSq9ZX2TecWV70PBDQaZ75CkLAKTU hjdWTp4+Ln8bnjqYFXRwd1cxURo903F2gEonR6pvt9eZGP3WLPJyIyqfX60FsP+MilmVJj0QgZ fj8=
- References: <cover.1567097252.git.alistair.francis@wdc.com>
- Wdcironportexception: Internal
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>
* nptl/thrd_sleep.c: Use clock_nanosleep_time64 instead of nanosleep.
* sysdeps/unix/sysv/linux/nanosleep.c: Likewise.
* sysdeps/unix/sysv/linux/clock_nanosleep.c: Likewise.
* sysdeps/unix/sysv/linux/nanosleep_nocancel.c: Likewise.
---
include/time.h | 6 ++
nptl/thrd_sleep.c | 69 ++++++++++++++++--
sysdeps/unix/sysv/linux/clock_nanosleep.c | 74 ++++++++++++++++++--
sysdeps/unix/sysv/linux/nanosleep.c | 65 ++++++++++++++++-
sysdeps/unix/sysv/linux/nanosleep_nocancel.c | 64 ++++++++++++++++-
5 files changed, 264 insertions(+), 14 deletions(-)
diff --git a/include/time.h b/include/time.h
index 95b31429212..6d81f91384b 100644
--- a/include/time.h
+++ b/include/time.h
@@ -172,6 +172,12 @@ libc_hidden_proto (__difftime64)
extern double __difftime (time_t time1, time_t time0);
+#if __TIMESIZE == 64
+#define __thrd_sleep_time64 thrd_sleep
+#define __clock_nanosleep_time64 __clock_nanosleep
+#define __nanosleep_time64 __nanosleep
+#define __nanosleep_nocancel_time64 __nanosleep_nocancel
+#endif
/* Use in the clock_* functions. Size of the field representing the
actual clock ID. */
diff --git a/nptl/thrd_sleep.c b/nptl/thrd_sleep.c
index 07a51808df2..e85da561c68 100644
--- a/nptl/thrd_sleep.c
+++ b/nptl/thrd_sleep.c
@@ -22,18 +22,79 @@
#include "thrd_priv.h"
int
-thrd_sleep (const struct timespec* time_point, struct timespec* remaining)
+__thrd_sleep_time64 (const struct timespec* time_point, struct timespec* remaining)
{
INTERNAL_SYSCALL_DECL (err);
- int ret = INTERNAL_SYSCALL_CANCEL (nanosleep, err, time_point, remaining);
+ int ret = -1;
+
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_clock_nanosleep_time64
+# define __NR_clock_nanosleep_time64 __NR_clock_nanosleep
+# endif
+ ret = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, CLOCK_REALTIME,
+ 0, time_point, remaining);
+#else
+# ifdef __NR_clock_nanosleep_time64
+ long int ret_64;
+
+ ret_64 = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, CLOCK_REALTIME,
+ 0, time_point, remaining);
+
+ if (ret_64 == 0 || errno != ENOSYS)
+ ret = ret_64;
+# endif /* __NR_clock_nanosleep_time64 */
+ if (ret < 0)
+ {
+ struct timespec tp32, tr32;
+
+ if (! in_time_t_range (time_point->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ valid_timespec64_to_timespec (time_point, &tp32);
+ ret = INTERNAL_SYSCALL_CANCEL (nanosleep, err, &tp32, &tr32);
+
+ if ((ret == 0 || errno != ENOSYS) && remaining)
+ valid_timespec_to_timespec64(&tr32, remaining);
+ }
+#endif /* __ASSUME_TIME64_SYSCALLS */
+
if (INTERNAL_SYSCALL_ERROR_P (ret, err))
{
/* C11 states thrd_sleep function returns -1 if it has been interrupted
- by a signal, or a negative value if it fails. */
+ by a signal, or a negative value if it fails. */
ret = INTERNAL_SYSCALL_ERRNO (ret, err);
if (ret == EINTR)
- return -1;
+ return -1;
return -2;
}
return 0;
}
+
+#if __TIMESIZE != 64
+int
+thrd_sleep (const struct timespec* time_point, struct timespec* remaining)
+{
+ int ret;
+ timespec64 tp64, tr64;
+
+ valid_timespec_to_timespec64(time_point, &tp64);
+ ret = __thrd_sleep_time64 (&tp64, &tr64);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ if (! in_time_t_range (tr64->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ if (remaining)
+ valid_timespec64_to_timespec(&tr32, remaining);
+ }
+
+ return ret;
+}
+#endif
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 0cb6614dc92..64302fbcc69 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -21,13 +21,14 @@
#include <sysdep-cancel.h>
#include "kernel-posix-cpu-timers.h"
-
/* We can simply use the syscall. The CPU clocks are not supported
with this function. */
int
-__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
- struct timespec *rem)
+__clock_nanosleep_time64 (clockid_t clock_id, int flags, const struct timespec *req,
+ struct timespec *rem)
{
+ int r = -1;
+
if (clock_id == CLOCK_THREAD_CPUTIME_ID)
return EINVAL;
if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
@@ -36,9 +37,70 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
/* If the call is interrupted by a signal handler or encounters an error,
it returns a positive value similar to errno. */
INTERNAL_SYSCALL_DECL (err);
- int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, clock_id, flags,
- req, rem);
+
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_clock_nanosleep_time64
+# define __NR_clock_nanosleep_time64 __NR_clock_nanosleep
+# endif
+ r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
+ flags, req, rem);
+#else
+# ifdef __NR_clock_nanosleep_time64
+ long int ret_64;
+
+ ret_64 = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
+ flags, req, rem);
+
+ if (ret_64 == 0 || errno != ENOSYS)
+ r = ret_64;
+# endif /* __NR_clock_nanosleep_time64 */
+ if (r < 0)
+ {
+ struct timespec ts32, tr32;
+
+ if (! in_time_t_range (req->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ valid_timespec64_to_timespec (req, &ts32);
+ r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, &ts32, &tr32);
+
+ if ((r == 0 || errno != ENOSYS) && rem)
+ valid_timespec_to_timespec64(&tr32, rem);
+ }
+#endif /* __ASSUME_TIME64_SYSCALLS */
+
return (INTERNAL_SYSCALL_ERROR_P (r, err)
- ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
+ ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
}
+
+#if __TIMESIZE != 64
+int
+__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
+ struct timespec *rem)
+{
+ int r;
+ timespec64 treq64, trem64;
+
+ valid_timespec_to_timespec64(req, &treq64)
+ r = __clock_nanosleep_time64 (clock_id, flags, &treq64, &trem64);
+
+ if (r == 0 || errno != ENOSYS)
+ {
+ if (! in_time_t_range (trem64->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ if (remaining)
+ valid_timespec64_to_timespec(&tr32, remaining);
+ }
+
+ return r;
+}
+#endif
+
weak_alias (__clock_nanosleep, clock_nanosleep)
diff --git a/sysdeps/unix/sysv/linux/nanosleep.c b/sysdeps/unix/sysv/linux/nanosleep.c
index f14ae565af5..9a8dd5a4b82 100644
--- a/sysdeps/unix/sysv/linux/nanosleep.c
+++ b/sysdeps/unix/sysv/linux/nanosleep.c
@@ -22,10 +22,71 @@
/* Pause execution for a number of nanoseconds. */
int
+__nanosleep_time64 (const struct timespec *requested_time,
+ struct timespec *remaining)
+{
+#if defined(__ASSUME_TIME64_SYSCALLS)
+# ifndef __NR_clock_nanosleep_time64
+# define __NR_clock_nanosleep_time64 __NR_clock_nanosleep
+# endif
+ return SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0,
+ requested_time, remaining);
+#else
+# ifdef __NR_clock_nanosleep_time64
+ long int ret_64;
+
+ ret_64 = SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0,
+ requested_time, remaining);
+
+ if (ret_64 == 0 || errno != ENOSYS)
+ return ret_64;
+# endif /* __NR_clock_nanosleep_time64 */
+ int ret;
+ struct timespec ts32, tr32;
+
+ if (! in_time_t_range (requested_time->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ valid_timespec64_to_timespec (requested_time, &ts32);
+ ret = SYSCALL_CANCEL (nanosleep, &ts32, &tr32);
+
+ if ((ret == 0 || errno != ENOSYS) && remaining)
+ valid_timespec_to_timespec64(&tr32, remaining);
+
+ return ret;
+#endif /* __ASSUME_TIME64_SYSCALLS */
+}
+
+#if __TIMESIZE != 64
+int
__nanosleep (const struct timespec *requested_time,
- struct timespec *remaining)
+ struct timespec *remaining)
{
- return SYSCALL_CANCEL (nanosleep, requested_time, remaining);
+ int r;
+ timespec64 treq64, trem64;
+
+
+ valid_timespec_to_timespec64(req, &treq64);
+ r = __nanosleep_time64 (&treq64, &trem64);
+
+ if (r == 0 || errno != ENOSYS)
+ {
+ if (! in_time_t_range (trem64->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ if (remaining)
+ valid_timespec64_to_timespec(&tr32, remaining);
+ }
+
+ return r;
}
+#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 122ba627ff3..03f5be2ff9e 100644
--- a/sysdeps/unix/sysv/linux/nanosleep_nocancel.c
+++ b/sysdeps/unix/sysv/linux/nanosleep_nocancel.c
@@ -20,10 +20,70 @@
#include <sysdep-cancel.h>
#include <not-cancel.h>
+int
+__nanosleep_nocancel_time64 (const struct timespec *requested_time,
+ struct timespec *remaining)
+{
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_clock_nanosleep_time64
+# define __NR_clock_nanosleep_time64 __NR_clock_nanosleep
+# endif
+ return INLINE_SYSCALL_CALL (clock_nanosleep_time64, CLOCK_REALTIME, 0,
+ requested_time, remaining);
+#else
+# ifdef __NR_clock_nanosleep_time64
+ long int ret_64;
+
+ ret_64 = INLINE_SYSCALL_CALL (clock_nanosleep_time64, CLOCK_REALTIME, 0,
+ requested_time, remaining);
+
+ if (ret_64 == 0 || errno != ENOSYS)
+ return ret_64;
+# endif /* __NR_clock_nanosleep_time64 */
+ int ret;
+ struct timespec ts32, tr32;
+
+ if (! in_time_t_range (requested_time->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ valid_timespec64_to_timespec (requested_time, &ts32);
+ ret = INLINE_SYSCALL_CALL (nanosleep, &ts32, &tr32);
+
+ if (ret == 0 || errno != ENOSYS)
+ valid_timespec_to_timespec64(&tr32, remaining);
+
+ return ret;
+#endif /* __ASSUME_TIME64_SYSCALLS */
+}
+
+#if __TIMESIZE != 64
int
__nanosleep_nocancel (const struct timespec *requested_time,
- struct timespec *remaining)
+ struct timespec *remaining)
{
- return INLINE_SYSCALL_CALL (nanosleep, requested_time, remaining);
+ int ret;
+ timespec64 treq64, trem64;
+
+ valid_timespec_to_timespec64(req, &treq64)
+ ret = __nanosleep_nocancel_time64 (&treq64, &trem64);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ if (! in_time_t_range (trem64->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ if (remaining)
+ valid_timespec64_to_timespec(&tr32, remaining);
+ }
+
+ return ret;
}
+#endif
+
hidden_def (__nanosleep_nocancel)
--
2.22.0