diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2013-03-05 23:21:23 +0530 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2013-03-08 13:57:15 -0600 |
commit | 23673ca740e0eda66901ca801a5a901df378b063 (patch) | |
tree | be62ffa43f5d182d2925bc6dfddc416670e53a1b | |
parent | 2ea5a7af7bfa576a5936400ccca4144caca9640b (diff) |
qemu-char: add watch support
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>
Message-id: 96f93c0f741064604bbb6389ce962191120af8b7.1362505276.git.amit.shah@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r-- | include/char/char.h | 4 | ||||
-rw-r--r-- | qemu-char.c | 32 |
2 files changed, 35 insertions, 1 deletions
diff --git a/include/char/char.h b/include/char/char.h index c91ce3c98a..09ac4014dd 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 5a5349111c..70917438d3 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); |