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 <errno.h>
19 #include <limits.h>
20 #include <signal.h>
21 #include <stddef.h>	/* For NULL.  */
22 #include <sys/poll.h>
23 #include <sysdep-cancel.h>
24 #include <time.h>
25 
26 
27 int
ppoll(struct pollfd * fds,nfds_t nfds,const struct timespec * timeout,const sigset_t * sigmask)28 ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
29        const sigset_t *sigmask)
30 {
31   int tval = -1;
32 
33   /* poll uses a simple millisecond value.  Convert it.  */
34   if (timeout != NULL)
35     {
36       if (timeout->tv_sec < 0 || ! valid_nanoseconds (timeout->tv_nsec))
37 	{
38 	  __set_errno (EINVAL);
39 	  return -1;
40 	}
41 
42       if (timeout->tv_sec > INT_MAX / 1000
43 	  || (timeout->tv_sec == INT_MAX / 1000
44 	      && ((timeout->tv_nsec + 999999) / 1000000 > INT_MAX % 1000)))
45 	/* We cannot represent the timeout in an int value.  Wait
46 	   forever.  */
47 	tval = -1;
48       else
49 	tval = (timeout->tv_sec * 1000
50 		+ (timeout->tv_nsec + 999999) / 1000000);
51     }
52 
53   /* The setting and restoring of the signal mask and the select call
54      should be an atomic operation.  This can't be done without kernel
55      help.  */
56   sigset_t savemask;
57   if (sigmask != NULL)
58     __sigprocmask (SIG_SETMASK, sigmask, &savemask);
59 
60   /* Note the ppoll() is a cancellation point.  But since we call
61      poll() which itself is a cancellation point we do not have
62      to do anything here.  */
63   int retval = __poll (fds, nfds, tval);
64 
65   if (sigmask != NULL)
66     __sigprocmask (SIG_SETMASK, &savemask, NULL);
67 
68   return retval;
69 }
70 
71 #ifndef ppoll
72 libc_hidden_def (ppoll);
73 #endif
74