1 /* GLIB - Library of useful routines for C programming 2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald 3 * 4 * gpoll.c: poll(2) abstraction 5 * Copyright 1998 Owen Taylor 6 * Copyright 2008 Red Hat, Inc. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the 20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 21 * Boston, MA 02111-1307, USA. 22 */ 23 24 /* 25 * Modified by the GLib Team and others 1997-2000. See the AUTHORS 26 * file for a list of people on the GLib Team. See the ChangeLog 27 * files for a list of changes. These files are distributed with 28 * GLib at ftp://ftp.gtk.org/pub/gtk/. 29 */ 30 31 /* 32 * MT safe 33 */ 34 35 #include "config.h" 36 37 /* Uncomment the next line (and the corresponding line in gmain.c) to 38 * enable debugging printouts if the environment variable 39 * G_MAIN_POLL_DEBUG is set to some value. 40 */ 41 /* #define G_MAIN_POLL_DEBUG */ 42 43 #ifdef _WIN32 44 /* Always enable debugging printout on Windows, as it is more often 45 * needed there... 46 */ 47 #define G_MAIN_POLL_DEBUG 48 #endif 49 50 #include "glib.h" 51 #include <sys/types.h> 52 #include <time.h> 53 #include <stdlib.h> 54 #ifdef HAVE_SYS_TIME_H 55 #include <sys/time.h> 56 #endif /* HAVE_SYS_TIME_H */ 57 #ifdef GLIB_HAVE_SYS_POLL_H 58 # include <sys/poll.h> 59 # undef events /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */ 60 # undef revents /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */ 61 62 /* The poll() emulation on OS/X doesn't handle fds=NULL, nfds=0, 63 * so we prefer our own poll emulation. 64 */ 65 #if defined(_POLL_EMUL_H_) || defined(BROKEN_POLL) 66 #undef HAVE_POLL 67 #endif 68 69 #endif /* GLIB_HAVE_SYS_POLL_H */ 70 #ifdef HAVE_UNISTD_H 71 #include <unistd.h> 72 #endif /* HAVE_UNISTD_H */ 73 #include <errno.h> 74 75 #ifdef G_OS_WIN32 76 #define STRICT 77 #include <windows.h> 78 #endif /* G_OS_WIN32 */ 79 80 #include "galias.h" 81 82 #ifdef G_MAIN_POLL_DEBUG 83 extern gboolean _g_main_poll_debug; 84 #endif 85 86 #ifdef HAVE_POLL 87 /* SunOS has poll, but doesn't provide a prototype. */ 88 # if defined (sun) && !defined (__SVR4) 89 extern gint poll (struct pollfd *fds, guint nfsd, gint timeout); 90 # endif /* !sun */ 91 92 /** 93 * g_poll: 94 * @fds: file descriptors to poll 95 * @nfds: the number of file descriptors in @fds 96 * @timeout: amount of time to wait, in milliseconds, or -1 to wait forever 97 * 98 * Polls @fds, as with the poll() system call, but portably. (On 99 * systems that don't have poll(), it is emulated using select().) 100 * This is used internally by #GMainContext, but it can be called 101 * directly if you need to block until a file descriptor is ready, but 102 * don't want to run the full main loop. 103 * 104 * Each element of @fds is a #GPollFD describing a single file 105 * descriptor to poll. The %fd field indicates the file descriptor, 106 * and the %events field indicates the events to poll for. On return, 107 * the %revents fields will be filled with the events that actually 108 * occurred. 109 * 110 * On POSIX systems, the file descriptors in @fds can be any sort of 111 * file descriptor, but the situation is much more complicated on 112 * Windows. If you need to use g_poll() in code that has to run on 113 * Windows, the easiest solution is to construct all of your 114 * #GPollFD<!-- -->s with g_io_channel_win32_make_pollfd(). 115 * 116 * Return value: the number of entries in @fds whose %revents fields 117 * were filled in, or 0 if the operation timed out, or -1 on error or 118 * if the call was interrupted. 119 * 120 * Since: 2.20 121 **/ 122 gint 123 g_poll (GPollFD *fds, 124 guint nfds, 125 gint timeout) 126 { 127 return poll ((struct pollfd *)fds, nfds, timeout); 128 } 129 130 #else /* !HAVE_POLL */ 131 132 #ifdef G_OS_WIN32 133 134 static int 135 poll_rest (gboolean poll_msgs, 136 HANDLE *handles, 137 gint nhandles, 138 GPollFD *fds, 139 guint nfds, 140 gint timeout) 141 { 142 DWORD ready; 143 GPollFD *f; 144 int recursed_result; 145 146 if (poll_msgs) 147 { 148 /* Wait for either messages or handles 149 * -> Use MsgWaitForMultipleObjectsEx 150 */ 151 if (_g_main_poll_debug) 152 g_print (" MsgWaitForMultipleObjectsEx(%d, %d)\n", nhandles, timeout); 153 154 ready = MsgWaitForMultipleObjectsEx (nhandles, handles, timeout, 155 QS_ALLINPUT, MWMO_ALERTABLE); 156 157 if (ready == WAIT_FAILED) 158 { 159 gchar *emsg = g_win32_error_message (GetLastError ()); 160 g_warning ("MsgWaitForMultipleObjectsEx failed: %s", emsg); 161 g_free (emsg); 162 } 163 } 164 else if (nhandles == 0) 165 { 166 /* No handles to wait for, just the timeout */ 167 if (timeout == INFINITE) 168 ready = WAIT_FAILED; 169 else 170 { 171 SleepEx (timeout, TRUE); 172 ready = WAIT_TIMEOUT; 173 } 174 } 175 else 176 { 177 /* Wait for just handles 178 * -> Use WaitForMultipleObjectsEx 179 */ 180 if (_g_main_poll_debug) 181 g_print (" WaitForMultipleObjectsEx(%d, %d)\n", nhandles, timeout); 182 183 ready = WaitForMultipleObjectsEx (nhandles, handles, FALSE, timeout, TRUE); 184 if (ready == WAIT_FAILED) 185 { 186 gchar *emsg = g_win32_error_message (GetLastError ()); 187 g_warning ("WaitForMultipleObjectsEx failed: %s", emsg); 188 g_free (emsg); 189 } 190 } 191 192 if (_g_main_poll_debug) 193 g_print (" wait returns %ld%s\n", 194 ready, 195 (ready == WAIT_FAILED ? " (WAIT_FAILED)" : 196 (ready == WAIT_TIMEOUT ? " (WAIT_TIMEOUT)" : 197 (poll_msgs && ready == WAIT_OBJECT_0 + nhandles ? " (msg)" : "")))); 198 199 if (ready == WAIT_FAILED) 200 return -1; 201 else if (ready == WAIT_TIMEOUT || 202 ready == WAIT_IO_COMPLETION) 203 return 0; 204 else if (poll_msgs && ready == WAIT_OBJECT_0 + nhandles) 205 { 206 for (f = fds; f < &fds[nfds]; ++f) 207 if (f->fd == G_WIN32_MSG_HANDLE && f->events & G_IO_IN) 208 f->revents |= G_IO_IN; 209 210 /* If we have a timeout, or no handles to poll, be satisfied 211 * with just noticing we have messages waiting. 212 */ 213 if (timeout != 0 || nhandles == 0) 214 return 1; 215 216 /* If no timeout and handles to poll, recurse to poll them, 217 * too. 218 */ 219 recursed_result = poll_rest (FALSE, handles, nhandles, fds, nfds, 0); 220 return (recursed_result == -1) ? -1 : 1 + recursed_result; 221 } 222 else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles) 223 { 224 for (f = fds; f < &fds[nfds]; ++f) 225 { 226 if ((HANDLE) f->fd == handles[ready - WAIT_OBJECT_0]) 227 { 228 f->revents = f->events; 229 if (_g_main_poll_debug) 230 g_print (" got event %p\n", (HANDLE) f->fd); 231 } 232 } 233 234 /* If no timeout and polling several handles, recurse to poll 235 * the rest of them. 236 */ 237 if (timeout == 0 && nhandles > 1) 238 { 239 /* Remove the handle that fired */ 240 int i; 241 if (ready < nhandles - 1) 242 for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) 243 handles[i-1] = handles[i]; 244 nhandles--; 245 recursed_result = poll_rest (FALSE, handles, nhandles, fds, nfds, 0); 246 return (recursed_result == -1) ? -1 : 1 + recursed_result; 247 } 248 return 1; 249 } 250 251 return 0; 252 } 253 254 gint 255 g_poll (GPollFD *fds, 256 guint nfds, 257 gint timeout) 258 { 259 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 260 gboolean poll_msgs = FALSE; 261 GPollFD *f; 262 gint nhandles = 0; 263 int retval; 264 265 if (_g_main_poll_debug) 266 g_print ("g_poll: waiting for"); 267 268 for (f = fds; f < &fds[nfds]; ++f) 269 if (f->fd == G_WIN32_MSG_HANDLE && (f->events & G_IO_IN)) 270 { 271 if (_g_main_poll_debug && !poll_msgs) 272 g_print (" MSG"); 273 poll_msgs = TRUE; 274 } 275 else if (f->fd > 0) 276 { 277 /* Don't add the same handle several times into the array, as 278 * docs say that is not allowed, even if it actually does seem 279 * to work. 280 */ 281 gint i; 282 283 for (i = 0; i < nhandles; i++) 284 if (handles[i] == (HANDLE) f->fd) 285 break; 286 287 if (i == nhandles) 288 { 289 if (nhandles == MAXIMUM_WAIT_OBJECTS) 290 { 291 g_warning ("Too many handles to wait for!\n"); 292 break; 293 } 294 else 295 { 296 if (_g_main_poll_debug) 297 g_print (" %p", (HANDLE) f->fd); 298 handles[nhandles++] = (HANDLE) f->fd; 299 } 300 } 301 } 302 303 if (_g_main_poll_debug) 304 g_print ("\n"); 305 306 for (f = fds; f < &fds[nfds]; ++f) 307 f->revents = 0; 308 309 if (timeout == -1) 310 timeout = INFINITE; 311 312 /* Polling for several things? */ 313 if (nhandles > 1 || (nhandles > 0 && poll_msgs)) 314 { 315 /* First check if one or several of them are immediately 316 * available 317 */ 318 retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, 0); 319 320 /* If not, and we have a significant timeout, poll again with 321 * timeout then. Note that this will return indication for only 322 * one event, or only for messages. We ignore timeouts less than 323 * ten milliseconds as they are mostly pointless on Windows, the 324 * MsgWaitForMultipleObjectsEx() call will timeout right away 325 * anyway. 326 */ 327 if (retval == 0 && (timeout == INFINITE || timeout >= 10)) 328 retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, timeout); 329 } 330 else 331 { 332 /* Just polling for one thing, so no need to check first if 333 * available immediately 334 */ 335 retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, timeout); 336 } 337 338 if (retval == -1) 339 for (f = fds; f < &fds[nfds]; ++f) 340 f->revents = 0; 341 342 return retval; 343 } 344 345 #else /* !G_OS_WIN32 */ 346 347 /* The following implementation of poll() comes from the GNU C Library. 348 * Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. 349 */ 350 351 #include <string.h> /* for bzero on BSD systems */ 352 353 #ifdef HAVE_SYS_SELECT_H 354 #include <sys/select.h> 355 #endif /* HAVE_SYS_SELECT_H */ 356 357 #ifdef G_OS_BEOS 358 #undef NO_FD_SET 359 #endif /* G_OS_BEOS */ 360 361 #ifndef NO_FD_SET 362 # define SELECT_MASK fd_set 363 #else /* !NO_FD_SET */ 364 # ifndef _AIX 365 typedef long fd_mask; 366 # endif /* _AIX */ 367 # ifdef _IBMR2 368 # define SELECT_MASK void 369 # else /* !_IBMR2 */ 370 # define SELECT_MASK int 371 # endif /* !_IBMR2 */ 372 #endif /* !NO_FD_SET */ 373 374 gint 375 g_poll (GPollFD *fds, 376 guint nfds, 377 gint timeout) 378 { 379 struct timeval tv; 380 SELECT_MASK rset, wset, xset; 381 GPollFD *f; 382 int ready; 383 int maxfd = 0; 384 385 FD_ZERO (&rset); 386 FD_ZERO (&wset); 387 FD_ZERO (&xset); 388 389 for (f = fds; f < &fds[nfds]; ++f) 390 if (f->fd >= 0) 391 { 392 if (f->events & G_IO_IN) 393 FD_SET (f->fd, &rset); 394 if (f->events & G_IO_OUT) 395 FD_SET (f->fd, &wset); 396 if (f->events & G_IO_PRI) 397 FD_SET (f->fd, &xset); 398 if (f->fd > maxfd && (f->events & (G_IO_IN|G_IO_OUT|G_IO_PRI))) 399 maxfd = f->fd; 400 } 401 402 tv.tv_sec = timeout / 1000; 403 tv.tv_usec = (timeout % 1000) * 1000; 404 405 ready = select (maxfd + 1, &rset, &wset, &xset, 406 timeout == -1 ? NULL : &tv); 407 if (ready > 0) 408 for (f = fds; f < &fds[nfds]; ++f) 409 { 410 f->revents = 0; 411 if (f->fd >= 0) 412 { 413 if (FD_ISSET (f->fd, &rset)) 414 f->revents |= G_IO_IN; 415 if (FD_ISSET (f->fd, &wset)) 416 f->revents |= G_IO_OUT; 417 if (FD_ISSET (f->fd, &xset)) 418 f->revents |= G_IO_PRI; 419 } 420 } 421 422 return ready; 423 } 424 425 #endif /* !G_OS_WIN32 */ 426 427 #endif /* !HAVE_POLL */ 428 429 #define __G_POLL_C__ 430 #include "galiasdef.c" 431