libxl: events: Deregister evtchn fd when not needed

We want to have no fd events registered when we are idle.
In this patch, deal with the evtchn fd:

 * Defer setup of the evtchn handle to the first use.
 * Defer registration of the evtchn fd; register as needed on use.
 * When cancelling an evtchn wait, or when wait setup fails, check
   whether there are now no evtchn waits and if so deregister the fd.
 * On libxl teardown, the evtchn fd should therefore be unregistered.
   assert that this is the case.

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Ian Campbell <ian.campbell@citrix.com>
Release-Acked-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
v2: Do not bother putting evtchn_fd in the ctx; instead, get it
     from xc_evtchn_fd when we need it.  (Cosmetic.)
    Do not register the evtchn fd multiple times: check it's not
     registered before we call libxl__ev_fd_register.  (Bugfix.)
This commit is contained in:
Ian Jackson authored and Ian Jackson committed 2014-12-10 13:48:31 +00:00
1 parent 5a96825745
commit 2ffeb5d7f5
2 files changed
+18 -7

No files matched your search

+1 -3
View File
@@ -118,8 +118,6 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version,
rc = ERROR_FAIL; goto out;
}
rc = libxl__ctx_evtchn_init(gc);
*pctx = ctx;
return 0;
@@ -166,7 +164,7 @@ int libxl_ctx_free(libxl_ctx *ctx)
for (i = 0; i < ctx->watch_nslots; i++)
assert(!libxl__watch_slot_contents(gc, i));
assert(!libxl__ev_fd_isregistered(&ctx->watch_efd));
libxl__ev_fd_deregister(gc, &ctx->evtchn_efd);
assert(!libxl__ev_fd_isregistered(&ctx->evtchn_efd));
assert(!libxl__ev_fd_isregistered(&ctx->sigchld_selfpipe_efd));
/* Now there should be no more events requested from the application: */
+17 -4
View File
@@ -739,10 +739,6 @@ int libxl__ctx_evtchn_init(libxl__gc *gc) {
rc = libxl_fd_set_nonblock(CTX, fd, 1);
if (rc) goto out;
rc = libxl__ev_fd_register(gc, &CTX->evtchn_efd,
evtchn_fd_callback, fd, POLLIN);
if (rc) goto out;
CTX->xce = xce;
return 0;
@@ -751,6 +747,12 @@ int libxl__ctx_evtchn_init(libxl__gc *gc) {
return rc;
}
static void evtchn_check_fd_deregister(libxl__gc *gc)
{
if (CTX->xce && LIBXL_LIST_EMPTY(&CTX->evtchns_waiting))
libxl__ev_fd_deregister(gc, &CTX->evtchn_efd);
}
int libxl__ev_evtchn_wait(libxl__gc *gc, libxl__ev_evtchn *evev)
{
int r, rc;
@@ -758,6 +760,15 @@ int libxl__ev_evtchn_wait(libxl__gc *gc, libxl__ev_evtchn *evev)
DBG("ev_evtchn=%p port=%d wait (was waiting=%d)",
evev, evev->port, evev->waiting);
rc = libxl__ctx_evtchn_init(gc);
if (rc) goto out;
if (!libxl__ev_fd_isregistered(&CTX->evtchn_efd)) {
rc = libxl__ev_fd_register(gc, &CTX->evtchn_efd, evtchn_fd_callback,
xc_evtchn_fd(CTX->xce), POLLIN);
if (rc) goto out;
}
if (evev->waiting)
return 0;
@@ -773,6 +784,7 @@ int libxl__ev_evtchn_wait(libxl__gc *gc, libxl__ev_evtchn *evev)
return 0;
out:
evtchn_check_fd_deregister(gc);
return rc;
}
@@ -786,6 +798,7 @@ void libxl__ev_evtchn_cancel(libxl__gc *gc, libxl__ev_evtchn *evev)
evev->waiting = 0;
LIBXL_LIST_REMOVE(evev, entry);
evtchn_check_fd_deregister(gc);
}
/*
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.