[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1/3] libxl: ao: allow immediate completion
On Fri, 2012-02-17 at 18:43 +0000, Ian Jackson wrote: > Make it possible to complete an ao during its initating function. > > Previously this was not generally possible because initiators did not > have an egc. But there is no reason why an ao initiator should not > have an egc, so make the standard macros provide one. > > Change the internal documentation comments accordingly. (This change, > which means that an initiator function may call a completion callback > directly, is already consistent with the documented external API.) > > We also invent of a new state flag "constructing" which indicates > whether we are between ao__create and ao__inprogress. This is a > slightly optimisation which allows ao_complete to not bother poking > the wakeup pipe, since the logic in ao__inprogress will not run the > event loop if the ao is complete on entry. > > Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> > --- > tools/libxl/libxl_event.c | 8 ++++++-- > tools/libxl/libxl_internal.h | 13 +++++++++---- > 2 files changed, 15 insertions(+), 6 deletions(-) > > diff --git a/tools/libxl/libxl_event.c b/tools/libxl/libxl_event.c > index 271949a..dda9d6f 100644 > --- a/tools/libxl/libxl_event.c > +++ b/tools/libxl/libxl_event.c > @@ -1225,7 +1225,9 @@ void libxl__ao_complete(libxl__egc *egc, libxl__ao *ao, > int rc) > > if (ao->poller) { > assert(ao->in_initiator); > - libxl__poller_wakeup(egc, ao->poller); > + if (!ao->constructing) > + /* don't bother with this if we're not in the event loop */ > + libxl__poller_wakeup(egc, ao->poller); > } else if (ao->how.callback) { > LIBXL_TAILQ_INSERT_TAIL(&egc->aos_for_callback, ao, > entry_for_callback); > } else { > @@ -1251,6 +1253,7 @@ libxl__ao *libxl__ao_create(libxl_ctx *ctx, uint32_t > domid, > if (!ao) goto out; > > ao->magic = LIBXL__AO_MAGIC; > + ao->constructing = 1; > ao->in_initiator = 1; > ao->poller = 0; > ao->domid = domid; > @@ -1275,7 +1278,8 @@ int libxl__ao_inprogress(libxl__ao *ao) > int rc; > > assert(ao->magic == LIBXL__AO_MAGIC); > - assert(ao->in_initiator); > + assert(ao->constructing && ao->in_initiator); Doing two asserts will make it clearer which condition is not satisfied if we ever see this. > + ao->constructing = 0; > > if (ao->poller) { > /* Caller wants it done synchronously. */ > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h > index 8846c68..49688e1 100644 > --- a/tools/libxl/libxl_internal.h > +++ b/tools/libxl/libxl_internal.h > @@ -337,7 +337,7 @@ struct libxl__egc { > > struct libxl__ao { > uint32_t magic; > - unsigned in_initiator:1, complete:1, notified:1; > + unsigned constructing:1, in_initiator:1, complete:1, notified:1; > int rc; > libxl__gc gc; > libxl_asyncop_how how; > @@ -1185,6 +1185,10 @@ _hidden void libxl__egc_cleanup(libxl__egc *egc); > * AO_INITIATOR_ENTRY. These functions MAY NOT be called from > * outside libxl, because they can cause reentrancy callbacks. > * > + * For the same reason functions taking an ao_how may make themselves > + * an egc with EGC_INIT (and they will generally want to, to be able > + * to immediately complete an ao during its setup). > + * > * Lifecycle of an ao: > * > * - Created by libxl__ao_create (or the AO_CREATE convenience macro). > @@ -1214,8 +1218,7 @@ _hidden void libxl__egc_cleanup(libxl__egc *egc); > * directly or indirectly, should call libxl__ao_complete (with the > * ctx locked, as it will generally already be in any event callback > * function). This must happen exactly once for each ao (and not if > - * the ao has been destroyed, obviously), and it may not happen > - * until libxl__ao_inprogress has been called on the ao. > + * the ao has been destroyed, obviously). > * > * - Note that during callback functions, two gcs are available: > * - The one in egc, whose lifetime is only this callback > @@ -1229,12 +1232,13 @@ _hidden void libxl__egc_cleanup(libxl__egc *egc); > libxl__ctx_lock(ctx); \ > libxl__ao *ao = libxl__ao_create(ctx, domid, ao_how); \ > if (!ao) { libxl__ctx_unlock(ctx); return ERROR_NOMEM; } \ > - AO_GC; > + EGC_INIT(ctx); This means that the "gc" within a function which uses this macro is now "&egc->gc" rather than "&ao->gc". However the egc->gc is cleaned up in AO_INPROGRESS/AO_ABORT whereas the ao->gc persists until the activity completes which is a meaningful difference to think about. Now, as it happens, none of the existing callers of AO_CREATE actually use the gc for anything (they just pass it around a bit). If, hypothetically, libxl__device_from_disk() were to allocate some memory into the libxl__device passed to libxl__initiate_device_remove(ao,device) then would initiate_device_remove be expected to copy any part of device which it wanted to keep until completion? Another difference is that any function calling AO_CREATE cannot now be called from within libxl, since it now calls LIBXL__INIT_EGC which has this restriction. libxl_cdrom_insert does not obey this new restriction. Ian. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |