diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-07-22 12:52:34 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-07-22 12:52:34 +0100 |
commit | dc94bd9166af5236a56bd5bb06845911915a925c (patch) | |
tree | da7f57b66fdc24f5904dc64e2def74de296a9987 /include | |
parent | b9c46307996856d03ddc1527468ff5401ac03a79 (diff) | |
parent | 05e514b1d4d5bd4209e2c8bbc76ff05c85a235f3 (diff) | |
download | qemu-dc94bd9166af5236a56bd5bb06845911915a925c.zip qemu-dc94bd9166af5236a56bd5bb06845911915a925c.tar.gz qemu-dc94bd9166af5236a56bd5bb06845911915a925c.tar.bz2 |
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
# gpg: Signature made Wed Jul 22 12:43:35 2015 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>"
* remotes/stefanha/tags/block-pull-request:
AioContext: optimize clearing the EventNotifier
AioContext: fix broken placement of event_notifier_test_and_clear
AioContext: fix broken ctx->dispatching optimization
aio-win32: reorganize polling loop
tests: remove irrelevant assertions from test-aio
qemu-timer: initialize "timers_done_ev" to set
mirror: Speed up bitmap initial scanning
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/block/aio.h | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/include/block/aio.h b/include/block/aio.h index b46103e..9dd32e0 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -63,10 +63,30 @@ struct AioContext { */ int walking_handlers; - /* Used to avoid unnecessary event_notifier_set calls in aio_notify. - * Writes protected by lock or BQL, reads are lockless. + /* Used to avoid unnecessary event_notifier_set calls in aio_notify; + * accessed with atomic primitives. If this field is 0, everything + * (file descriptors, bottom halves, timers) will be re-evaluated + * before the next blocking poll(), thus the event_notifier_set call + * can be skipped. If it is non-zero, you may need to wake up a + * concurrent aio_poll or the glib main event loop, making + * event_notifier_set necessary. + * + * Bit 0 is reserved for GSource usage of the AioContext, and is 1 + * between a call to aio_ctx_check and the next call to aio_ctx_dispatch. + * Bits 1-31 simply count the number of active calls to aio_poll + * that are in the prepare or poll phase. + * + * The GSource and aio_poll must use a different mechanism because + * there is no certainty that a call to GSource's prepare callback + * (via g_main_context_prepare) is indeed followed by check and + * dispatch. It's not clear whether this would be a bug, but let's + * play safe and allow it---it will just cause extra calls to + * event_notifier_set until the next call to dispatch. + * + * Instead, the aio_poll calls include both the prepare and the + * dispatch phase, hence a simple counter is enough for them. */ - bool dispatching; + uint32_t notify_me; /* lock to protect between bh's adders and deleter */ QemuMutex bh_lock; @@ -79,7 +99,19 @@ struct AioContext { */ int walking_bh; - /* Used for aio_notify. */ + /* Used by aio_notify. + * + * "notified" is used to avoid expensive event_notifier_test_and_clear + * calls. When it is clear, the EventNotifier is clear, or one thread + * is going to clear "notified" before processing more events. False + * positives are possible, i.e. "notified" could be set even though the + * EventNotifier is clear. + * + * Note that event_notifier_set *cannot* be optimized the same way. For + * more information on the problem that would result, see "#ifdef BUG2" + * in the docs/aio_notify_accept.promela formal model. + */ + bool notified; EventNotifier notifier; /* Thread pool for performing work and receiving completion callbacks */ @@ -89,9 +121,6 @@ struct AioContext { QEMUTimerListGroup tlg; }; -/* Used internally to synchronize aio_poll against qemu_bh_schedule. */ -void aio_set_dispatching(AioContext *ctx, bool dispatching); - /** * aio_context_new: Allocate a new AioContext. * @@ -157,6 +186,24 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque); void aio_notify(AioContext *ctx); /** + * aio_notify_accept: Acknowledge receiving an aio_notify. + * + * aio_notify() uses an EventNotifier in order to wake up a sleeping + * aio_poll() or g_main_context_iteration(). Calls to aio_notify() are + * usually rare, but the AioContext has to clear the EventNotifier on + * every aio_poll() or g_main_context_iteration() in order to avoid + * busy waiting. This event_notifier_test_and_clear() cannot be done + * using the usual aio_context_set_event_notifier(), because it must + * be done before processing all events (file descriptors, bottom halves, + * timers). + * + * aio_notify_accept() is an optimized event_notifier_test_and_clear() + * that is specific to an AioContext's notifier; it is used internally + * to clear the EventNotifier only if aio_notify() had been called. + */ +void aio_notify_accept(AioContext *ctx); + +/** * aio_bh_poll: Poll bottom halves for an AioContext. * * These are internal functions used by the QEMU main loop. |