summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2019-11-12 12:17:41 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2019-11-12 12:17:41 -0300
commit023ea2130ce4191e3db8000c51befbf8782a3e4b (patch)
treee132954a0eb2bc04a908d4500661c0d4d622e98f
parentf31de7b04764dc966216f849fbdebe7b59e12cee (diff)
downloadglibc-azanella/pselect-time64.tar.gz
y2038: linux: Provide __pselect64 implementationazanella/pselect-time64
-rw-r--r--include/sys/select.h17
-rw-r--r--sysdeps/unix/sysv/linux/pselect.c51
2 files changed, 61 insertions, 7 deletions
diff --git a/include/sys/select.h b/include/sys/select.h
index 07bb49b994..6f6b848e29 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -14,5 +14,18 @@ extern int __select (int __nfds, fd_set *__restrict __readfds,
struct timeval *__restrict __timeout);
libc_hidden_proto (__select)
-#endif
-#endif
+# if __TIMESIZE == 64
+# define __pselect64 __pselect
+# else
+# include <time.h>
+# include <signal.h>
+
+extern int __pselect64 (int __nfds, fd_set *__readfds, fd_set *__writefds,
+ fd_set *__exceptfds,
+ const struct __timespec64 *__timeout,
+ const sigset_t *__sigmask);
+libc_hidden_proto (__pselect64)
+# endif /* __TIMESIZE == 64 */
+
+#endif /* _ISOMAC */
+#endif /* _SYS_SELECT_H */
diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c
index 77a5179925..45a3b4ab58 100644
--- a/sysdeps/unix/sysv/linux/pselect.c
+++ b/sysdeps/unix/sysv/linux/pselect.c
@@ -23,13 +23,13 @@
#include <kernel-features.h>
#include <sysdep-cancel.h>
-int
-__pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
- const struct timespec *timeout, const sigset_t *sigmask)
+int __pselect64 (int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, const struct __timespec64 *timeout,
+ const sigset_t *sigmask)
{
/* The Linux kernel can in some situations update the timeout value.
We do not want that so use a local variable. */
- struct timespec tval;
+ struct __timespec64 tval;
if (timeout != NULL)
{
tval = *timeout;
@@ -49,9 +49,50 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
data.ss = (__syscall_ulong_t) (uintptr_t) sigmask;
data.ss_len = _NSIG / 8;
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_pselect6_time64
+# define __NR_pselect6_time64 __NR_pselect6
+# endif
+ return SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds, exceptfds,
+ timeout, &data);
+#else
+# ifdef __NR_ppoll_time64
+ int ret = SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds,
+ exceptfds, timeout, &data);
+ if (ret >= 0 || errno != ENOSYS)
+ return ret;
+# endif
+ struct timespec ts32;
+ if (timeout)
+ {
+ if (! in_time_t_range (timeout->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ ts32 = valid_timespec64_to_timespec (*timeout);
+ }
+
return SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds,
- timeout, &data);
+ timeout ? &ts32 : NULL, &data);
+#endif /* __ASSUME_TIME64_SYSCALLS */
}
+
+#if __TIMESIZE != 64
+int
+__pselect (int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, const struct timespec *timeout,
+ const sigset_t *sigmask)
+{
+ struct __timespec64 ts64;
+ if (timeout)
+ ts64 = valid_timespec_to_timespec64 (*timeout);
+
+ return __pselect64 (nfds, readfds, writefds, exceptfds,
+ timeout ? &ts64 : NULL, sigmask);
+}
+#endif
#ifndef __pselect
weak_alias (__pselect, pselect)
#endif