qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC 1/3] char: Trigger timeouts on poll() when frontend is


From: Heinz Graalfs
Subject: [Qemu-devel] [RFC 1/3] char: Trigger timeouts on poll() when frontend is unready
Date: Fri, 24 Oct 2014 10:13:45 +0200

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 <address@hidden>
---
 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);
 }
 
-- 
1.8.3.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]