static void glib_pollfds_fill(int64_t *cur_timeout) { GMainContext *context = g_main_context_default(); int timeout = 0; int64_t timeout_ns; int n; g_main_context_prepare(context, &max_priority); glib_pollfds_idx = gpollfds->len; n = glib_n_poll_fds; do { GPollFD *pfds; glib_n_poll_fds = n; g_array_set_size(gpollfds, glib_pollfds_idx + glib_n_poll_fds); pfds = &g_array_index(gpollfds, GPollFD, glib_pollfds_idx); n = g_main_context_query(context, max_priority, &timeout, pfds, glib_n_poll_fds); } while (n != glib_n_poll_fds); if (timeout < 0) { timeout_ns = -1; } else { timeout_ns = (int64_t)timeout * (int64_t)SCALE_MS; } *cur_timeout = qemu_soonest_timeout(timeout_ns, *cur_timeout); }
int qemu_calculate_timeout(void) { int timeout; if (!vm_running) timeout = 5000; else if (tcg_has_work()) timeout = 0; else { #ifdef WIN32 /* This corresponds to the case where the emulated system is * totally idle and waiting for i/o. The problem is that on * Windows, the default value will prevent Windows user events * to be delivered in less than 5 seconds. * * Upstream contains a different way to handle this, for now * this hack should be sufficient until we integrate it into * our tree. */ timeout = 1000/15; /* deliver user events every 15/th of second */ #else timeout = 5000; #endif int64_t timeout_ns = (int64_t)timeout * 1000000LL; timeout_ns = qemu_soonest_timeout( timeout_ns, timerlistgroup_deadline_ns(&main_loop_tlg)); timeout = (int)((timeout_ns + 999999LL) / 1000000LL); } return timeout; }
int64_t aio_compute_timeout(AioContext *ctx) { int64_t deadline; int timeout = -1; QEMUBH *bh; for (bh = ctx->first_bh; bh; bh = bh->next) { if (!bh->deleted && bh->scheduled) { if (bh->idle) { /* idle bottom halves will be polled at least * every 10ms */ timeout = 10000000; } else { /* non-idle bottom halves will be executed * immediately */ return 0; } } } deadline = timerlistgroup_deadline_ns(&ctx->tlg); if (deadline == 0) { return 0; } else { return qemu_soonest_timeout(timeout, deadline); } }
int main_loop_wait(int nonblocking) { int ret; uint32_t timeout = UINT32_MAX; int64_t timeout_ns; if (nonblocking) { timeout = 0; } /* poll any events */ g_array_set_size(gpollfds, 0); /* reset for new iteration */ /* XXX: separate device handlers from system ones */ #ifdef CONFIG_SLIRP slirp_update_timeout(&timeout); slirp_pollfds_fill(gpollfds); #endif qemu_iohandler_fill(gpollfds); if (timeout == UINT32_MAX) { timeout_ns = -1; } else { timeout_ns = (uint64_t)timeout * (int64_t)(SCALE_MS); } timeout_ns = qemu_soonest_timeout(timeout_ns, timerlistgroup_deadline_ns( &main_loop_tlg)); ret = os_host_main_loop_wait(timeout_ns); qemu_iohandler_poll(gpollfds, ret); #ifdef CONFIG_SLIRP slirp_pollfds_poll(gpollfds, (ret < 0)); #endif qemu_clock_run_all_timers(); return ret; }
int main_loop_wait(int nonblocking) { int ret; uint32_t timeout = UINT32_MAX; int64_t timeout_ns; if (nonblocking) { timeout = 0; } /* poll any events */ g_array_set_size(gpollfds, 0); /* reset for new iteration */ /* XXX: separate device handlers from system ones */ #ifdef CONFIG_SLIRP slirp_pollfds_fill(gpollfds, &timeout); #endif if (timeout == UINT32_MAX) { timeout_ns = -1; } else { timeout_ns = (uint64_t)timeout * (int64_t)(SCALE_MS); } timeout_ns = qemu_soonest_timeout(timeout_ns, timerlistgroup_deadline_ns( &main_loop_tlg)); ret = os_host_main_loop_wait(timeout_ns); #ifdef CONFIG_SLIRP slirp_pollfds_poll(gpollfds, (ret < 0)); #endif /* CPU thread can infinitely wait for event after missing the warp */ qemu_clock_warp(QEMU_CLOCK_VIRTUAL); qemu_clock_run_all_timers(); return ret; }
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; }