CTX_UNLOCK;
}
+short libxl__fd_poll_recheck(libxl__egc *egc, int fd, short events) {
+ struct pollfd check;
+ int r;
+
+ for (;;) {
+ check.fd = fd;
+ check.events = events;
+ r = poll(&check, 1, 0);
+ DBG("poll recheck fd=%d r=%d revents=%#x", fd, r, check.revents);
+ if (!r)
+ break;
+ if (r==1)
+ break;
+ assert(r<0);
+ if (errno != EINTR) {
+ LIBXL__EVENT_DISASTER(egc, "failed poll to check for fd", errno, 0);
+ return 0;
+ }
+ }
+ assert(!!r == !!check.revents);
+ return check.revents;
+}
+
/*
* timeouts
*/
{
EGC_GC;
libxl__ev_evtchn *evev;
- int r, rc;
+ int rc;
evtchn_port_or_error_t port;
- struct pollfd recheck;
rc = evtchn_revents_check(egc, revents);
if (rc) return;
* held continuously since someone noticed the fd. Normally
* this wouldn't be a problem but evtchn devices don't always
* honour O_NONBLOCK (see xenctrl.h). */
-
- recheck.fd = fd;
- recheck.events = POLLIN;
- recheck.revents = 0;
- r = poll(&recheck, 1, 0);
- DBG("ev_evtchn recheck r=%d revents=%#x", r, recheck.revents);
- if (r < 0) {
- LIBXL__EVENT_DISASTER(egc,
- "unexpected failure polling event channel fd for recheck",
- errno, 0);
- return;
- }
- if (r == 0)
+ revents = libxl__fd_poll_recheck(egc,fd,POLLIN);
+ if (!revents)
break;
- rc = evtchn_revents_check(egc, recheck.revents);
+ rc = evtchn_revents_check(egc, revents);
if (rc) return;
/* OK, that's that workaround done. We can actually check for
if (!ev) goto out;
if (ev->fd != fd) goto out;
- struct pollfd check;
- for (;;) {
- check.fd = fd;
- check.events = ev->events;
- int r = poll(&check, 1, 0);
- if (!r)
- goto out;
- if (r==1)
- break;
- assert(r<0);
- if (errno != EINTR) {
- LIBXL__EVENT_DISASTER(egc, "failed poll to check for fd", errno, 0);
- goto out;
- }
- }
+ short current_revents = libxl__fd_poll_recheck(egc, ev->fd, ev->events);
- if (check.revents)
- ev->func(egc, ev, fd, ev->events, check.revents);
+ if (current_revents)
+ ev->func(egc, ev, fd, ev->events, current_revents);
out:
CTX_UNLOCK;