From patchwork Tue Sep 25 12:55:55 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 186817 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0AB762C007A for ; Tue, 25 Sep 2012 23:44:05 +1000 (EST) Received: from localhost ([::1]:35719 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TGUhU-0004gx-SA for incoming@patchwork.ozlabs.org; Tue, 25 Sep 2012 08:57:20 -0400 Received: from eggs.gnu.org ([208.118.235.92]:48654) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TGUgu-0003ZM-J4 for qemu-devel@nongnu.org; Tue, 25 Sep 2012 08:56:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TGUgs-00016v-Md for qemu-devel@nongnu.org; Tue, 25 Sep 2012 08:56:44 -0400 Received: from mail-pb0-f45.google.com ([209.85.160.45]:65329) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TGUgs-0000zu-GH for qemu-devel@nongnu.org; Tue, 25 Sep 2012 08:56:42 -0400 Received: by mail-pb0-f45.google.com with SMTP id rp2so67620pbb.4 for ; Tue, 25 Sep 2012 05:56:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; bh=BpCiHjNxdXdDoRC3ffIxMmJkl13YslFef2PyYe4VDr4=; b=CQTZrW5rNC6UZT/2vm8+v8x2fufWARIfIBSF1KfX6UouHyxlZ/gAHUVKzY7ixT1Oav vVzVZq5tL8oYSyaK9iwIO8KejyHhjCN5Xx/vVEgKQIw4AzyRvZUWLI6GMreZRHdzkfuF zWETWNxYuPjoNMJEuzSEpgqDMZy7y1nf65RomnamGgNwoxsNvcqWkmgD4ZIOctXg5wtl rS79pxasG0ThNChClIFD/pqrxIAoQO7jNHi5g5vS45W2gXob/AHyMQ1pKLhpRwm+X06Q CmL1zZyU6FSGc4zeY5b0rKQotzUDVZv9/pZOMqF01Ai+hezmvHqwdx3EHZqrLBuaG2zY yRew== Received: by 10.68.240.7 with SMTP id vw7mr45496519pbc.152.1348577802059; Tue, 25 Sep 2012 05:56:42 -0700 (PDT) Received: from yakj.usersys.redhat.com (93-34-169-1.ip50.fastwebnet.it. [93.34.169.1]) by mx.google.com with ESMTPS id py9sm309335pbb.20.2012.09.25.05.56.39 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 25 Sep 2012 05:56:40 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 25 Sep 2012 14:55:55 +0200 Message-Id: <1348577763-12920-10-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.12 In-Reply-To: <1348577763-12920-1-git-send-email-pbonzini@redhat.com> References: <1348577763-12920-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.160.45 Subject: [Qemu-devel] [PATCH 09/17] aio: prepare for introducing GSource-based dispatch X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This adds a GPollFD to each AioHandler. It will then be possible to attach these GPollFDs to a GSource, and from there to the main loop. aio_wait examines the GPollFDs and avoids calling select() if any is set (similar to what it does if bottom halves are available). Signed-off-by: Paolo Bonzini --- aio.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------- qemu-aio.h | 7 ++++++ 2 file modificati, 78 inserzioni(+), 11 rimozioni(-) diff --git a/aio.c b/aio.c index 95ad467..c848a9f 100644 --- a/aio.c +++ b/aio.c @@ -20,7 +20,7 @@ struct AioHandler { - int fd; + GPollFD pfd; IOHandler *io_read; IOHandler *io_write; AioFlushHandler *io_flush; @@ -34,7 +34,7 @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd) AioHandler *node; QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (node->fd == fd) + if (node->pfd.fd == fd) if (!node->deleted) return node; } @@ -57,9 +57,10 @@ void aio_set_fd_handler(AioContext *ctx, if (!io_read && !io_write) { if (node) { /* If the lock is held, just mark the node as deleted */ - if (ctx->walking_handlers) + if (ctx->walking_handlers) { node->deleted = 1; - else { + node->pfd.revents = 0; + } else { /* Otherwise, delete it for real. We can't just mark it as * deleted because deleted nodes are only cleaned up after * releasing the walking_handlers lock. @@ -72,7 +73,7 @@ void aio_set_fd_handler(AioContext *ctx, if (node == NULL) { /* Alloc and insert if it's not already there */ node = g_malloc0(sizeof(AioHandler)); - node->fd = fd; + node->pfd.fd = fd; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); } /* Update handler with latest information */ @@ -80,6 +81,10 @@ void aio_set_fd_handler(AioContext *ctx, node->io_write = io_write; node->io_flush = io_flush; node->opaque = opaque; + + node->pfd.events = G_IO_ERR; + node->pfd.events |= (io_read ? G_IO_IN | G_IO_HUP : 0); + node->pfd.events |= (io_write ? G_IO_OUT : 0); } } @@ -93,6 +98,25 @@ void aio_set_event_notifier(AioContext *ctx, (AioFlushHandler *)io_flush, notifier); } +bool aio_pending(AioContext *ctx) +{ + AioHandler *node; + + QLIST_FOREACH(node, &ctx->aio_handlers, node) { + int revents; + + revents = node->pfd.revents & node->pfd.events; + if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) { + return true; + } + if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) { + return true; + } + } + + return false; +} + bool aio_poll(AioContext *ctx, bool blocking) { static struct timeval tv0; @@ -114,6 +138,42 @@ bool aio_poll(AioContext *ctx, bool blocking) progress = true; } + /* + * Then dispatch any pending callbacks from the GSource. + * + * We have to walk very carefully in case qemu_aio_set_fd_handler is + * called while we're walking. + */ + node = QLIST_FIRST(&ctx->aio_handlers); + while (node) { + AioHandler *tmp; + int revents; + + ctx->walking_handlers++; + + revents = node->pfd.revents & node->pfd.events; + node->pfd.revents &= ~revents; + + if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) { + node->io_read(node->opaque); + progress = true; + } + if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) { + node->io_write(node->opaque); + progress = true; + } + + tmp = node; + node = QLIST_NEXT(node, node); + + ctx->walking_handlers--; + + if (!ctx->walking_handlers && tmp->deleted) { + QLIST_REMOVE(tmp, node); + g_free(tmp); + } + } + if (progress && !blocking) { return true; } @@ -137,12 +197,12 @@ bool aio_poll(AioContext *ctx, bool blocking) busy = true; } if (!node->deleted && node->io_read) { - FD_SET(node->fd, &rdfds); - max_fd = MAX(max_fd, node->fd + 1); + FD_SET(node->pfd.fd, &rdfds); + max_fd = MAX(max_fd, node->pfd.fd + 1); } if (!node->deleted && node->io_write) { - FD_SET(node->fd, &wrfds); - max_fd = MAX(max_fd, node->fd + 1); + FD_SET(node->pfd.fd, &wrfds); + max_fd = MAX(max_fd, node->pfd.fd + 1); } } @@ -167,12 +227,12 @@ bool aio_poll(AioContext *ctx, bool blocking) ctx->walking_handlers++; if (!node->deleted && - FD_ISSET(node->fd, &rdfds) && + FD_ISSET(node->pfd.fd, &rdfds) && node->io_read) { node->io_read(node->opaque); } if (!node->deleted && - FD_ISSET(node->fd, &wrfds) && + FD_ISSET(node->pfd.fd, &wrfds) && node->io_write) { node->io_write(node->opaque); } diff --git a/qemu-aio.h b/qemu-aio.h index f19201e..ac24896 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -133,6 +133,13 @@ void qemu_bh_delete(QEMUBH *bh); * outstanding AIO operations have been completed or cancelled. */ void aio_flush(AioContext *ctx); +/* Return whether there are any pending callbacks from the GSource + * attached to the AioContext. + * + * This is used internally in the implementation of the GSource. + */ +bool aio_pending(AioContext *ctx); + /* Progress in completing AIO work to occur. This can issue new pending * aio as a result of executing I/O completion or bh callbacks. *