aio: add aio_notify
With this change async.c does not rely anymore on any service from main-loop.c, i.e. it is completely self-contained. Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
e3713e001f
commit
2f4dc3c1b2
30
async.c
30
async.c
|
@ -30,6 +30,7 @@
|
||||||
/* bottom halves (can be seen as timers which expire ASAP) */
|
/* bottom halves (can be seen as timers which expire ASAP) */
|
||||||
|
|
||||||
struct QEMUBH {
|
struct QEMUBH {
|
||||||
|
AioContext *ctx;
|
||||||
QEMUBHFunc *cb;
|
QEMUBHFunc *cb;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
QEMUBH *next;
|
QEMUBH *next;
|
||||||
|
@ -42,6 +43,7 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
|
||||||
{
|
{
|
||||||
QEMUBH *bh;
|
QEMUBH *bh;
|
||||||
bh = g_malloc0(sizeof(QEMUBH));
|
bh = g_malloc0(sizeof(QEMUBH));
|
||||||
|
bh->ctx = ctx;
|
||||||
bh->cb = cb;
|
bh->cb = cb;
|
||||||
bh->opaque = opaque;
|
bh->opaque = opaque;
|
||||||
bh->next = ctx->first_bh;
|
bh->next = ctx->first_bh;
|
||||||
|
@ -101,8 +103,7 @@ void qemu_bh_schedule(QEMUBH *bh)
|
||||||
return;
|
return;
|
||||||
bh->scheduled = 1;
|
bh->scheduled = 1;
|
||||||
bh->idle = 0;
|
bh->idle = 0;
|
||||||
/* stop the currently executing CPU to execute the BH ASAP */
|
aio_notify(bh->ctx);
|
||||||
qemu_notify_event();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_bh_cancel(QEMUBH *bh)
|
void qemu_bh_cancel(QEMUBH *bh)
|
||||||
|
@ -177,11 +178,20 @@ aio_ctx_dispatch(GSource *source,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
aio_ctx_finalize(GSource *source)
|
||||||
|
{
|
||||||
|
AioContext *ctx = (AioContext *) source;
|
||||||
|
|
||||||
|
aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL);
|
||||||
|
event_notifier_cleanup(&ctx->notifier);
|
||||||
|
}
|
||||||
|
|
||||||
static GSourceFuncs aio_source_funcs = {
|
static GSourceFuncs aio_source_funcs = {
|
||||||
aio_ctx_prepare,
|
aio_ctx_prepare,
|
||||||
aio_ctx_check,
|
aio_ctx_check,
|
||||||
aio_ctx_dispatch,
|
aio_ctx_dispatch,
|
||||||
NULL
|
aio_ctx_finalize
|
||||||
};
|
};
|
||||||
|
|
||||||
GSource *aio_get_g_source(AioContext *ctx)
|
GSource *aio_get_g_source(AioContext *ctx)
|
||||||
|
@ -190,9 +200,21 @@ GSource *aio_get_g_source(AioContext *ctx)
|
||||||
return &ctx->source;
|
return &ctx->source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aio_notify(AioContext *ctx)
|
||||||
|
{
|
||||||
|
event_notifier_set(&ctx->notifier);
|
||||||
|
}
|
||||||
|
|
||||||
AioContext *aio_context_new(void)
|
AioContext *aio_context_new(void)
|
||||||
{
|
{
|
||||||
return (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
|
AioContext *ctx;
|
||||||
|
ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
|
||||||
|
event_notifier_init(&ctx->notifier, false);
|
||||||
|
aio_set_event_notifier(ctx, &ctx->notifier,
|
||||||
|
(EventNotifierHandler *)
|
||||||
|
event_notifier_test_and_clear, NULL);
|
||||||
|
|
||||||
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void aio_context_ref(AioContext *ctx)
|
void aio_context_ref(AioContext *ctx)
|
||||||
|
|
18
qemu-aio.h
18
qemu-aio.h
|
@ -62,6 +62,9 @@ typedef struct AioContext {
|
||||||
* no callbacks are removed while we're walking and dispatching callbacks.
|
* no callbacks are removed while we're walking and dispatching callbacks.
|
||||||
*/
|
*/
|
||||||
int walking_bh;
|
int walking_bh;
|
||||||
|
|
||||||
|
/* Used for aio_notify. */
|
||||||
|
EventNotifier notifier;
|
||||||
} AioContext;
|
} AioContext;
|
||||||
|
|
||||||
/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
|
/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
|
||||||
|
@ -101,6 +104,21 @@ void aio_context_unref(AioContext *ctx);
|
||||||
*/
|
*/
|
||||||
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
|
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aio_notify: Force processing of pending events.
|
||||||
|
*
|
||||||
|
* Similar to signaling a condition variable, aio_notify forces
|
||||||
|
* aio_wait to exit, so that the next call will re-examine pending events.
|
||||||
|
* The caller of aio_notify will usually call aio_wait again very soon,
|
||||||
|
* or go through another iteration of the GLib main loop. Hence, aio_notify
|
||||||
|
* also has the side effect of recalculating the sets of file descriptors
|
||||||
|
* that the main loop waits for.
|
||||||
|
*
|
||||||
|
* Calling aio_notify is rarely necessary, because for example scheduling
|
||||||
|
* a bottom half calls it already.
|
||||||
|
*/
|
||||||
|
void aio_notify(AioContext *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aio_bh_poll: Poll bottom halves for an AioContext.
|
* aio_bh_poll: Poll bottom halves for an AioContext.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue