int sim_slirp_select (SLIRP *slirp, int ms_timeout) { int select_ret = 0; uint32 slirp_timeout = ms_timeout; struct timeval timeout; fd_set rfds, wfds, xfds; fd_set save_rfds, save_wfds, save_xfds; int nfds; /* Populate the GPollFDs from slirp */ g_array_set_size (slirp->gpollfds, 1); /* Leave the doorbell chime alone */ slirp_pollfds_fill(slirp->gpollfds, &slirp_timeout); timeout.tv_sec = slirp_timeout / 1000; timeout.tv_usec = (slirp_timeout % 1000) * 1000; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&xfds); /* Extract the GPollFDs interest */ nfds = pollfds_fill (slirp->gpollfds, &rfds, &wfds, &xfds); save_rfds = rfds; save_wfds = wfds; save_xfds = xfds; select_ret = select(nfds + 1, &rfds, &wfds, &xfds, &timeout); if (select_ret) { int i; /* Update the GPollFDs results */ pollfds_poll (slirp->gpollfds, nfds, &rfds, &wfds, &xfds); if (FD_ISSET (slirp->db_chime, &rfds)) { char buf[32]; /* consume the doorbell wakeup ring */ recv (slirp->db_chime, buf, sizeof (buf), 0); } sim_debug (slirp->dbit, slirp->dptr, "Select returned %d\r\n", select_ret); for (i=0; i<nfds+1; i++) { if (FD_ISSET(i, &rfds) || FD_ISSET(i, &save_rfds)) sim_debug (slirp->dbit, slirp->dptr, "%d: save_rfd=%d, rfd=%d\r\n", i, FD_ISSET(i, &save_rfds), FD_ISSET(i, &rfds)); if (FD_ISSET(i, &wfds) || FD_ISSET(i, &save_wfds)) sim_debug (slirp->dbit, slirp->dptr, "%d: save_wfd=%d, wfd=%d\r\n", i, FD_ISSET(i, &save_wfds), FD_ISSET(i, &wfds)); if (FD_ISSET(i, &xfds) || FD_ISSET(i, &save_xfds)) sim_debug (slirp->dbit, slirp->dptr, "%d: save_xfd=%d, xfd=%d\r\n", i, FD_ISSET(i, &save_xfds), FD_ISSET(i, &xfds)); } } return select_ret + 1; /* Force dispatch even on timeout */ }
static int os_host_main_loop_wait(int64_t timeout) { GMainContext *context = g_main_context_default(); GPollFD poll_fds[1024 * 2]; /* this is probably overkill */ int select_ret = 0; int g_poll_ret, ret, i, n_poll_fds; PollingEntry *pe; WaitObjects *w = &wait_objects; gint poll_timeout; int64_t poll_timeout_ns; static struct timeval tv0; fd_set rfds, wfds, xfds; int nfds; /* XXX: need to suppress polling by better using win32 events */ ret = 0; for (pe = first_polling_entry; pe != NULL; pe = pe->next) { ret |= pe->func(pe->opaque); } if (ret != 0) { return ret; } FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&xfds); nfds = pollfds_fill(gpollfds, &rfds, &wfds, &xfds); if (nfds >= 0) { select_ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0); if (select_ret != 0) { timeout = 0; } if (select_ret > 0) { pollfds_poll(gpollfds, nfds, &rfds, &wfds, &xfds); } } g_main_context_prepare(context, &max_priority); n_poll_fds = g_main_context_query(context, max_priority, &poll_timeout, poll_fds, ARRAY_SIZE(poll_fds)); g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds)); for (i = 0; i < w->num; i++) { poll_fds[n_poll_fds + i].fd = (DWORD_PTR)w->events[i]; poll_fds[n_poll_fds + i].events = G_IO_IN; } if (poll_timeout < 0) { poll_timeout_ns = -1; } else { poll_timeout_ns = (int64_t)poll_timeout * (int64_t)SCALE_MS; } poll_timeout_ns = qemu_soonest_timeout(poll_timeout_ns, timeout); qemu_mutex_unlock_iothread(); g_poll_ret = qemu_poll_ns(poll_fds, n_poll_fds + w->num, poll_timeout_ns); qemu_mutex_lock_iothread(); if (g_poll_ret > 0) { for (i = 0; i < w->num; i++) { w->revents[i] = poll_fds[n_poll_fds + i].revents; } for (i = 0; i < w->num; i++) { if (w->revents[i] && w->func[i]) { w->func[i](w->opaque[i]); } } } if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) { g_main_context_dispatch(context); } return select_ret || g_poll_ret; }