[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 13/10] libxl: Introduce libxl__ev_devstate
Provide a new-style asynchronous facility for waiting for device states on xenbus. This will replace libxl__wait_for_device_state, after the callers have been updated in later patches. Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> --- tools/libxl/libxl_event.c | 74 ++++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl_internal.h | 41 +++++++++++++++++++++++ 2 files changed, 115 insertions(+), 0 deletions(-) diff --git a/tools/libxl/libxl_event.c b/tools/libxl/libxl_event.c index c594494..c26210b 100644 --- a/tools/libxl/libxl_event.c +++ b/tools/libxl/libxl_event.c @@ -506,6 +506,80 @@ void libxl__ev_xswatch_deregister(libxl__gc *gc, libxl__ev_xswatch *w) } /* + * waiting for device state + */ + +static void devstate_watch_callback(libxl__egc *egc, libxl__ev_xswatch *watch, + const char *watch_path, const char *event_path) +{ + libxl__ev_devstate *ds; + libxl__gc *gc = &egc->gc; + GET_CONTAINING_STRUCT(ds, watch, watch); + int rc; + + char *sstate = libxl__xs_read(&egc->gc, XBT_NULL, watch_path); + if (!sstate) { + if (errno == ENOENT) { + LIBXL__LOG(CTX, LIBXL__LOG_DEBUG, "backend %s wanted state %d" + " but it was removed", watch_path, ds->wanted); + rc = ERROR_INVAL; + } else { + LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR, "backend %s wanted state" + " %d but read failed", watch_path, ds->wanted); + rc = ERROR_FAIL; + } + } else { + int got = atoi(sstate); + if (got == ds->wanted) { + LIBXL__LOG(CTX, LIBXL__LOG_DEBUG, "backend %s wanted state %d ok", + watch_path, ds->wanted); + rc = 0; + } else { + LIBXL__LOG(CTX, LIBXL__LOG_DEBUG, "backend %s wanted state %d " + " still waiting state %d", watch_path, ds->wanted, got); + return; + } + } + libxl__ev_devstate_cancel(&egc->gc, ds); + ds->callback(egc, ds, rc); +} + +static void devstate_timeout(libxl__egc *egc, libxl__ev_time *ev, + const struct timeval *requested_abs) +{ + libxl__ev_devstate *ds; + libxl__gc *gc = &egc->gc; + GET_CONTAINING_STRUCT(ds, ev, timeout); + LIBXL__LOG(CTX, LIBXL__LOG_DEBUG, "backend %s wanted state %d " + " timed out", ds->watch.path, ds->wanted); + libxl__ev_devstate_cancel(&egc->gc, ds); + ds->callback(egc, ds, ERROR_TIMEDOUT); +} + +int libxl__ev_devstate_wait(libxl__gc *gc, libxl__ev_devstate *ds, + libxl__ev_devstate_callback cb, + const char *state_path, int state, int milliseconds) +{ + int rc; + + ds->wanted = state; + + rc = libxl__ev_time_register_rel(gc, &ds->timeout, devstate_timeout, + milliseconds); + if (rc) goto out; + + rc = libxl__ev_xswatch_register(gc, &ds->watch, devstate_watch_callback, + state_path); + if (rc) goto out; + + return 0; + + out: + libxl__ev_devstate_cancel(gc, ds); + return rc; +} + +/* * osevent poll */ diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index e0c2ad6..6c87290 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -683,6 +683,47 @@ _hidden int libxl__wait_for_device_state(libxl__gc *gc, struct timeval *tv, libxl__device_state_handler handler); /* + * libxl__ev_devstate - waits a given time for a device to + * reach a given state. Follows the libxl_ev_* conventions. + * Will generate only one event, and after that is automatically + * cancelled. + */ +typedef struct libxl__ev_devstate libxl__ev_devstate; +typedef void libxl__ev_devstate_callback(libxl__egc *egc, libxl__ev_devstate*, + int rc); + /* rc will be 0, ERROR_TIMEDOUT, ERROR_INVAL (meaning path was removed), + * or ERROR_FAIL if other stuff went wrong (in which latter case, logged) */ + +struct libxl__ev_devstate { + /* read-only for caller, who may read only when waiting: */ + int wanted; + libxl__ev_devstate_callback *callback; + /* as for the remainder, read-only public parts may also be + * read by the caller (notably, watch.path), but only when waiting: */ + libxl__ev_xswatch watch; + libxl__ev_time timeout; +}; + +static inline void libxl__ev_devstate_init(libxl__ev_devstate *ds) +{ + libxl__ev_time_init(&ds->timeout); + libxl__ev_xswatch_init(&ds->watch); +} + +static inline void libxl__ev_devstate_cancel(libxl__gc *gc, + libxl__ev_devstate *ds) +{ + libxl__ev_time_deregister(gc,&ds->timeout); + libxl__ev_xswatch_deregister(gc,&ds->watch); +} + +_hidden int libxl__ev_devstate_wait(libxl__gc *gc, libxl__ev_devstate *ds, + libxl__ev_devstate_callback cb, + const char *state_path, + int state, int milliseconds); + + +/* * libxl__try_phy_backend - Check if there's support for the passed * type of file using the PHY backend * st_mode: mode_t of the file, as returned by stat function -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |