From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36619) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bsVQk-0007Xx-MI for qemu-devel@nongnu.org; Fri, 07 Oct 2016 09:43:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bsVQe-0004Jd-BQ for qemu-devel@nongnu.org; Fri, 07 Oct 2016 09:43:17 -0400 From: Kevin Wolf Date: Fri, 7 Oct 2016 15:42:51 +0200 Message-Id: <1475847779-7336-3-git-send-email-kwolf@redhat.com> In-Reply-To: <1475847779-7336-1-git-send-email-kwolf@redhat.com> References: <1475847779-7336-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PULL 02/10] async: add aio_bh_schedule_oneshot List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-block@nongnu.org Cc: kwolf@redhat.com, qemu-devel@nongnu.org From: Paolo Bonzini qemu_bh_delete is already clearing bh->scheduled at the same time as it's setting bh->deleted. Since it's not using any memory barriers, there is no synchronization going on for bh->deleted, and this makes the bh->deleted checks superfluous in aio_compute_timeout, aio_bh_poll and aio_ctx_check. Just remove them, and put the (bh->scheduled && bh->deleted) combo to work in a new function aio_bh_schedule_oneshot. The new function removes the need to save the QEMUBH pointer between the creation and the execution of the bottom half. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- async.c | 27 +++++++++++++++++++++++---- include/block/aio.h | 6 ++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/async.c b/async.c index 3bca9b0..f30d011 100644 --- a/async.c +++ b/async.c @@ -44,6 +44,25 @@ struct QEMUBH { bool deleted; }; +void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque) +{ + QEMUBH *bh; + bh = g_new(QEMUBH, 1); + *bh = (QEMUBH){ + .ctx = ctx, + .cb = cb, + .opaque = opaque, + }; + qemu_mutex_lock(&ctx->bh_lock); + bh->next = ctx->first_bh; + bh->scheduled = 1; + bh->deleted = 1; + /* Make sure that the members are ready before putting bh into list */ + smp_wmb(); + ctx->first_bh = bh; + qemu_mutex_unlock(&ctx->bh_lock); +} + QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) { QEMUBH *bh; @@ -86,7 +105,7 @@ int aio_bh_poll(AioContext *ctx) * thread sees the zero before bh->cb has run, and thus will call * aio_notify again if necessary. */ - if (!bh->deleted && atomic_xchg(&bh->scheduled, 0)) { + if (atomic_xchg(&bh->scheduled, 0)) { /* Idle BHs and the notify BH don't count as progress */ if (!bh->idle && bh != ctx->notify_dummy_bh) { ret = 1; @@ -104,7 +123,7 @@ int aio_bh_poll(AioContext *ctx) bhp = &ctx->first_bh; while (*bhp) { bh = *bhp; - if (bh->deleted) { + if (bh->deleted && !bh->scheduled) { *bhp = bh->next; g_free(bh); } else { @@ -168,7 +187,7 @@ aio_compute_timeout(AioContext *ctx) QEMUBH *bh; for (bh = ctx->first_bh; bh; bh = bh->next) { - if (!bh->deleted && bh->scheduled) { + if (bh->scheduled) { if (bh->idle) { /* idle bottom halves will be polled at least * every 10ms */ @@ -216,7 +235,7 @@ aio_ctx_check(GSource *source) aio_notify_accept(ctx); for (bh = ctx->first_bh; bh; bh = bh->next) { - if (!bh->deleted && bh->scheduled) { + if (bh->scheduled) { return true; } } diff --git a/include/block/aio.h b/include/block/aio.h index 173c1ed..b9fe2cb 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -181,6 +181,12 @@ void aio_context_acquire(AioContext *ctx); void aio_context_release(AioContext *ctx); /** + * aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run + * only once and as soon as possible. + */ +void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque); + +/** * aio_bh_new: Allocate a new bottom half structure. * * Bottom halves are lightweight callbacks whose invocation is guaranteed -- 1.8.3.1