This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[RFC v4 02/24] 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: Fri, 9 Aug 2019 17:59:52 -0700
- Subject: [RFC v4 02/24] sysdeps/nanosleep: Use clock_nanosleep_time64 if avaliable
- Ironport-sdr: 5ihonVjfitLuq1jomkW6UL8XOF5gAmi/+OCjn+GA2VjtbEujmivg3O5cWqsxTLHc6KXEFqLlCH YcwnyDYpMplzqnNQoU02QodhjYQpBTw7gwKdS8famnZIZEtzkhCLVqJXqGFnEscDAx0/vgY87U xoHdmp5m/ExzeyALCa1FUNtse29lN9395VMdFTYuOL5t3Rq6jCgXOkefCoDG30RfGluVEh7hO3 7t77pLM87sook/yjTqosOdPVC+SksiZu5+7cCdgkJDRgHxeNpSPk7SiBC0DYjBNVNPjnUAyKgg AEs=
- Ironport-sdr: vhNt/eH6wK2o96QZKjFLUKqi51I/L5rk1GpKVJp5qg0lHvSKN3+3Ll7ItvbkZhvEMGJ9S9R7+o oOi1OiBxJVBbDXGB/RI87fslwStxOUNFApWRNIqujiH8NpWhgt/JojMh0aCWSOsZ9KEegqwwKf 1LntC/bG4YtXeEgFUOimVRlol9UEbF1iXM3dRzYbSi9ZHOh5IG56N/3ovjGL5n9kY7DBdonKHu 3JtP4bqYdF+tgu/yubUMLJVxna81VZhSACgNpdhYhWusXIDz+/rUeWWY9Duy2p+xY6ONWfERzO gtjRTM1j1u1dYD8Jfey5t/Qo
- Ironport-sdr: NctYj1TZCyBM8sOjT+7zdh1PSrj4igi3R5jkWhC8ivP6CDroeDCuRv1X5m5nZFrMDJgHR33rfl WeXB6NMN0txMmH0bUxr0jMDWrbnIey52beWKTIr5zE6FB/VKNxKGShHwX7KLFAbqphrk8KK/q5 ryUyOzHB7HjifkuHdff9qmVg9//+Lbhh/0DpCNUt2l4/hrKkQexe4FaF2jh9OVd8Ux20zuL4Gl FQBJrgiZPJFF5Qsi0mCDMED77Aq/3fC/vB2ns/IE/HatuzOxpogIVB5LANQh4i9/jpyqwT9qCH 878=
- References: <cover.1565398513.git.alistair.francis@wdc.com>
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()"
NOTE: We don't convert the struct timespec* remaining to a 64-bit value,
we need to kernel to provide __NR_clock_nanosleep_time64 and __TIMESIZE == 64
to get a 64bit timespec.
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
ChangeLog | 6 ++
nptl/thrd_sleep.c | 60 +++++++++++++++-
sysdeps/unix/sysv/linux/clock_nanosleep.c | 61 +++++++++++++++-
sysdeps/unix/sysv/linux/nanosleep.c | 75 ++++++++++++++++++++
sysdeps/unix/sysv/linux/nanosleep_nocancel.c | 47 ++++++++++++
5 files changed, 243 insertions(+), 6 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index a8186db3944..aab4469b3d4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1419,6 +1419,12 @@
* support/xtime.h: Add xclock_now() helper function.
+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 07a51808df2..fc495b56c67 100644
--- a/nptl/thrd_sleep.c
+++ b/nptl/thrd_sleep.c
@@ -25,14 +25,68 @@ 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 = -1;
+
+#ifdef __ASSUME_TIME64_SYSCALLS
+ ret = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, CLOCK_REALTIME,
+ 0, time_point, remaining);
+#else
+# ifdef __NR_clock_nanosleep_time64
+# if __TIMESIZE == 64
+ 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;
+# else
+ timespec64 ts64;
+
+ ret = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err,
+ CLOCK_REALTIME, 0, time_point,
+ ts64);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ remaining->tv_sec = ts64.tv_sec;
+ remaining->tv_nsec = ts64.tv_nsec;
+ }
+# endif /* __TIMESIZE == 64 */
+# endif /* __NR_clock_nanosleep_time64 */
+# if __TIMESIZE == 64
+ if (ret < 0)
+ {
+ struct timespec ts32, tr32;
+
+ if (! in_time_t_range (time_point->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ valid_timespec64_to_timespec (time_point, &ts32);
+ ret = INTERNAL_SYSCALL_CANCEL (nanosleep, err, &ts32, &tr32);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ remaining->tv_sec = tr32.tv_sec;
+ remaining->tv_nsec = tr32.tv_nsec;
+ }
+ }
+# else
+ if (ret < 0)
+ ret = INTERNAL_SYSCALL_CANCEL (nanosleep, err, time_point, remaining);
+# endif /* __TIMESIZE == 64 */
+#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;
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 0cb6614dc92..4f9fc8b47b6 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)
{
+ int r = -1;
+
if (clock_id == CLOCK_THREAD_CPUTIME_ID)
return EINVAL;
if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
@@ -36,8 +37,62 @@ __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
+ r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
+ flags, req, rem);
+#else
+# ifdef __NR_clock_nanosleep_time64
+# if __TIMESIZE == 64
+ 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;
+# else
+ timespec64 ts64;
+
+ r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err,
+ clock_id, flags, req,
+ ts64);
+
+ if (r == 0 || errno != ENOSYS)
+ {
+ rem->tv_sec = ts64.tv_sec;
+ rem->tv_nsec = ts64.tv_nsec;
+ return r;
+ }
+# endif /* __TIMESIZE == 64 */
+# endif /* __NR_clock_nanosleep_time64 */
+# if __TIMESIZE == 64
+ struct timespec ts32, tr32;
+
+ if (r < 0)
+ {
+ 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->tv_sec = tr32.tv_sec;
+ rem->tv_nsec = tr32.tv_nsec;
+ }
+ }
+# else
+ if (r < 0)
+ r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, req, rem);
+# endif /* __TIMESIZE == 64 */
+#endif /* __ASSUME_TIME64_SYSCALLS */
+
return (INTERNAL_SYSCALL_ERROR_P (r, err)
? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
}
diff --git a/sysdeps/unix/sysv/linux/nanosleep.c b/sysdeps/unix/sysv/linux/nanosleep.c
index f14ae565af5..a894ccbc6dd 100644
--- a/sysdeps/unix/sysv/linux/nanosleep.c
+++ b/sysdeps/unix/sysv/linux/nanosleep.c
@@ -20,12 +20,87 @@
#include <sysdep-cancel.h>
#include <not-cancel.h>
+#if defined(__ASSUME_TIME64_SYSCALLS) || defined(__NR_clock_nanosleep_time64)
+static int
+__nanosleep_time64_64 (const struct timespec *requested_time,
+ struct timespec *remaining)
+{
+ return SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0,
+ requested_time, remaining);
+}
+
+#if __TIMESIZE == 32
+struct timespec64
+{
+ long long int tv_sec; /* Seconds. */
+ long int tv_nsec; /* Nanoseconds. */
+};
+
+static int
+__nanosleep_time64_32 (const struct timespec *requested_time,
+ struct timespec *remaining)
+{
+ timespec64 ts;
+
+ long int ret = SYSCALL_CANCEL (clock_nanosleep_time64, CLOCK_REALTIME, 0,
+ requested_time, &ts);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ remaining->tv_sec = ts.tv_sec;
+ remaining->tv_nsec = ts.tv_nsec;
+ }
+
+ return ret;
+}
+#endif
+#endif
+
/* Pause execution for a number of nanoseconds. */
int
__nanosleep (const struct timespec *requested_time,
struct timespec *remaining)
{
+#ifdef __ASSUME_TIME64_SYSCALLS
+ return __nanosleep_time64_64 (requested_time, remaining);
+#else
+ long int ret;
+# ifdef __NR_clock_nanosleep_time64
+# if __TIMESIZE == 64
+ ret = __nanosleep_time64_64 (requested_time, remaining);
+
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+# else
+ ret = __nanosleep_time64_32 (requested_time, remaining);
+
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+# endif /* __TIMESIZE == 64 */
+# endif /* __NR_clock_nanosleep_time64 */
+# if __TIMESIZE == 64
+ 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->tv_sec = tr32.tv_sec;
+ remaining->tv_nsec = tr32.tv_nsec;
+ }
+
+ return ret;
+# else
return SYSCALL_CANCEL (nanosleep, requested_time, remaining);
+# endif /* __TIMESIZE == 64 */
+#endif /* __ASSUME_TIME64_SYSCALLS */
}
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..f04e229e5ec 100644
--- a/sysdeps/unix/sysv/linux/nanosleep_nocancel.c
+++ b/sysdeps/unix/sysv/linux/nanosleep_nocancel.c
@@ -24,6 +24,53 @@ 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
+ long int ret;
+# ifdef __NR_clock_nanosleep_time64
+# if __TIMESIZE == 64
+ ret = INLINE_SYSCALL_CALL (clock_nanosleep_time64, CLOCK_REALTIME, 0,
+ requested_time, remaining);
+
+ if (ret_64 == 0 || errno != ENOSYS)
+ return ret;
+# else
+ timespec64 ts64;
+
+ ret = INLINE_SYSCALL_CALL (clock_nanosleep_time64, CLOCK_REALTIME, 0,
+ time_point, ts64);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ remaining->tv_sec = ts64.tv_sec;
+ remaining->tv_nsec = ts64.tv_nsec;
+ return ret;
+ }
+# endif /* __TIMESIZE == 64 */
+# endif /* __NR_clock_nanosleep_time64 */
+# if __TIMESIZE == 64
+ 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)
+ {
+ remaining->tv_sec = tr32.tv_sec;
+ remaining->tv_nsec = tr32.tv_nsec;
+ }
+ return ret;
+# else
return INLINE_SYSCALL_CALL (nanosleep, requested_time, remaining);
+# endif /* __TIMESIZE == 64 */
+#endif /* __ASSUME_TIME64_SYSCALLS */
}
hidden_def (__nanosleep_nocancel)
--
2.22.0