1 /* Copyright (C) 2006-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18 #include <sys/select.h>
19 #include <sysdep-cancel.h>
20
21 static int
pselect64_syscall(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,const struct __timespec64 * timeout,const sigset_t * sigmask)22 pselect64_syscall (int nfds, fd_set *readfds, fd_set *writefds,
23 fd_set *exceptfds, const struct __timespec64 *timeout,
24 const sigset_t *sigmask)
25 {
26 #ifndef __NR_pselect6_time64
27 # define __NR_pselect6_time64 __NR_pselect6
28 #endif
29 /* NB: This is required by ARGIFY used in x32 internal_syscallN. */
30 __syscall_ulong_t data[2] =
31 {
32 (uintptr_t) sigmask, __NSIG_BYTES
33 };
34 return SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds, exceptfds,
35 timeout, data);
36 }
37
38 int
__pselect64(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,const struct __timespec64 * timeout,const sigset_t * sigmask)39 __pselect64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
40 const struct __timespec64 *timeout, const sigset_t *sigmask)
41 {
42 /* The Linux kernel can in some situations update the timeout value.
43 We do not want that so use a local variable. */
44 struct __timespec64 tval;
45 if (timeout != NULL)
46 {
47 tval = *timeout;
48 timeout = &tval;
49 }
50
51 /* Note: the system call expects 7 values but on most architectures
52 we can only pass in 6 directly. If there is an architecture with
53 support for more parameters a new version of this file needs to
54 be created. */
55 #ifdef __ASSUME_TIME64_SYSCALLS
56 return pselect64_syscall (nfds, readfds, writefds, exceptfds, timeout,
57 sigmask);
58 #else
59 bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
60 if (need_time64)
61 {
62 int r = pselect64_syscall (nfds, readfds, writefds, exceptfds, timeout,
63 sigmask);
64 if (r == 0 || errno != ENOSYS)
65 return r;
66 __set_errno (EOVERFLOW);
67 return -1;
68 }
69
70 return __pselect32 (nfds, readfds, writefds, exceptfds, timeout, sigmask);
71 #endif
72 }
73
74 #if __TIMESIZE != 64
libc_hidden_def(__pselect64)75 libc_hidden_def (__pselect64)
76
77 int
78 __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
79 const struct timespec *timeout, const sigset_t *sigmask)
80 {
81 struct __timespec64 ts64, *pts64 = NULL;
82 if (timeout != NULL)
83 {
84 ts64 = valid_timespec_to_timespec64 (*timeout);
85 pts64 = &ts64;
86 }
87 return __pselect64 (nfds, readfds, writefds, exceptfds, pts64, sigmask);
88 }
89 #endif
90
91 #ifndef __pselect
92 weak_alias (__pselect, pselect)
93 #endif
94