aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>2017-09-08 00:42:16 +0200
committerAlbert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>2018-10-24 12:53:27 +0200
commitc4ec41f9cf3279d8316be52011ba5603215384dd (patch)
treee837cbefbfa893510e81bb69cc147f960d9e5916
parentd9a19a386245ebcfa78309709fd6394a45292601 (diff)
downloadglibc-c4ec41f9cf3279d8316be52011ba5603215384dd.tar
glibc-c4ec41f9cf3279d8316be52011ba5603215384dd.tar.gz
glibc-c4ec41f9cf3279d8316be52011ba5603215384dd.tar.bz2
glibc-c4ec41f9cf3279d8316be52011ba5603215384dd.zip
Y2038: add function pselect64
-rw-r--r--include/sys/select.h8
-rw-r--r--sysdeps/unix/sysv/linux/pselect.c66
2 files changed, 74 insertions, 0 deletions
diff --git a/include/sys/select.h b/include/sys/select.h
index 07bb49b994..ba013a395c 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -3,6 +3,7 @@
#ifndef _ISOMAC
/* Now define the internal interfaces. */
+
extern int __pselect (int __nfds, fd_set *__readfds,
fd_set *__writefds, fd_set *__exceptfds,
const struct timespec *__timeout,
@@ -14,5 +15,12 @@ extern int __select (int __nfds, fd_set *__restrict __readfds,
struct timeval *__restrict __timeout);
libc_hidden_proto (__select)
+/* 64-bit time version */
+
+extern int __pselect64 (int __nfds, fd_set *__readfds,
+ fd_set *__writefds, fd_set *__exceptfds,
+ const struct __timespec64 *__timeout,
+ const __sigset_t *__sigmask);
+
#endif
#endif
diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c
index 2b052e7b00..8a77036697 100644
--- a/sysdeps/unix/sysv/linux/pselect.c
+++ b/sysdeps/unix/sysv/linux/pselect.c
@@ -22,6 +22,7 @@
#include <sys/poll.h>
#include <kernel-features.h>
#include <sysdep-cancel.h>
+#include <y2038-support.h>
#ifdef __NR_pselect6
@@ -79,6 +80,71 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
}
weak_alias (__pselect, pselect)
+/* 64-bit time version */
+
+int
+__pselect64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ const struct __timespec64 *timeout, const sigset_t *sigmask)
+{
+ struct timespec tval32, *timeout32 = NULL;
+
+ /* Note: the system call expects 7 values but on most architectures
+ we can only pass in 6 directly. If there is an architecture with
+ support for more parameters a new version of this file needs to
+ be created. */
+ struct
+ {
+ __syscall_ulong_t ss;
+ __syscall_ulong_t ss_len;
+ } data;
+
+ data.ss = (__syscall_ulong_t) (uintptr_t) sigmask;
+ data.ss_len = _NSIG / 8;
+
+ int result;
+
+#ifdef __NR_pselect6_time64
+ if (__y2038_linux_support > 0)
+ {
+ result = SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds,
+ exceptfds, timeout, &data);
+ if (result == 0 || errno != ENOSYS)
+ return result;
+ __y2038_linux_support = -1;
+ }
+#endif
+
+ /* The Linux kernel can in some situations update the timeout value.
+ We do not want that so use a local variable. */
+ if (timeout != NULL)
+ {
+ if (timeout->tv_sec > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ tval32.tv_sec = timeout->tv_sec;
+ tval32.tv_nsec = timeout->tv_nsec;
+ timeout32 = &tval32;
+ }
+
+#ifndef CALL_PSELECT6
+# define CALL_PSELECT6(nfds, readfds, writefds, exceptfds, timeout, data) \
+ SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds, timeout32, data)
+#endif
+
+ result = CALL_PSELECT6 (nfds, readfds, writefds, exceptfds, timeout32,
+ &data);
+
+# ifndef __ASSUME_PSELECT
+ if (result == -1 && errno == ENOSYS)
+ result = __generic_pselect (nfds, readfds, writefds, exceptfds, timeout32,
+ sigmask);
+# endif
+
+ return result;
+}
+
# ifndef __ASSUME_PSELECT
# define __pselect static __generic_pselect
# endif