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 {
if (!ao) goto out;
ao->magic = LIBXL__AO_MAGIC;
+ ao->constructing = 1;
ao->in_initiator = 1;
ao->poller = 0;
ao->domid = domid;
int rc;
assert(ao->magic == LIBXL__AO_MAGIC);
+ assert(ao->constructing);
assert(ao->in_initiator);
+ ao->constructing = 0;
if (ao->poller) {
/* Caller wants it done synchronously. */
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;
* operation ("ao") machinery. The function should take a parameter
* const libxl_asyncop_how *ao_how and must start with a call to
* AO_INITIATOR_ENTRY. These functions MAY NOT be called from
- * outside libxl, because they can cause reentrancy callbacks.
+ * inside 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:
*
* 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
libxl__ctx_lock(ctx); \
libxl__ao *ao = libxl__ao_create(ctx, domid, ao_how); \
if (!ao) { libxl__ctx_unlock(ctx); return ERROR_NOMEM; } \
+ libxl__egc egc[1]; LIBXL_INIT_EGC(egc[0],ctx); \
AO_GC;
#define AO_INPROGRESS ({ \
libxl_ctx *ao__ctx = libxl__gc_owner(&ao->gc); \
int ao__rc = libxl__ao_inprogress(ao); \
libxl__ctx_unlock(ao__ctx); /* gc is now invalid */ \
+ EGC_FREE; \
(ao__rc); \
})
assert(rc); \
libxl__ao_abort(ao); \
libxl__ctx_unlock(ao__ctx); /* gc is now invalid */ \
+ EGC_FREE; \
(rc); \
})