static int poll_rest(gboolean poll_msgs, HANDLE *handles, gint nhandles, GPollFD *fds, guint nfds, gint timeout) { DWORD ready; GPollFD *f; int recursed_result; if (poll_msgs) { /* Wait for either messages or handles * -> Use MsgWaitForMultipleObjectsEx */ ready = MsgWaitForMultipleObjectsEx(nhandles, handles, timeout, QS_ALLINPUT, MWMO_ALERTABLE); if (ready == WAIT_FAILED) { gchar *emsg = g_win32_error_message(GetLastError()); g_warning("MsgWaitForMultipleObjectsEx failed: %s", emsg); g_free(emsg); } } else if (nhandles == 0) { /* No handles to wait for, just the timeout */ if (timeout == INFINITE) { ready = WAIT_FAILED; } else { SleepEx(timeout, TRUE); ready = WAIT_TIMEOUT; } } else { /* Wait for just handles * -> Use WaitForMultipleObjectsEx */ ready = WaitForMultipleObjectsEx(nhandles, handles, FALSE, timeout, TRUE); if (ready == WAIT_FAILED) { gchar *emsg = g_win32_error_message(GetLastError()); g_warning("WaitForMultipleObjectsEx failed: %s", emsg); g_free(emsg); } } if (ready == WAIT_FAILED) { return -1; } else if (ready == WAIT_TIMEOUT || ready == WAIT_IO_COMPLETION) { return 0; } else if (poll_msgs && ready == WAIT_OBJECT_0 + nhandles) { for (f = fds; f < &fds[nfds]; ++f) { if (f->fd == G_WIN32_MSG_HANDLE && f->events & G_IO_IN) { f->revents |= G_IO_IN; } } /* If we have a timeout, or no handles to poll, be satisfied * with just noticing we have messages waiting. */ if (timeout != 0 || nhandles == 0) { return 1; } /* If no timeout and handles to poll, recurse to poll them, * too. */ recursed_result = poll_rest(FALSE, handles, nhandles, fds, nfds, 0); return (recursed_result == -1) ? -1 : 1 + recursed_result; } else if (/* QEMU: removed the following unneeded statement which causes * a compiler warning: ready >= WAIT_OBJECT_0 && */ ready < WAIT_OBJECT_0 + nhandles) { for (f = fds; f < &fds[nfds]; ++f) { if ((HANDLE) f->fd == handles[ready - WAIT_OBJECT_0]) { f->revents = f->events; } } /* If no timeout and polling several handles, recurse to poll * the rest of them. */ if (timeout == 0 && nhandles > 1) { /* Remove the handle that fired */ int i; if (ready < nhandles - 1) { for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) { handles[i-1] = handles[i]; } } nhandles--; recursed_result = poll_rest(FALSE, handles, nhandles, fds, nfds, 0); return (recursed_result == -1) ? -1 : 1 + recursed_result; } return 1; } return 0; }
gint g_poll(GPollFD *fds, guint nfds, gint timeout) { HANDLE handles[MAXIMUM_WAIT_OBJECTS]; gboolean poll_msgs = FALSE; GPollFD *f; gint nhandles = 0; int retval; for (f = fds; f < &fds[nfds]; ++f) { if (f->fd == G_WIN32_MSG_HANDLE && (f->events & G_IO_IN)) { poll_msgs = TRUE; } else if (f->fd > 0) { /* Don't add the same handle several times into the array, as * docs say that is not allowed, even if it actually does seem * to work. */ gint i; for (i = 0; i < nhandles; i++) { if (handles[i] == (HANDLE) f->fd) { break; } } if (i == nhandles) { if (nhandles == MAXIMUM_WAIT_OBJECTS) { g_warning("Too many handles to wait for!\n"); break; } else { handles[nhandles++] = (HANDLE) f->fd; } } } } for (f = fds; f < &fds[nfds]; ++f) { f->revents = 0; } if (timeout == -1) { timeout = INFINITE; } /* Polling for several things? */ if (nhandles > 1 || (nhandles > 0 && poll_msgs)) { /* First check if one or several of them are immediately * available */ retval = poll_rest(poll_msgs, handles, nhandles, fds, nfds, 0); /* If not, and we have a significant timeout, poll again with * timeout then. Note that this will return indication for only * one event, or only for messages. We ignore timeouts less than * ten milliseconds as they are mostly pointless on Windows, the * MsgWaitForMultipleObjectsEx() call will timeout right away * anyway. * * Modification for QEMU: replaced timeout >= 10 by timeout > 0. */ if (retval == 0 && (timeout == INFINITE || timeout > 0)) { retval = poll_rest(poll_msgs, handles, nhandles, fds, nfds, timeout); } } else { /* Just polling for one thing, so no need to check first if * available immediately */ retval = poll_rest(poll_msgs, handles, nhandles, fds, nfds, timeout); } if (retval == -1) { for (f = fds; f < &fds[nfds]; ++f) { f->revents = 0; } } return retval; }
gint g_poll (GPollFD *fds, guint nfds, gint timeout) { HANDLE handles[MAXIMUM_WAIT_OBJECTS]; gboolean poll_msgs = FALSE; GPollFD *f; gint nhandles = 0; int retval; if (_g_main_poll_debug) g_print ("g_poll: waiting for"); for (f = fds; f < &fds[nfds]; ++f) if (f->fd == G_WIN32_MSG_HANDLE && (f->events & G_IO_IN)) { if (_g_main_poll_debug && !poll_msgs) g_print (" MSG"); poll_msgs = TRUE; } else if (f->fd > 0) { if (nhandles == MAXIMUM_WAIT_OBJECTS) { g_warning ("Too many handles to wait for!\n"); break; } else { if (_g_main_poll_debug) g_print (" %p", (HANDLE) f->fd); handles[nhandles++] = (HANDLE) f->fd; } } if (_g_main_poll_debug) g_print ("\n"); for (f = fds; f < &fds[nfds]; ++f) f->revents = 0; if (timeout == -1) timeout = INFINITE; /* Polling for several things? */ if (nhandles > 1 || (nhandles > 0 && poll_msgs)) { /* First check if one or several of them are immediately * available */ retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, 0); /* If not, and we have a significant timeout, poll again with * timeout then. Note that this will return indication for only * one event, or only for messages. */ if (retval == 0 && (timeout == INFINITE || timeout > 0)) retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, timeout); } else { /* Just polling for one thing, so no need to check first if * available immediately */ retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, timeout); } if (retval == -1) for (f = fds; f < &fds[nfds]; ++f) f->revents = 0; return retval; }