diff mbox

[08/20] qemu-char: add watch support

Message ID 96f93c0f741064604bbb6389ce962191120af8b7.1362505276.git.amit.shah@redhat.com
State New
Headers show

Commit Message

Amit Shah March 5, 2013, 5:51 p.m. UTC
From: Anthony Liguori <aliguori@us.ibm.com>

This allows a front-end to request for a callback when the backend
is writable again.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
---
 include/char/char.h |  4 ++++
 qemu-char.c         | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 35 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/include/char/char.h b/include/char/char.h
index c91ce3c..09ac401 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -56,6 +56,7 @@  typedef void IOEventHandler(void *opaque, int event);
 struct CharDriverState {
     void (*init)(struct CharDriverState *s);
     int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
+    GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond);
     void (*chr_update_read_handler)(struct CharDriverState *s);
     int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
     int (*get_msgfd)(struct CharDriverState *s);
@@ -152,6 +153,9 @@  void qemu_chr_fe_close(struct CharDriverState *chr);
 void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
 
+guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
+                            GIOFunc func, void *user_data);
+
 /**
  * @qemu_chr_fe_write:
  *
diff --git a/qemu-char.c b/qemu-char.c
index 5a53491..7091743 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -686,7 +686,11 @@  static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
         status = g_io_channel_write_chars(fd, (const gchar *)buf, len,
                                           &bytes_written, NULL);
         if (status != G_IO_STATUS_NORMAL) {
-            if (status != G_IO_STATUS_AGAIN) {
+            if (status == G_IO_STATUS_AGAIN) {
+                errno = EAGAIN;
+                return -1;
+            } else {
+                errno = EINVAL;
                 return -1;
             }
         } else if (status == G_IO_STATUS_EOF) {
@@ -753,6 +757,12 @@  static int fd_chr_read_poll(void *opaque)
     return s->max_size;
 }
 
+static GSource *fd_chr_add_watch(CharDriverState *chr, GIOCondition cond)
+{
+    FDCharDriver *s = chr->opaque;
+    return g_io_create_watch(s->fd_out, cond);
+}
+
 static void fd_chr_update_read_handler(CharDriverState *chr)
 {
     FDCharDriver *s = chr->opaque;
@@ -796,8 +806,10 @@  static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     s = g_malloc0(sizeof(FDCharDriver));
     s->fd_in = io_channel_from_fd(fd_in);
     s->fd_out = io_channel_from_fd(fd_out);
+    fcntl(fd_out, F_SETFL, O_NONBLOCK);
     s->chr = chr;
     chr->opaque = s;
+    chr->chr_add_watch = fd_chr_add_watch;
     chr->chr_write = fd_chr_write;
     chr->chr_update_read_handler = fd_chr_update_read_handler;
     chr->chr_close = fd_chr_close;
@@ -3279,6 +3291,24 @@  void qemu_chr_fe_close(struct CharDriverState *chr)
     }
 }
 
+guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
+                            GIOFunc func, void *user_data)
+{
+    GSource *src;
+    guint tag;
+
+    if (s->chr_add_watch == NULL) {
+        return -ENOSYS;
+    }
+
+    src = s->chr_add_watch(s, cond);
+    g_source_set_callback(src, (GSourceFunc)func, user_data, NULL);
+    tag = g_source_attach(src, NULL);
+    g_source_unref(src);
+
+    return tag;
+}
+
 void qemu_chr_delete(CharDriverState *chr)
 {
     QTAILQ_REMOVE(&chardevs, chr, next);