summaryrefslogtreecommitdiff
path: root/async.c
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-09-05 20:35:53 +0900
committerChanho Park <chanho61.park@samsung.com>2014-09-05 20:35:53 +0900
commit16b1353a36171ae06d63fd309f4772dbfb1da113 (patch)
treecf6c297ee81aba0d9b47f23d78a889667e7bce48 /async.c
parenta15119db2ff5c2fdfdeb913b297bf8aa3399132e (diff)
downloadqemu-16b1353a36171ae06d63fd309f4772dbfb1da113.tar.gz
qemu-16b1353a36171ae06d63fd309f4772dbfb1da113.tar.bz2
qemu-16b1353a36171ae06d63fd309f4772dbfb1da113.zip
Imported Upstream version 2.1.0upstream/2.1.0
Diffstat (limited to 'async.c')
-rw-r--r--async.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/async.c b/async.c
index 6930185e6..34af0b25c 100644
--- a/async.c
+++ b/async.c
@@ -26,6 +26,7 @@
#include "block/aio.h"
#include "block/thread-pool.h"
#include "qemu/main-loop.h"
+#include "qemu/atomic.h"
/***********************************************************/
/* bottom halves (can be seen as timers which expire ASAP) */
@@ -117,15 +118,21 @@ void qemu_bh_schedule_idle(QEMUBH *bh)
void qemu_bh_schedule(QEMUBH *bh)
{
+ AioContext *ctx;
+
if (bh->scheduled)
return;
+ ctx = bh->ctx;
bh->idle = 0;
- /* Make sure that idle & any writes needed by the callback are done
- * before the locations are read in the aio_bh_poll.
+ /* Make sure that:
+ * 1. idle & any writes needed by the callback are done before the
+ * locations are read in the aio_bh_poll.
+ * 2. ctx is loaded before scheduled is set and the callback has a chance
+ * to execute.
*/
- smp_wmb();
+ smp_mb();
bh->scheduled = 1;
- aio_notify(bh->ctx);
+ aio_notify(ctx);
}
@@ -241,9 +248,25 @@ ThreadPool *aio_get_thread_pool(AioContext *ctx)
return ctx->thread_pool;
}
+void aio_set_dispatching(AioContext *ctx, bool dispatching)
+{
+ ctx->dispatching = dispatching;
+ if (!dispatching) {
+ /* Write ctx->dispatching before reading e.g. bh->scheduled.
+ * Optimization: this is only needed when we're entering the "unsafe"
+ * phase where other threads must call event_notifier_set.
+ */
+ smp_mb();
+ }
+}
+
void aio_notify(AioContext *ctx)
{
- event_notifier_set(&ctx->notifier);
+ /* Write e.g. bh->scheduled before reading ctx->dispatching. */
+ smp_mb();
+ if (!ctx->dispatching) {
+ event_notifier_set(&ctx->notifier);
+ }
}
static void aio_timerlist_notify(void *opaque)