[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.