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); }
static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds, fd_set *xfds, uint32_t *cur_timeout) { GMainContext *context = g_main_context_default(); int i; int timeout = 0; g_main_context_prepare(context, &max_priority); n_poll_fds = g_main_context_query(context, max_priority, &timeout, poll_fds, ARRAY_SIZE(poll_fds)); g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds)); for (i = 0; i < n_poll_fds; i++) { GPollFD *p = &poll_fds[i]; if ((p->events & G_IO_IN)) { FD_SET(p->fd, rfds); *max_fd = MAX(*max_fd, p->fd); } if ((p->events & G_IO_OUT)) { FD_SET(p->fd, wfds); *max_fd = MAX(*max_fd, p->fd); } if ((p->events & G_IO_ERR)) { FD_SET(p->fd, xfds); *max_fd = MAX(*max_fd, p->fd); } } if (timeout >= 0 && timeout < *cur_timeout) { *cur_timeout = timeout; } }
static void glibPrepare (CompDisplay *display, GMainContext *context) { int nFds = 0; int timeout = -1; int i; GLIB_DISPLAY (display); g_main_context_prepare (context, &gd->maxPriority); do { if (nFds > gd->fdsSize) { if (gd->fds) free (gd->fds); gd->fds = malloc ((sizeof (GPollFD) + sizeof (GLibWatch)) * nFds); if (!gd->fds) { nFds = 0; break; } gd->watch = (GLibWatch *) (gd->fds + nFds); gd->fdsSize = nFds; } nFds = g_main_context_query (context, gd->maxPriority, &timeout, gd->fds, gd->fdsSize); } while (nFds > gd->fdsSize); if (timeout < 0) timeout = INT_MAX; for (i = 0; i < nFds; i++) { gd->watch[i].display = display; gd->watch[i].index = i; gd->watch[i].handle = compAddWatchFd (gd->fds[i].fd, gd->fds[i].events, glibCollectEvents, &gd->watch[i]); } gd->nFds = nFds; gd->timeoutHandle = compAddTimeout (timeout, timeout, glibDispatchAndPrepare, display); }
/** @internal Block until wait object is signaled or timeout. * * This function waits for wait objects and the timers associated with * the root object. When any wait object is signaled or timer is * expired, it invokes the callbacks. * * This function returns when a callback has been invoked or @c tout * milliseconds is elapsed. * * @param self pointer to port * @param tout timeout in milliseconds * * @Return * Milliseconds to the next invocation of timer, or @c SU_WAIT_FOREVER if * there are no active timers. */ su_duration_t su_source_step(su_port_t *self, su_duration_t tout) { GMainContext *gmc; enter; gmc = g_source_get_context(self->sup_source); if (gmc && g_main_context_acquire(gmc)) { GPollFD *fds = NULL; gint fds_size = 0; gint fds_wait; gint priority = G_MAXINT; gint src_tout = -1; g_main_context_prepare(gmc, &priority); fds_wait = g_main_context_query(gmc, priority, &src_tout, NULL, 0); while (fds_wait > fds_size) { fds = g_alloca(fds_wait * sizeof(fds[0])); fds_size = fds_wait; fds_wait = g_main_context_query(gmc, priority, &src_tout, fds, fds_size); } if (src_tout >= 0 && tout > (su_duration_t)src_tout) tout = src_tout; su_wait((su_wait_t *)fds, fds_wait, tout); g_main_context_check(gmc, priority, fds, fds_wait); g_main_context_dispatch(gmc); g_main_context_release(gmc); } return 0; }
CAMLprim value lwt_glib_iter(value may_block) { GMainContext *gc; gint max_priority, timeout; GPollFD *pollfds = NULL; gint pollfds_size = 0; gint nfds; gint i; /* Get the main context. */ gc = g_main_context_default(); /* Try to acquire it. */ if (!g_main_context_acquire(gc)) caml_failwith("Lwt_glib.iter"); /* Dispatch pending events. */ g_main_context_dispatch(gc); /* Prepare the context for polling. */ g_main_context_prepare(gc, &max_priority); /* Get all file descriptors to poll. */ while (pollfds_size < (nfds = g_main_context_query(gc, max_priority, &timeout, pollfds, pollfds_size))) { free(pollfds); pollfds_size = nfds; pollfds = lwt_unix_malloc(pollfds_size * sizeof (GPollFD)); } /* Clear all revents fields. */ for (i = 0; i < nfds; i++) pollfds[i].revents = 0; /* Set the timeout to 0 if we do not want to block. */ if (!Bool_val(may_block)) timeout = 0; /* Do the blocking call. */ caml_enter_blocking_section(); g_main_context_get_poll_func(gc)(pollfds, nfds, timeout); caml_leave_blocking_section(); /* Let glib parse the result. */ g_main_context_check(gc, max_priority, pollfds, nfds); /* Release the context. */ g_main_context_release(gc); free(pollfds); return Val_unit; }
void mainLoop () { GPollFD dpy_pollfd = {x_fd, G_IO_IN, 0};// | G_IO_HUP | G_IO_ERR GSourceFuncs x11_source_funcs = { x11_fd_prepare, x11_fd_check, x11_fd_dispatch, NULL, /* finalize */ NULL, /* closure_callback */ NULL /* closure_marshal */ }; GSource *x11_source = g_source_new(&x11_source_funcs, sizeof(x11_source_t)); ((x11_source_t*)x11_source)->dpy = dpy; ((x11_source_t*)x11_source)->pending_events = 0; g_source_add_poll(x11_source, &dpy_pollfd); g_source_attach(x11_source,NULL); /* must use default context so that DBus signal handling is not impeded */ { #if 0 GMainLoop *mainloop = g_main_loop_new(NULL,FALSE); g_main_loop_run(mainloop); #else GMainContext *ctx = g_main_context_default (); GPollFD qfd_a[10]; do { gint timeout; int priority = 0; int i; g_main_context_prepare (ctx, &priority); gint recordCount = g_main_context_query(ctx, 2, &timeout, qfd_a, 10); /* we need to specify the timeout, in order for glib signals to propagate properly Ain't that stupid!!!!!! */ g_poll (qfd_a, recordCount, 200); /* don't want to trust glib's main loop with our X event handling - it gets all screwed up */ #if 1 for (i = 0 ; i < recordCount ; ++i) if (qfd_a[i].revents) { /* show_progress ( "%d: fd = %d, events = 0x%X, revents = 0x%X", time(NULL), qfd_a[i].fd, qfd_a[i].events, qfd_a[i].revents); */ if (qfd_a[i].fd == x_fd) { HandleXEvent(); qfd_a[i].revents = 0; } } #endif g_main_context_check(ctx, -1, qfd_a, recordCount); g_main_context_dispatch (ctx); }while (1); #endif } }
CAMLprim value lwt_glib_get_sources(value Unit) { gint timeout; int i; int events; GPollFD *gpollfd; CAMLparam0(); CAMLlocal3(fds, watches, result); g_main_context_dispatch(gc); g_main_context_prepare(gc, &max_priority); while (fds_count < (n_fds = g_main_context_query(gc, max_priority, &timeout, gpollfds, fds_count))) { free(gpollfds); fds_count = n_fds; gpollfds = lwt_unix_malloc(fds_count * sizeof (GPollFD)); } fds = caml_alloc_tuple(n_fds); watches = caml_alloc_tuple(n_fds); for (i = 0; i < n_fds; i++) { gpollfd = gpollfds + i; gpollfd->revents = 0; events = 0; if (gpollfd->events & G_IO_IN) events |= 1; if (gpollfd->events & G_IO_OUT) events |= 2; #if defined(LWT_ON_WINDOWS) /* On windows, glib file descriptors are handles */ Field(fds, i) = alloc_fd((HANDLE)gpollfd->fd); #else Field(fds, i) = Val_int(gpollfd->fd); if (gpollfd->fd < 0) events = 0; #endif Field(watches, i) = Val_int(events); } result = caml_alloc_tuple(3); Store_field(result, 0, fds); Store_field(result, 1, watches); Store_field(result, 2, caml_copy_double(timeout * 1e-3)); CAMLreturn(result); }
static int glib_query(void *user_data, struct pollfd *fds, int nfd, int *timeout) { glib_glue_t *glue = (glib_glue_t *)user_data; int n; mrp_debug("*** GMainLoop <%p>: querying...", user_data); glib_acquire(glue); n = g_main_context_query(glue->mc, glue->maxprio, timeout, (GPollFD *)fds, nfd); glib_release(glue); mrp_debug("GMainLoop <%p>: %d fds, timeout %d", user_data, n, *timeout); return n; }
MOSHEXPORT int mglib_loop_start_wait(void* q, void** c, void* fds, int len){ int count; gint timeout; count = g_main_context_query(g_main_context_default(), 999999, /* FIXME: */ &timeout, fds, len); c[0] = fds; c[1] = (uintptr_t)count; c[2] = (intptr_t)timeout; //printf("push %x\n",(int)fds); if(count <= len){ /* perform actual poll() */ g_async_queue_push((GAsyncQueue *)q, c); } return count; /* pass this value to loop_dispatch */ }
static mst_Boolean main_loop_poll (int ms) { GMainContext *context; int timeout; if (!loop || !g_main_loop_is_running (loop)) return FALSE; if (!fds) { fds = g_new (GPollFD, 20); allocated_nfds = 20; } context = g_main_loop_get_context (loop); if (!g_main_context_acquire (context)) abort (); timeout = -1; g_main_context_prepare (context, &maxprio); while ((nfds = g_main_context_query (context, maxprio, &timeout, fds, allocated_nfds)) > allocated_nfds) { g_free (fds); fds = g_new (GPollFD, nfds); allocated_nfds = nfds; } if (ms != -1 && (timeout == -1 || timeout > ms)) timeout = ms; g_main_context_release (context); g_poll (fds, nfds, timeout); return g_main_context_check (context, maxprio, fds, nfds); }
int xg_select (int fds_lim, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, EMACS_TIME *timeout, sigset_t *sigmask) { SELECT_TYPE all_rfds, all_wfds; EMACS_TIME tmo, *tmop = timeout; GMainContext *context; int have_wfds = wfds != NULL; GPollFD gfds_buf[128]; GPollFD *gfds = gfds_buf; int gfds_size = sizeof gfds_buf / sizeof *gfds_buf; int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; int i, nfds, tmo_in_millisec; USE_SAFE_ALLOCA; if (! (x_in_use && g_main_context_pending (context = g_main_context_default ()))) return pselect (fds_lim, rfds, wfds, efds, timeout, sigmask); if (rfds) all_rfds = *rfds; else FD_ZERO (&all_rfds); if (wfds) all_wfds = *wfds; else FD_ZERO (&all_wfds); n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, gfds_size); if (gfds_size < n_gfds) { SAFE_NALLOCA (gfds, sizeof *gfds, n_gfds); gfds_size = n_gfds; n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, gfds_size); } for (i = 0; i < n_gfds; ++i) { if (gfds[i].events & G_IO_IN) { FD_SET (gfds[i].fd, &all_rfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; } if (gfds[i].events & G_IO_OUT) { FD_SET (gfds[i].fd, &all_wfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; have_wfds = 1; } } SAFE_FREE (); if (tmo_in_millisec >= 0) { tmo = make_emacs_time (tmo_in_millisec / 1000, 1000 * 1000 * (tmo_in_millisec % 1000)); if (!timeout || EMACS_TIME_LT (tmo, *timeout)) tmop = &tmo; } fds_lim = max_fds + 1; nfds = pselect (fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, efds, tmop, sigmask); if (nfds < 0) retval = nfds; else if (nfds > 0) { for (i = 0; i < fds_lim; ++i) { if (FD_ISSET (i, &all_rfds)) { if (rfds && FD_ISSET (i, rfds)) ++retval; else ++our_fds; } else if (rfds) FD_CLR (i, rfds); if (have_wfds && FD_ISSET (i, &all_wfds)) { if (wfds && FD_ISSET (i, wfds)) ++retval; else ++our_fds; } else if (wfds) FD_CLR (i, wfds); if (efds && FD_ISSET (i, efds)) ++retval; } } if (our_fds > 0 || (nfds == 0 && tmop == &tmo)) { /* If Gtk+ is in use eventually gtk_main_iteration will be called, unless retval is zero. */ #ifdef USE_GTK if (retval == 0) #endif while (g_main_context_pending (context)) g_main_context_dispatch (context); /* To not have to recalculate timeout, return like this. */ if (retval == 0) { retval = -1; errno = EINTR; } } return retval; }
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; }
CAMLprim value lwt_glib_poll(value val_fds, value val_count, value val_timeout) { gint timeout, lwt_timeout; long count; int i; GPollFD *gpollfd; gint events, revents; CAMLparam3(val_fds, val_count, val_timeout); CAMLlocal5(node, src, node_result, src_result, tmp); count = Long_val(val_count); g_main_context_dispatch(gc); g_main_context_prepare(gc, &max_priority); while (fds_count < count + (n_fds = g_main_context_query(gc, max_priority, &timeout, gpollfds, fds_count))) { free(gpollfds); fds_count = n_fds + count; gpollfds = lwt_unix_malloc(fds_count * sizeof (GPollFD)); } /* Clear all revents fields. */ for (i = 0; i < n_fds + count; i++) gpollfds[i].revents = 0; /* Add all Lwt fds. */ for (i = n_fds, node = val_fds; i < n_fds + count; i++, node = Field(node, 1)) { src = Field(node, 0); gpollfd = gpollfds + i; #if defined(LWT_ON_WINDOWS) gpollfd->fd = Handle_val(Field(src, 0)); #else gpollfd->fd = Int_val(Field(src, 0)); #endif events = 0; if (Bool_val(Field(src, 1))) events |= G_IO_IN; if (Bool_val(Field(src, 2))) events |= G_IO_OUT; gpollfd->events = events; } lwt_timeout = Int_val(val_timeout); if (timeout < 0 || (lwt_timeout >= 0 && lwt_timeout < timeout)) timeout = lwt_timeout; /* Do the blocking call. */ caml_enter_blocking_section(); g_main_context_get_poll_func(gc)(gpollfds, n_fds + count, timeout); caml_leave_blocking_section(); g_main_context_check(gc, max_priority, gpollfds, n_fds); /* Build the result. */ node_result = Val_int(0); for (i = n_fds, node = val_fds; i < n_fds + count; i++, node = Field(node, 1)) { gpollfd = gpollfds + i; src_result = caml_alloc_tuple(3); src = Field(node, 0); Field(src_result, 0) = Field(src, 0); revents = gpollfd->revents; if (revents & G_IO_HUP) { /* Treat HUP as ready. There's no point continuing to wait on this FD. */ if (gpollfd->events & G_IO_IN) revents |= G_IO_IN; if (gpollfd->events & G_IO_OUT) revents |= G_IO_OUT; } Field(src_result, 1) = Val_bool(revents & G_IO_IN); Field(src_result, 2) = Val_bool(revents & G_IO_OUT); tmp = caml_alloc_tuple(2); Field(tmp, 0) = src_result; Field(tmp, 1) = node_result; node_result = tmp; } CAMLreturn(node_result); }
int xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timespec *timeout, sigset_t *sigmask) { fd_set all_rfds, all_wfds; struct timespec tmo; struct timespec *tmop = timeout; GMainContext *context; bool have_wfds = wfds != NULL; GPollFD gfds_buf[128]; GPollFD *gfds = gfds_buf; int gfds_size = ARRAYELTS (gfds_buf); int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; bool context_acquired = false; int i, nfds, tmo_in_millisec, must_free = 0; bool need_to_dispatch; context = g_main_context_default (); context_acquired = g_main_context_acquire (context); /* FIXME: If we couldn't acquire the context, we just silently proceed because this function handles more than just glib file descriptors. Note that, as implemented, this failure is completely silent: there is no feedback to the caller. */ if (rfds) all_rfds = *rfds; else FD_ZERO (&all_rfds); if (wfds) all_wfds = *wfds; else FD_ZERO (&all_wfds); n_gfds = (context_acquired ? g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, gfds_size) : -1); if (gfds_size < n_gfds) { /* Avoid using SAFE_NALLOCA, as that implicitly refers to the current thread. Using xnmalloc avoids thread-switching problems here. */ gfds = xnmalloc (n_gfds, sizeof *gfds); must_free = 1; gfds_size = n_gfds; n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, gfds_size); } for (i = 0; i < n_gfds; ++i) { if (gfds[i].events & G_IO_IN) { FD_SET (gfds[i].fd, &all_rfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; } if (gfds[i].events & G_IO_OUT) { FD_SET (gfds[i].fd, &all_wfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; have_wfds = true; } } if (must_free) xfree (gfds); if (n_gfds >= 0 && tmo_in_millisec >= 0) { tmo = make_timespec (tmo_in_millisec / 1000, 1000 * 1000 * (tmo_in_millisec % 1000)); if (!timeout || timespec_cmp (tmo, *timeout) < 0) tmop = &tmo; } fds_lim = max_fds + 1; nfds = thread_select (pselect, fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, efds, tmop, sigmask); if (nfds < 0) retval = nfds; else if (nfds > 0) { for (i = 0; i < fds_lim; ++i) { if (FD_ISSET (i, &all_rfds)) { if (rfds && FD_ISSET (i, rfds)) ++retval; else ++our_fds; } else if (rfds) FD_CLR (i, rfds); if (have_wfds && FD_ISSET (i, &all_wfds)) { if (wfds && FD_ISSET (i, wfds)) ++retval; else ++our_fds; } else if (wfds) FD_CLR (i, wfds); if (efds && FD_ISSET (i, efds)) ++retval; } } /* If Gtk+ is in use eventually gtk_main_iteration will be called, unless retval is zero. */ #ifdef USE_GTK need_to_dispatch = retval == 0; #else need_to_dispatch = true; #endif if (need_to_dispatch && context_acquired) { int pselect_errno = errno; /* Prevent g_main_dispatch recursion, that would occur without block_input wrapper, because event handlers call unblock_input. Event loop recursion was causing Bug#15801. */ block_input (); while (g_main_context_pending (context)) g_main_context_dispatch (context); unblock_input (); errno = pselect_errno; } if (context_acquired) g_main_context_release (context); /* To not have to recalculate timeout, return like this. */ if ((our_fds > 0 || (nfds == 0 && tmop == &tmo)) && (retval == 0)) { retval = -1; errno = EINTR; } return retval; }
int xg_select (int max_fds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, EMACS_TIME *timeout) { SELECT_TYPE all_rfds, all_wfds; EMACS_TIME tmo, *tmop = timeout; GMainContext *context = g_main_context_default (); int have_wfds = wfds != NULL; int n_gfds = 0, our_tmo = 0, retval = 0, our_fds = 0; int i, nfds, tmo_in_millisec; if (rfds) memcpy (&all_rfds, rfds, sizeof (all_rfds)); else FD_ZERO (&all_rfds); if (wfds) memcpy (&all_wfds, wfds, sizeof (all_rfds)); else FD_ZERO (&all_wfds); /* Update event sources in GLib. */ g_main_context_pending (context); do { if (n_gfds > gfds_size) { while (n_gfds > gfds_size) gfds_size *= 2; xfree (gfds); gfds = xmalloc (sizeof (*gfds) * gfds_size); } n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, gfds_size); } while (n_gfds > gfds_size); for (i = 0; i < n_gfds; ++i) { if (gfds[i].events & G_IO_IN) { FD_SET (gfds[i].fd, &all_rfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; } if (gfds[i].events & G_IO_OUT) { FD_SET (gfds[i].fd, &all_wfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; have_wfds = 1; } } if (tmo_in_millisec >= 0) { EMACS_SET_SECS_USECS (tmo, tmo_in_millisec/1000, 1000 * (tmo_in_millisec % 1000)); if (!timeout) our_tmo = 1; else { EMACS_TIME difference; EMACS_SUB_TIME (difference, tmo, *timeout); if (EMACS_TIME_NEG_P (difference)) our_tmo = 1; } if (our_tmo) tmop = &tmo; } nfds = select (max_fds+1, &all_rfds, have_wfds ? &all_wfds : NULL, efds, tmop); if (nfds < 0) retval = nfds; else if (nfds > 0) { for (i = 0; i < max_fds+1; ++i) { if (FD_ISSET (i, &all_rfds)) { if (rfds && FD_ISSET (i, rfds)) ++retval; else ++our_fds; } else if (rfds) FD_CLR (i, rfds); if (have_wfds && FD_ISSET (i, &all_wfds)) { if (wfds && FD_ISSET (i, wfds)) ++retval; else ++our_fds; } else if (wfds) FD_CLR (i, wfds); if (efds && FD_ISSET (i, efds)) ++retval; } } if (our_fds > 0 || (nfds == 0 && our_tmo)) { /* If Gtk+ is in use eventually gtk_main_iteration will be called, unless retval is zero. */ #ifdef USE_GTK if (retval == 0) #endif while (g_main_context_pending (context)) g_main_context_dispatch (context); /* To not have to recalculate timeout, return like this. */ if (retval == 0) { retval = -1; errno = EINTR; } } return retval; }
static int os_host_main_loop_wait(uint32_t timeout) { GMainContext *context = g_main_context_default(); int ret, i; PollingEntry *pe; WaitObjects *w = &wait_objects; gint poll_timeout; static struct timeval tv0; /* 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; } if (nfds >= 0) { ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0); if (ret != 0) { timeout = 0; } } 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 || timeout < poll_timeout) { poll_timeout = timeout; } qemu_mutex_unlock_iothread(); ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout); qemu_mutex_lock_iothread(); if (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); } /* If an edge-triggered socket event occurred, select will return a * positive result on the next iteration. We do not need to do anything * here. */ return ret; }
int xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timespec const *timeout, sigset_t const *sigmask) { fd_set all_rfds, all_wfds; struct timespec tmo; struct timespec const *tmop = timeout; GMainContext *context; int have_wfds = wfds != NULL; GPollFD gfds_buf[128]; GPollFD *gfds = gfds_buf; int gfds_size = ARRAYELTS (gfds_buf); int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; int i, nfds, tmo_in_millisec; bool need_to_dispatch; USE_SAFE_ALLOCA; context = g_main_context_default (); if (rfds) all_rfds = *rfds; else FD_ZERO (&all_rfds); if (wfds) all_wfds = *wfds; else FD_ZERO (&all_wfds); n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, gfds_size); if (gfds_size < n_gfds) { SAFE_NALLOCA (gfds, sizeof *gfds, n_gfds); gfds_size = n_gfds; n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, gfds_size); } for (i = 0; i < n_gfds; ++i) { if (gfds[i].events & G_IO_IN) { FD_SET (gfds[i].fd, &all_rfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; } if (gfds[i].events & G_IO_OUT) { FD_SET (gfds[i].fd, &all_wfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; have_wfds = 1; } } SAFE_FREE (); if (tmo_in_millisec >= 0) { tmo = make_timespec (tmo_in_millisec / 1000, 1000 * 1000 * (tmo_in_millisec % 1000)); if (!timeout || timespec_cmp (tmo, *timeout) < 0) tmop = &tmo; } fds_lim = max_fds + 1; nfds = pselect (fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, efds, tmop, sigmask); if (nfds < 0) retval = nfds; else if (nfds > 0) { for (i = 0; i < fds_lim; ++i) { if (FD_ISSET (i, &all_rfds)) { if (rfds && FD_ISSET (i, rfds)) ++retval; else ++our_fds; } else if (rfds) FD_CLR (i, rfds); if (have_wfds && FD_ISSET (i, &all_wfds)) { if (wfds && FD_ISSET (i, wfds)) ++retval; else ++our_fds; } else if (wfds) FD_CLR (i, wfds); if (efds && FD_ISSET (i, efds)) ++retval; } } /* If Gtk+ is in use eventually gtk_main_iteration will be called, unless retval is zero. */ #ifdef USE_GTK need_to_dispatch = retval == 0; #else need_to_dispatch = true; #endif if (need_to_dispatch) { int pselect_errno = errno; /* Prevent g_main_dispatch recursion, that would occur without block_input wrapper, because event handlers call unblock_input. Event loop recursion was causing Bug#15801. */ block_input (); while (g_main_context_pending (context)) g_main_context_dispatch (context); unblock_input (); errno = pselect_errno; } /* To not have to recalculate timeout, return like this. */ if ((our_fds > 0 || (nfds == 0 && tmop == &tmo)) && (retval == 0)) { retval = -1; errno = EINTR; } return retval; }