diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2016-12-12 17:07:52 +0300 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2017-01-31 23:31:20 +0400 |
commit | a6da7ffa38f7715f863b4e926dd2cce6b5ce4acd (patch) | |
tree | 1cefbf49dcae0cd9359287042f329701285531e0 /chardev/char.c | |
parent | 09fbe4e3e1e8a0742d46327440835e1c1b57d030 (diff) | |
download | qemu-a6da7ffa38f7715f863b4e926dd2cce6b5ce4acd.zip qemu-a6da7ffa38f7715f863b4e926dd2cce6b5ce4acd.tar.gz qemu-a6da7ffa38f7715f863b4e926dd2cce6b5ce4acd.tar.bz2 |
char: move QIOChannel-related stuff to char-io.h
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'chardev/char.c')
-rw-r--r-- | chardev/char.c | 174 |
1 files changed, 1 insertions, 173 deletions
diff --git a/chardev/char.c b/chardev/char.c index 722c98d..3cbe42a 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -86,6 +86,7 @@ #include "ui/qemu-spice.h" #include "char-mux.h" +#include "char-io.h" #define TCP_MAX_FDS 16 @@ -479,8 +480,6 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) va_end(ap); } -static void remove_fd_in_watch(Chardev *chr); - static void qemu_char_open(Chardev *chr, ChardevBackend *backend, bool *be_opened, Error **errp) { @@ -716,178 +715,7 @@ void qemu_chr_fe_take_focus(CharBackend *b) } } -typedef struct IOWatchPoll -{ - GSource parent; - - QIOChannel *ioc; - GSource *src; - - IOCanReadHandler *fd_can_read; - GSourceFunc fd_read; - void *opaque; - GMainContext *context; -} IOWatchPoll; - -static IOWatchPoll *io_watch_poll_from_source(GSource *source) -{ - return container_of(source, IOWatchPoll, parent); -} - -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; - bool was_active = iwp->src != NULL; - if (was_active == now_active) { - return FALSE; - } - - if (now_active) { - iwp->src = qio_channel_create_watch( - iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL); - g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL); - g_source_attach(iwp->src, iwp->context); - } else { - g_source_destroy(iwp->src); - g_source_unref(iwp->src); - iwp->src = NULL; - } - return FALSE; -} - -static gboolean io_watch_poll_check(GSource *source) -{ - return FALSE; -} - -static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback, - gpointer user_data) -{ - abort(); -} - -static void io_watch_poll_finalize(GSource *source) -{ - /* Due to a glib bug, removing the last reference to a source - * inside a finalize callback causes recursive locking (and a - * deadlock). This is not a problem inside other callbacks, - * including dispatch callbacks, so we call io_remove_watch_poll - * to remove this source. At this point, iwp->src must - * be NULL, or we would leak it. - * - * This would be solved much more elegantly by child sources, - * but we support older glib versions that do not have them. - */ - IOWatchPoll *iwp = io_watch_poll_from_source(source); - assert(iwp->src == NULL); -} - -static GSourceFuncs io_watch_poll_funcs = { - .prepare = io_watch_poll_prepare, - .check = io_watch_poll_check, - .dispatch = io_watch_poll_dispatch, - .finalize = io_watch_poll_finalize, -}; - -/* Can only be used for read */ -static guint io_add_watch_poll(Chardev *chr, - QIOChannel *ioc, - IOCanReadHandler *fd_can_read, - QIOChannelFunc fd_read, - gpointer user_data, - GMainContext *context) -{ - IOWatchPoll *iwp; - int tag; - char *name; - - iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs, - sizeof(IOWatchPoll)); - iwp->fd_can_read = fd_can_read; - iwp->opaque = user_data; - iwp->ioc = ioc; - iwp->fd_read = (GSourceFunc) fd_read; - iwp->src = NULL; - iwp->context = context; - - name = g_strdup_printf("chardev-iowatch-%s", chr->label); - g_source_set_name((GSource *)iwp, name); - g_free(name); - - tag = g_source_attach(&iwp->parent, context); - g_source_unref(&iwp->parent); - return tag; -} - -static void io_remove_watch_poll(guint tag) -{ - GSource *source; - IOWatchPoll *iwp; - - g_return_if_fail (tag > 0); - - source = g_main_context_find_source_by_id(NULL, tag); - g_return_if_fail (source != NULL); - - iwp = io_watch_poll_from_source(source); - if (iwp->src) { - g_source_destroy(iwp->src); - g_source_unref(iwp->src); - iwp->src = NULL; - } - g_source_destroy(&iwp->parent); -} - -static void remove_fd_in_watch(Chardev *chr) -{ - if (chr->fd_in_tag) { - io_remove_watch_poll(chr->fd_in_tag); - chr->fd_in_tag = 0; - } -} - - -static int io_channel_send_full(QIOChannel *ioc, - const void *buf, size_t len, - int *fds, size_t nfds) -{ - size_t offset = 0; - - while (offset < len) { - ssize_t ret = 0; - struct iovec iov = { .iov_base = (char *)buf + offset, - .iov_len = len - offset }; - - ret = qio_channel_writev_full( - ioc, &iov, 1, - fds, nfds, NULL); - if (ret == QIO_CHANNEL_ERR_BLOCK) { - if (offset) { - return offset; - } - - errno = EAGAIN; - return -1; - } else if (ret < 0) { - errno = EINVAL; - return -1; - } - - offset += ret; - } - - return offset; -} - - #ifndef _WIN32 -static int io_channel_send(QIOChannel *ioc, const void *buf, size_t len) -{ - return io_channel_send_full(ioc, buf, len, NULL, 0); -} - typedef struct FDChardev { Chardev parent; Chardev *chr; |