summaryrefslogtreecommitdiff
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-04-18 21:28:45 +0200
commitc1fc42402250ccf43699556a1f06244055c6337e (patch)
tree619ea00255edbe178982460d5d3b9e50f1d06974
parent7d9864c8f953bf47cf1b1aab40d8185624c72791 (diff)
downloadglibc-c1fc42402250ccf43699556a1f06244055c6337e.tar.gz
Y2038: add function pselect64
-rw-r--r--include/sys/select.h8
-rw-r--r--sysdeps/unix/sysv/linux/pselect.c61
2 files changed, 69 insertions, 0 deletions
diff --git a/include/sys/select.h b/include/sys/select.h
index 07bb49b994..96d46f4de2 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..8ef606f1f1 100644
--- a/sysdeps/unix/sysv/linux/pselect.c
+++ b/sysdeps/unix/sysv/linux/pselect.c
@@ -79,6 +79,67 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
}
weak_alias (__pselect, pselect)
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+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;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement using Linux kernel system call */
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+
+#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