diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-09-24 14:37:53 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-10-30 09:30:53 +0100 |
commit | 7c0628b20e7c56b7e04abb8b5f8d7da3f7cb87e8 (patch) | |
tree | 9d5ee71c6356c75ee356b81a764951c2ad919434 | |
parent | 4231c88d27d9e46e6ad6e6b7bbb6e442bcf9cd05 (diff) |
aio: add non-blocking variant of aio_wait
This will be used when polling the GSource attached to an AioContext.
Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | aio.c | 20 | ||||
-rw-r--r-- | async.c | 2 | ||||
-rw-r--r-- | main-loop.c | 2 | ||||
-rw-r--r-- | qemu-aio.h | 21 |
4 files changed, 32 insertions, 13 deletions
@@ -93,13 +93,16 @@ void aio_set_event_notifier(AioContext *ctx, (AioFlushHandler *)io_flush, notifier); } -bool aio_wait(AioContext *ctx) +bool aio_poll(AioContext *ctx, bool blocking) { + static struct timeval tv0; AioHandler *node; fd_set rdfds, wrfds; int max_fd = -1; int ret; - bool busy; + bool busy, progress; + + progress = false; /* * If there are callbacks left that have been queued, we need to call then. @@ -107,6 +110,11 @@ bool aio_wait(AioContext *ctx) * does not need a complete flush (as is the case for qemu_aio_wait loops). */ if (aio_bh_poll(ctx)) { + blocking = false; + progress = true; + } + + if (progress && !blocking) { return true; } @@ -142,11 +150,11 @@ bool aio_wait(AioContext *ctx) /* No AIO operations? Get us out of here */ if (!busy) { - return false; + return progress; } /* wait until next event */ - ret = select(max_fd, &rdfds, &wrfds, NULL, NULL); + ret = select(max_fd, &rdfds, &wrfds, NULL, blocking ? NULL : &tv0); /* if we have any readable fds, dispatch event */ if (ret > 0) { @@ -161,11 +169,13 @@ bool aio_wait(AioContext *ctx) if (!node->deleted && FD_ISSET(node->fd, &rdfds) && node->io_read) { + progress = true; node->io_read(node->opaque); } if (!node->deleted && FD_ISSET(node->fd, &wrfds) && node->io_write) { + progress = true; node->io_write(node->opaque); } @@ -181,5 +191,5 @@ bool aio_wait(AioContext *ctx) } } - return true; + return progress; } @@ -144,5 +144,5 @@ AioContext *aio_context_new(void) void aio_flush(AioContext *ctx) { - while (aio_wait(ctx)); + while (aio_poll(ctx, true)); } diff --git a/main-loop.c b/main-loop.c index 8f0117e7aa..1fdc3bdf2e 100644 --- a/main-loop.c +++ b/main-loop.c @@ -534,7 +534,7 @@ void qemu_aio_flush(void) bool qemu_aio_wait(void) { - return aio_wait(qemu_aio_context); + return aio_poll(qemu_aio_context, true); } void qemu_aio_set_fd_handler(int fd, diff --git a/qemu-aio.h b/qemu-aio.h index f8a93d8fb9..f19201e7ca 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -133,13 +133,22 @@ void qemu_bh_delete(QEMUBH *bh); * outstanding AIO operations have been completed or cancelled. */ void aio_flush(AioContext *ctx); -/* Wait for a single AIO completion to occur. This function will wait - * until a single AIO event has completed and it will ensure something - * has moved before returning. This can issue new pending aio as - * result of executing I/O completion or bh callbacks. +/* Progress in completing AIO work to occur. This can issue new pending + * aio as a result of executing I/O completion or bh callbacks. * - * Return whether there is still any pending AIO operation. */ -bool aio_wait(AioContext *ctx); + * If there is no pending AIO operation or completion (bottom half), + * return false. If there are pending bottom halves, return true. + * + * If there are no pending bottom halves, but there are pending AIO + * operations, it may not be possible to make any progress without + * blocking. If @blocking is true, this function will wait until one + * or more AIO events have completed, to ensure something has moved + * before returning. + * + * If @blocking is false, this function will also return false if the + * function cannot make any progress without blocking. + */ +bool aio_poll(AioContext *ctx, bool blocking); #ifdef CONFIG_POSIX /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ |