[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 19/25] libxl: Fix an ao completion bug; document locking policy
On Wed, 2012-04-25 at 16:55 +0100, Ian Jackson wrote: > Document the concurrent access policies for libxl__ao and libxl__egc, > and their corresponding gcs. > > Fix a violation of the policy: > > If an ao was submitted and a callback requested, and while the > initiating function was still running on the original thread, the ao > is completed on another thread, the completing thread would improperly > concurrently access the ao with the initiating thread. > > Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx> > --- > tools/libxl/libxl_event.c | 7 +++++++ > tools/libxl/libxl_internal.h | 23 ++++++++++++++++++++++- > 2 files changed, 29 insertions(+), 1 deletions(-) > > diff --git a/tools/libxl/libxl_event.c b/tools/libxl/libxl_event.c > index 2f559d5..7e8d002 100644 > --- a/tools/libxl/libxl_event.c > +++ b/tools/libxl/libxl_event.c > @@ -897,6 +897,11 @@ void libxl__event_disaster(libxl__egc *egc, const char > *msg, int errnoval, > > static void egc_run_callbacks(libxl__egc *egc) > { > + /* > + * The callbacks must happen with the ctx unlocked. > + * See the comment near #define EGC_GC in libxl_internal.h and > + * those in the definitions of libxl__egc and libxl__ao. > + */ > EGC_GC; > libxl_event *ev, *ev_tmp; > > @@ -910,9 +915,11 @@ static void egc_run_callbacks(libxl__egc *egc) > entry_for_callback, ao_tmp) { > LIBXL_TAILQ_REMOVE(&egc->aos_for_callback, ao, entry_for_callback); > ao->how.callback(CTX, ao->rc, ao->how.u.for_callback); > + CTX_LOCK; > ao->notified = 1; > if (!ao->in_initiator) > libxl__ao__destroy(CTX, ao); > + CTX_UNLOCK; > } > } > > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h > index c238e86..26e0713 100644 > --- a/tools/libxl/libxl_internal.h > +++ b/tools/libxl/libxl_internal.h > @@ -369,7 +369,8 @@ struct libxl__gc { > }; > > struct libxl__egc { > - /* for event-generating functions only */ > + /* For event-generating functions only. > + * The egc and its gc may be accessed only on the creating thread. */ > struct libxl__gc gc; > struct libxl__event_list occurred_for_callback; > LIBXL_TAILQ_HEAD(, libxl__ao) aos_for_callback; > @@ -379,6 +380,20 @@ struct libxl__egc { > #define LIBXL__AO_MAGIC_DESTROYED 0xA0DEAD00ul > > struct libxl__ao { > + /* > + * An ao and its gc may be accessed only with the ctx lock held. > + * > + * Special exception: If an ao has been added to > + * egc->aos_for_callback, the thread owning the egc may remove the > + * ao from that list and make the callback without holding the > + * lock. > + * > + * Corresponding restriction: An ao may be added only to one > + * egc->aos_for_callback, once; rc and how must already have been > + * set and may not be subsequently modified. (This restriction is > + * easily and obviously met since the ao is queued for callback > + * only in libxl__ao_complete.) > + */ > uint32_t magic; > unsigned constructing:1, in_initiator:1, complete:1, notified:1; > int rc; > @@ -1356,6 +1371,12 @@ libxl__device_model_version_running(libxl__gc *gc, > uint32_t domid); > * should in any case not find it necessary to call egc-creators from > * within libxl. > * > + * The callbacks must all take place with the ctx unlocked because > + * the application is entitled to reenter libxl from them. This > + * would be bad not because the lock is not recursive (it is) but > + * because the application might make blocking libxl calls which > + * would hold the lock unreasonably long. > + * > * For the same reason libxl__egc_cleanup (or EGC_FREE) must be called > * with the ctx *unlocked*. So the right pattern has the EGC_... > * macro calls on the outside of the CTX_... ones. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |