From patchwork Thu Jul 21 08:26:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhang Chen X-Patchwork-Id: 9241131 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AD520602F0 for ; Thu, 21 Jul 2016 08:31:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9B93D26253 for ; Thu, 21 Jul 2016 08:31:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9051927D64; Thu, 21 Jul 2016 08:31:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D80ED27C0B for ; Thu, 21 Jul 2016 08:31:55 +0000 (UTC) Received: from localhost ([::1]:38976 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bQ9Oc-0004Mu-W9 for patchwork-qemu-devel@patchwork.kernel.org; Thu, 21 Jul 2016 04:31:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37477) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bQ9Jh-0000Xx-Tx for qemu-devel@nongnu.org; Thu, 21 Jul 2016 04:26:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bQ9Jf-0000h2-8g for qemu-devel@nongnu.org; Thu, 21 Jul 2016 04:26:48 -0400 Received: from [59.151.112.132] (port=12521 helo=heian.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bQ9Jd-0000fm-R4 for qemu-devel@nongnu.org; Thu, 21 Jul 2016 04:26:47 -0400 X-IronPort-AV: E=Sophos;i="5.22,518,1449504000"; d="scan'208";a="8937349" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 21 Jul 2016 16:26:29 +0800 Received: from G08CNEXCHPEKD02.g08.fujitsu.local (unknown [10.167.33.83]) by cn.fujitsu.com (Postfix) with ESMTP id 531144295F84; Thu, 21 Jul 2016 16:26:30 +0800 (CST) Received: from G08FNSTD140215.g08.fujitsu.local (10.167.226.56) by G08CNEXCHPEKD02.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.279.2; Thu, 21 Jul 2016 16:26:29 +0800 From: Zhang Chen To: qemu devel , Jason Wang Date: Thu, 21 Jul 2016 16:26:11 +0800 Message-ID: <1469089573-20923-6-git-send-email-zhangchen.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1469089573-20923-1-git-send-email-zhangchen.fnst@cn.fujitsu.com> References: <1469089573-20923-1-git-send-email-zhangchen.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.226.56] X-yoursite-MailScanner-ID: 531144295F84.ADA75 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: zhangchen.fnst@cn.fujitsu.com X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 59.151.112.132 Subject: [Qemu-devel] [RFC PATCH V8 5/7] qemu-char: Add qemu_chr_add_handlers_full() for GMaincontext X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Li Zhijian , "eddie . dong" , "Dr . David Alan Gilbert" , Paolo Bonzini , Zhang Chen , zhanghailiang Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Add qemu_chr_add_handlers_full() API, we can use this API pass in a GMainContext,make handler run in the context rather than main_loop. This comments from Daniel P . Berrange. Cc: Daniel P . Berrange Cc: Paolo Bonzini Signed-off-by: Zhang Chen Signed-off-by: Li Zhijian Signed-off-by: Wen Congyang --- include/sysemu/char.h | 10 ++++ qemu-char.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) diff --git a/include/sysemu/char.h b/include/sysemu/char.h index 307fd8f..3ab897e 100644 --- a/include/sysemu/char.h +++ b/include/sysemu/char.h @@ -66,6 +66,8 @@ struct CharDriverState { const uint8_t *buf, int len); GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond); void (*chr_update_read_handler)(struct CharDriverState *s); + void (*chr_update_read_handler_full)(struct CharDriverState *s, + GMainContext *context); int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); int (*get_msgfds)(struct CharDriverState *s, int* fds, int num); int (*set_msgfds)(struct CharDriverState *s, int *fds, int num); @@ -388,6 +390,14 @@ void qemu_chr_add_handlers(CharDriverState *s, IOEventHandler *fd_event, void *opaque); +/* This API can make handler run in the context what you pass to. */ +void qemu_chr_add_handlers_full(CharDriverState *s, + IOCanReadHandler *fd_can_read, + IOReadHandler *fd_read, + IOEventHandler *fd_event, + void *opaque, + GMainContext *context); + void qemu_chr_be_generic_open(CharDriverState *s); void qemu_chr_accept_input(CharDriverState *s); int qemu_chr_add_client(CharDriverState *s, int fd); diff --git a/qemu-char.c b/qemu-char.c index b597ee1..607b3b8 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -480,6 +480,40 @@ void qemu_chr_add_handlers(CharDriverState *s, } } +void qemu_chr_add_handlers_full(CharDriverState *s, + IOCanReadHandler *fd_can_read, + IOReadHandler *fd_read, + IOEventHandler *fd_event, + void *opaque, + GMainContext *context) +{ + int fe_open; + + if (!opaque && !fd_can_read && !fd_read && !fd_event) { + fe_open = 0; + remove_fd_in_watch(s); + } else { + fe_open = 1; + } + s->chr_can_read = fd_can_read; + s->chr_read = fd_read; + s->chr_event = fd_event; + s->handler_opaque = opaque; + if (fe_open && s->chr_update_read_handler) { + s->chr_update_read_handler_full(s, context); + } + + if (!s->explicit_fe_open) { + qemu_chr_fe_set_open(s, fe_open); + } + + /* We're connecting to an already opened device, so let's make sure we + also get the open event */ + if (fe_open && s->be_open) { + qemu_chr_be_generic_open(s); + } +} + static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { return len; @@ -840,6 +874,7 @@ typedef struct IOWatchPoll IOCanReadHandler *fd_can_read; GSourceFunc fd_read; void *opaque; + GMainContext *context; } IOWatchPoll; static IOWatchPoll *io_watch_poll_from_source(GSource *source) @@ -869,6 +904,29 @@ static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_) return FALSE; } +static gboolean io_watch_poll_prepare_full(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; @@ -903,6 +961,13 @@ static GSourceFuncs io_watch_poll_funcs = { .finalize = io_watch_poll_finalize, }; +static GSourceFuncs io_watch_poll_funcs_full = { + .prepare = io_watch_poll_prepare_full, + .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(QIOChannel *ioc, IOCanReadHandler *fd_can_read, @@ -924,6 +989,30 @@ static guint io_add_watch_poll(QIOChannel *ioc, return tag; } +/* Can only be used for read */ +static guint io_add_watch_poll_full(QIOChannel *ioc, + IOCanReadHandler *fd_can_read, + QIOChannelFunc fd_read, + gpointer user_data, + GMainContext *context) +{ + IOWatchPoll *iwp; + int tag; + + iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs_full, + 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; + + tag = g_source_attach(&iwp->parent, context); + g_source_unref(&iwp->parent); + return tag; + } + static void io_remove_watch_poll(guint tag) { GSource *source; @@ -1063,6 +1152,20 @@ static void fd_chr_update_read_handler(CharDriverState *chr) } } +static void fd_chr_update_read_handler_full(CharDriverState *chr, + GMainContext *context) +{ + FDCharDriver *s = chr->opaque; + + remove_fd_in_watch(chr); + if (s->ioc_in) { + chr->fd_in_tag = io_add_watch_poll_full(s->ioc_in, + fd_chr_read_poll, + fd_chr_read, chr, + context); + } +} + static void fd_chr_close(struct CharDriverState *chr) { FDCharDriver *s = chr->opaque; @@ -1099,6 +1202,7 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out, 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_update_read_handler_full = fd_chr_update_read_handler_full; chr->chr_close = fd_chr_close; return chr; @@ -1310,6 +1414,12 @@ static void pty_chr_update_read_handler(CharDriverState *chr) qemu_mutex_unlock(&chr->chr_write_lock); } +static void pty_chr_update_read_handler_full(CharDriverState *chr, + GMainContext *context) +{ + pty_chr_update_read_handler(chr); +} + /* Called with chr_write_lock held. */ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { @@ -1465,6 +1575,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id, chr->opaque = s; chr->chr_write = pty_chr_write; chr->chr_update_read_handler = pty_chr_update_read_handler; + chr->chr_update_read_handler_full = pty_chr_update_read_handler_full; chr->chr_close = pty_chr_close; chr->chr_add_watch = pty_chr_add_watch; chr->explicit_be_open = true; @@ -2558,6 +2669,20 @@ static void udp_chr_update_read_handler(CharDriverState *chr) } } +static void udp_chr_update_read_handler_full(CharDriverState *chr, + GMainContext *context) +{ + NetCharDriver *s = chr->opaque; + + remove_fd_in_watch(chr); + if (s->ioc) { + chr->fd_in_tag = io_add_watch_poll_full(s->ioc, + udp_chr_read_poll, + udp_chr_read, chr, + context); + } +} + static void udp_chr_close(CharDriverState *chr) { NetCharDriver *s = chr->opaque; @@ -2589,6 +2714,7 @@ static CharDriverState *qemu_chr_open_udp(QIOChannelSocket *sioc, chr->opaque = s; chr->chr_write = udp_chr_write; chr->chr_update_read_handler = udp_chr_update_read_handler; + chr->chr_update_read_handler_full = udp_chr_update_read_handler_full; chr->chr_close = udp_chr_close; /* be isn't opened until we get a connection */ chr->explicit_be_open = true; @@ -2952,6 +3078,24 @@ static void tcp_chr_update_read_handler(CharDriverState *chr) } } +static void tcp_chr_update_read_handler_full(CharDriverState *chr, + GMainContext *context) +{ + TCPCharDriver *s = chr->opaque; + + if (!s->connected) { + return; + } + + remove_fd_in_watch(chr); + if (s->ioc) { + chr->fd_in_tag = io_add_watch_poll_full(s->ioc, + tcp_chr_read_poll, + tcp_chr_read, chr, + context); + } +} + typedef struct { CharDriverState *chr; char buf[12]; @@ -4410,6 +4554,7 @@ static CharDriverState *qmp_chardev_open_socket(const char *id, chr->chr_add_client = tcp_chr_add_client; chr->chr_add_watch = tcp_chr_add_watch; chr->chr_update_read_handler = tcp_chr_update_read_handler; + chr->chr_update_read_handler_full = tcp_chr_update_read_handler_full; /* be isn't opened until we get a connection */ chr->explicit_be_open = true;