From patchwork Fri Oct 24 08:13:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heinz Graalfs X-Patchwork-Id: 402774 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A567514007D for ; Fri, 24 Oct 2014 19:16:59 +1100 (AEDT) Received: from localhost ([::1]:45922 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xha3N-0006Mf-P3 for incoming@patchwork.ozlabs.org; Fri, 24 Oct 2014 04:16:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39422) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xha1H-0002le-22 for qemu-devel@nongnu.org; Fri, 24 Oct 2014 04:14:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Xha16-0004yi-GJ for qemu-devel@nongnu.org; Fri, 24 Oct 2014 04:14:47 -0400 Received: from e06smtp17.uk.ibm.com ([195.75.94.113]:46791) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xha16-0004ya-8o for qemu-devel@nongnu.org; Fri, 24 Oct 2014 04:14:36 -0400 Received: from /spool/local by e06smtp17.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 24 Oct 2014 09:14:35 +0100 Received: from d06dlp03.portsmouth.uk.ibm.com (9.149.20.15) by e06smtp17.uk.ibm.com (192.168.101.147) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 24 Oct 2014 09:14:33 +0100 Received: from b06cxnps3075.portsmouth.uk.ibm.com (d06relay10.portsmouth.uk.ibm.com [9.149.109.195]) by d06dlp03.portsmouth.uk.ibm.com (Postfix) with ESMTP id 8508E1B08023 for ; Fri, 24 Oct 2014 09:14:34 +0100 (BST) Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id s9O8EXJR16908674 for ; Fri, 24 Oct 2014 08:14:33 GMT Received: from d06av02.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s9O8EVSX028928 for ; Fri, 24 Oct 2014 02:14:32 -0600 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id s9O8ELcv028408; Fri, 24 Oct 2014 02:14:30 -0600 From: Heinz Graalfs To: qemu-devel@nongnu.org Date: Fri, 24 Oct 2014 10:13:45 +0200 Message-Id: <1414138427-60643-2-git-send-email-graalfs@linux.vnet.ibm.com> X-Mailer: git-send-email 1.8.5.5 In-Reply-To: <1414138427-60643-1-git-send-email-graalfs@linux.vnet.ibm.com> References: <1414138427-60643-1-git-send-email-graalfs@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 14102408-0029-0000-0000-0000015625CC X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.75.94.113 Cc: cornelia.huck@de.ibm.com, pbonzini@redhat.com, Heinz Graalfs , borntraeger@de.ibm.com Subject: [Qemu-devel] [RFC 1/3] char: Trigger timeouts on poll() when frontend is unready 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 When a character frontend returns zero on 'can_read' poll() goes on without the backend's descriptor. The remaining active descriptors may not be a part of the main thread's poll; for example, if dataplane is active, activity may only be ongoing on the dataplane thread. This patch changes the character backend's io_watch_poll() loop logic. If a frontend returns -EAGAIN on 'can_read' a poll() timeout is triggered, thus the backend's descriptor has a chance to reappear within the poll desriptor array. The timeout callback reinvokes 'can_read' to ask the frontend if it is ready. Scheduling a timeout callback on poll() ends when the frontend returns a non negative value on 'can_read'. Frontends still returning zero on 'can_read' or without such callback are not affected. Signed-off-by: Heinz Graalfs --- qemu-char.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/qemu-char.c b/qemu-char.c index 8623c70..4adf7e4 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -697,6 +697,7 @@ typedef struct IOWatchPoll IOCanReadHandler *fd_can_read; GSourceFunc fd_read; void *opaque; + guint timer_tag; } IOWatchPoll; static IOWatchPoll *io_watch_poll_from_source(GSource *source) @@ -704,19 +705,38 @@ static IOWatchPoll *io_watch_poll_from_source(GSource *source) return container_of(source, IOWatchPoll, parent); } +static gboolean io_watch_timer(gpointer opaque) +{ + IOWatchPoll *iwp = io_watch_poll_from_source(opaque); + + if (iwp->fd_can_read(iwp->opaque) == -EAGAIN) { + return TRUE; + } + iwp->timer_tag = 0; + return FALSE; +} + static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_) { IOWatchPoll *iwp = io_watch_poll_from_source(source); - bool now_active = iwp->fd_can_read(iwp->opaque) > 0; + int avail = iwp->fd_can_read(iwp->opaque); + bool now_active = avail > 0; + bool use_timeout = avail == -EAGAIN; bool was_active = iwp->src != NULL; if (was_active == now_active) { return FALSE; } + if (iwp->timer_tag) { + g_source_remove(iwp->timer_tag); + iwp->timer_tag = 0; + } if (now_active) { iwp->src = g_io_create_watch(iwp->channel, G_IO_IN | G_IO_ERR | G_IO_HUP); g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL); g_source_attach(iwp->src, NULL); + } else if (use_timeout) { + iwp->timer_tag = g_timeout_add(100, io_watch_timer, source); } else { g_source_destroy(iwp->src); g_source_unref(iwp->src); @@ -774,6 +794,7 @@ static guint io_add_watch_poll(GIOChannel *channel, iwp->channel = channel; iwp->fd_read = (GSourceFunc) fd_read; iwp->src = NULL; + iwp->timer_tag = 0; tag = g_source_attach(&iwp->parent, NULL); g_source_unref(&iwp->parent); @@ -796,6 +817,10 @@ static void io_remove_watch_poll(guint tag) g_source_unref(iwp->src); iwp->src = NULL; } + if (iwp->timer_tag) { + g_source_remove(iwp->timer_tag); + iwp->timer_tag = 0; + } g_source_destroy(&iwp->parent); }