1 /* Copyright (C) 1994,1996,1997,1998,1999,2001,2002 2 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <http://www.gnu.org/licenses/>. */ 18 19 #include <sys/syscall.h> 20 #include <sys/poll.h> 21 #include <bits/kernel-features.h> 22 #include <cancel.h> 23 24 #if defined __ASSUME_POLL_SYSCALL && defined __NR_poll 25 26 #define __NR___poll_nocancel __NR_poll 27 static _syscall3(int, __NC(poll), struct pollfd *, fds, 28 unsigned long int, nfds, int, timeout) 29 30 #else /* !__NR_poll */ 31 32 #include <alloca.h> 33 #include <sys/types.h> 34 #include <errno.h> 35 #include <string.h> 36 #include <sys/time.h> 37 #include <sys/param.h> 38 #include <unistd.h> 39 #include <sys/select.h> 40 41 /* uClinux 2.0 doesn't have poll, emulate it using select */ 42 43 /* Poll the file descriptors described by the NFDS structures starting at 44 FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for 45 an event to occur; if TIMEOUT is -1, block until an event occurs. 46 Returns the number of file descriptors with events, zero if timed out, 47 or -1 for errors. */ 48 49 int __NC(poll)(struct pollfd *fds, nfds_t nfds, int timeout) 50 { 51 static int max_fd_size; 52 struct timeval tv; 53 fd_set *rset, *wset, *xset; 54 struct pollfd *f; 55 int ready; 56 int maxfd = 0; 57 int bytes; 58 59 if (!max_fd_size) 60 max_fd_size = getdtablesize (); 61 62 bytes = howmany (max_fd_size, __NFDBITS); 63 rset = alloca (bytes); 64 wset = alloca (bytes); 65 xset = alloca (bytes); 66 67 /* We can't call FD_ZERO, since FD_ZERO only works with sets 68 of exactly __FD_SETSIZE size. */ 69 memset (rset, 0, bytes); 70 memset (wset, 0, bytes); 71 memset (xset, 0, bytes); 72 73 for (f = fds; f < &fds[nfds]; ++f) 74 { 75 f->revents = 0; 76 if (f->fd >= 0) 77 { 78 if (f->fd >= max_fd_size) 79 { 80 /* The user provides a file descriptor number which is higher 81 than the maximum we got from the `getdtablesize' call. 82 Maybe this is ok so enlarge the arrays. */ 83 fd_set *nrset, *nwset, *nxset; 84 int nbytes; 85 86 max_fd_size = roundup (f->fd, __NFDBITS); 87 nbytes = howmany (max_fd_size, __NFDBITS); 88 89 nrset = alloca (nbytes); 90 nwset = alloca (nbytes); 91 nxset = alloca (nbytes); 92 93 memset ((char *) nrset + bytes, 0, nbytes - bytes); 94 memset ((char *) nwset + bytes, 0, nbytes - bytes); 95 memset ((char *) nxset + bytes, 0, nbytes - bytes); 96 97 rset = memcpy (nrset, rset, bytes); 98 wset = memcpy (nwset, wset, bytes); 99 xset = memcpy (nxset, xset, bytes); 100 101 bytes = nbytes; 102 } 103 104 if (f->events & POLLIN) 105 FD_SET (f->fd, rset); 106 if (f->events & POLLOUT) 107 FD_SET (f->fd, wset); 108 if (f->events & POLLPRI) 109 FD_SET (f->fd, xset); 110 if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) 111 maxfd = f->fd; 112 } 113 } 114 115 tv.tv_sec = timeout / 1000; 116 tv.tv_usec = (timeout % 1000) * 1000; 117 118 while (1) 119 { 120 ready = __NC(select) (maxfd + 1, rset, wset, xset, 121 timeout == -1 ? NULL : &tv); 122 123 /* It might be that one or more of the file descriptors is invalid. 124 We now try to find and mark them and then try again. */ 125 if (ready == -1 && errno == EBADF) 126 { 127 fd_set *sngl_rset = alloca (bytes); 128 fd_set *sngl_wset = alloca (bytes); 129 fd_set *sngl_xset = alloca (bytes); 130 struct timeval sngl_tv; 131 132 /* Clear the original set. */ 133 memset (rset, 0, bytes); 134 memset (wset, 0, bytes); 135 memset (xset, 0, bytes); 136 137 /* This means we don't wait for input. */ 138 sngl_tv.tv_sec = 0; 139 sngl_tv.tv_usec = 0; 140 141 maxfd = -1; 142 143 /* Reset the return value. */ 144 ready = 0; 145 146 for (f = fds; f < &fds[nfds]; ++f) 147 if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI)) 148 && (f->revents & POLLNVAL) == 0) 149 { 150 int n; 151 152 memset (sngl_rset, 0, bytes); 153 memset (sngl_wset, 0, bytes); 154 memset (sngl_xset, 0, bytes); 155 156 if (f->events & POLLIN) 157 FD_SET (f->fd, sngl_rset); 158 if (f->events & POLLOUT) 159 FD_SET (f->fd, sngl_wset); 160 if (f->events & POLLPRI) 161 FD_SET (f->fd, sngl_xset); 162 163 n = __NC(select) (f->fd + 1, sngl_rset, sngl_wset, sngl_xset, 164 &sngl_tv); 165 if (n != -1) 166 { 167 /* This descriptor is ok. */ 168 if (f->events & POLLIN) 169 FD_SET (f->fd, rset); 170 if (f->events & POLLOUT) 171 FD_SET (f->fd, wset); 172 if (f->events & POLLPRI) 173 FD_SET (f->fd, xset); 174 if (f->fd > maxfd) 175 maxfd = f->fd; 176 if (n > 0) 177 /* Count it as being available. */ 178 ++ready; 179 } 180 else if (errno == EBADF) 181 f->revents |= POLLNVAL; 182 } 183 /* Try again. */ 184 continue; 185 } 186 187 break; 188 } 189 190 if (ready > 0) 191 for (f = fds; f < &fds[nfds]; ++f) 192 { 193 if (f->fd >= 0) 194 { 195 if (FD_ISSET (f->fd, rset)) 196 f->revents |= POLLIN; 197 if (FD_ISSET (f->fd, wset)) 198 f->revents |= POLLOUT; 199 if (FD_ISSET (f->fd, xset)) 200 f->revents |= POLLPRI; 201 } 202 } 203 204 return ready; 205 } 206 207 #endif 208 CANCELLABLE_SYSCALL(int, poll, (struct pollfd *fds, nfds_t nfds, int timeout), 209 (fds, nfds, timeout)) 210 lt_libc_hidden(poll) 211