diff options
author | Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr> | 2017-09-08 00:42:16 +0200 |
---|---|---|
committer | Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr> | 2018-04-18 21:28:45 +0200 |
commit | c1fc42402250ccf43699556a1f06244055c6337e (patch) | |
tree | 619ea00255edbe178982460d5d3b9e50f1d06974 | |
parent | 7d9864c8f953bf47cf1b1aab40d8185624c72791 (diff) | |
download | glibc-c1fc42402250ccf43699556a1f06244055c6337e.tar.gz |
Y2038: add function pselect64
-rw-r--r-- | include/sys/select.h | 8 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/pselect.c | 61 |
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 |