xserver_poll.c (8662B)
1 /*---------------------------------------------------------------------------*\ 2 $Id$ 3 4 NAME 5 6 poll - select(2)-based poll() emulation function for BSD systems. 7 8 SYNOPSIS 9 #include "poll.h" 10 11 struct pollfd 12 { 13 int fd; 14 short events; 15 short revents; 16 } 17 18 int poll (struct pollfd *pArray, unsigned long n_fds, int timeout) 19 20 DESCRIPTION 21 22 This file, and the accompanying "poll.h", implement the System V 23 poll(2) system call for BSD systems (which typically do not provide 24 poll()). Poll() provides a method for multiplexing input and output 25 on multiple open file descriptors; in traditional BSD systems, that 26 capability is provided by select(). While the semantics of select() 27 differ from those of poll(), poll() can be readily emulated in terms 28 of select() -- which is how this function is implemented. 29 30 REFERENCES 31 Stevens, W. Richard. Unix Network Programming. Prentice-Hall, 1990. 32 33 NOTES 34 1. This software requires an ANSI C compiler. 35 36 LICENSE 37 38 This software is released under the following BSD license, adapted from 39 http://opensource.org/licenses/bsd-license.php 40 41 Copyright (c) 1995-2011, Brian M. Clapper 42 All rights reserved. 43 44 Redistribution and use in source and binary forms, with or without 45 modification, are permitted provided that the following conditions are met: 46 47 * Redistributions of source code must retain the above copyright notice, 48 this list of conditions and the following disclaimer. 49 50 * Redistributions in binary form must reproduce the above copyright 51 notice, this list of conditions and the following disclaimer in the 52 documentation and/or other materials provided with the distribution. 53 54 * Neither the name of the clapper.org nor the names of its contributors 55 may be used to endorse or promote products derived from this software 56 without specific prior written permission. 57 58 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 59 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 60 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 61 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 62 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 63 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 64 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 65 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 66 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 67 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 68 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 \*---------------------------------------------------------------------------*/ 70 71 72 /*---------------------------------------------------------------------------*\ 73 Includes 74 \*---------------------------------------------------------------------------*/ 75 76 #ifdef HAVE_DIX_CONFIG_H 77 #include <dix-config.h> 78 #endif 79 80 #include <unistd.h> /* standard Unix definitions */ 81 #include <sys/types.h> /* system types */ 82 #include <sys/time.h> /* time definitions */ 83 #include <assert.h> /* assertion macros */ 84 #include <string.h> /* string functions */ 85 #include "xserver_poll.h" 86 87 #if defined(WIN32) && !defined(__CYGWIN__) 88 #include <X11/Xwinsock.h> 89 #endif 90 91 /*---------------------------------------------------------------------------*\ 92 Macros 93 \*---------------------------------------------------------------------------*/ 94 95 #ifndef MAX 96 #define MAX(a,b) ((a) > (b) ? (a) : (b)) 97 #endif 98 99 /*---------------------------------------------------------------------------*\ 100 Private Functions 101 \*---------------------------------------------------------------------------*/ 102 103 static int map_poll_spec 104 (struct pollfd *pArray, 105 nfds_t n_fds, 106 fd_set *pReadSet, 107 fd_set *pWriteSet, 108 fd_set *pExceptSet) 109 { 110 register nfds_t i; /* loop control */ 111 register struct pollfd *pCur; /* current array element */ 112 register int max_fd = -1; /* return value */ 113 114 /* 115 Map the poll() structures into the file descriptor sets required 116 by select(). 117 */ 118 for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) 119 { 120 /* Skip any bad FDs in the array. */ 121 122 if (pCur->fd < 0) 123 continue; 124 125 if (pCur->events & POLLIN) 126 { 127 /* "Input Ready" notification desired. */ 128 FD_SET (pCur->fd, pReadSet); 129 } 130 131 if (pCur->events & POLLOUT) 132 { 133 /* "Output Possible" notification desired. */ 134 FD_SET (pCur->fd, pWriteSet); 135 } 136 137 if (pCur->events & POLLPRI) 138 { 139 /* 140 "Exception Occurred" notification desired. (Exceptions 141 include out of band data. 142 */ 143 FD_SET (pCur->fd, pExceptSet); 144 } 145 146 max_fd = MAX (max_fd, pCur->fd); 147 } 148 149 return max_fd; 150 } 151 152 static struct timeval *map_timeout 153 (int poll_timeout, struct timeval *pSelTimeout) 154 { 155 struct timeval *pResult; 156 157 /* 158 Map the poll() timeout value into a select() timeout. The possible 159 values of the poll() timeout value, and their meanings, are: 160 161 VALUE MEANING 162 163 -1 wait indefinitely (until signal occurs) 164 0 return immediately, don't block 165 >0 wait specified number of milliseconds 166 167 select() uses a "struct timeval", which specifies the timeout in 168 seconds and microseconds, so the milliseconds value has to be mapped 169 accordingly. 170 */ 171 172 assert (pSelTimeout != (struct timeval *) NULL); 173 174 switch (poll_timeout) 175 { 176 case -1: 177 /* 178 A NULL timeout structure tells select() to wait indefinitely. 179 */ 180 pResult = (struct timeval *) NULL; 181 break; 182 183 case 0: 184 /* 185 "Return immediately" (test) is specified by all zeros in 186 a timeval structure. 187 */ 188 pSelTimeout->tv_sec = 0; 189 pSelTimeout->tv_usec = 0; 190 pResult = pSelTimeout; 191 break; 192 193 default: 194 /* Wait the specified number of milliseconds. */ 195 pSelTimeout->tv_sec = poll_timeout / 1000; /* get seconds */ 196 poll_timeout %= 1000; /* remove seconds */ 197 pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */ 198 pResult = pSelTimeout; 199 break; 200 } 201 202 203 return pResult; 204 } 205 206 static void map_select_results 207 (struct pollfd *pArray, 208 unsigned long n_fds, 209 fd_set *pReadSet, 210 fd_set *pWriteSet, 211 fd_set *pExceptSet) 212 { 213 register unsigned long i; /* loop control */ 214 register struct pollfd *pCur; /* current array element */ 215 216 for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) 217 { 218 /* Skip any bad FDs in the array. */ 219 220 if (pCur->fd < 0) 221 continue; 222 223 /* Exception events take priority over input events. */ 224 225 pCur->revents = 0; 226 if (FD_ISSET (pCur->fd, pExceptSet)) 227 pCur->revents |= POLLPRI; 228 229 else if (FD_ISSET (pCur->fd, pReadSet)) 230 pCur->revents |= POLLIN; 231 232 if (FD_ISSET (pCur->fd, pWriteSet)) 233 pCur->revents |= POLLOUT; 234 } 235 236 return; 237 } 238 239 /*---------------------------------------------------------------------------*\ 240 Public Functions 241 \*---------------------------------------------------------------------------*/ 242 243 int xserver_poll 244 (struct pollfd *pArray, unsigned long n_fds, int timeout) 245 { 246 fd_set read_descs; /* input file descs */ 247 fd_set write_descs; /* output file descs */ 248 fd_set except_descs; /* exception descs */ 249 struct timeval stime; /* select() timeout value */ 250 int ready_descriptors; /* function result */ 251 int max_fd; /* maximum fd value */ 252 struct timeval *pTimeout; /* actually passed */ 253 254 FD_ZERO (&read_descs); 255 FD_ZERO (&write_descs); 256 FD_ZERO (&except_descs); 257 258 assert (pArray != (struct pollfd *) NULL); 259 260 /* Map the poll() file descriptor list in the select() data structures. */ 261 262 max_fd = map_poll_spec (pArray, n_fds, 263 &read_descs, &write_descs, &except_descs); 264 265 /* Map the poll() timeout value in the select() timeout structure. */ 266 267 pTimeout = map_timeout (timeout, &stime); 268 269 /* Make the select() call. */ 270 271 ready_descriptors = select (max_fd + 1, &read_descs, &write_descs, 272 &except_descs, pTimeout); 273 274 if (ready_descriptors >= 0) 275 { 276 map_select_results (pArray, n_fds, 277 &read_descs, &write_descs, &except_descs); 278 } 279 280 return ready_descriptors; 281 }