fc5c27b
>From 5fc1c0fc4c8153ea927aa8580c78c484f966be64 Mon Sep 17 00:00:00 2001
3f1f296
From: Amit Shah <amit.shah@redhat.com>
3f1f296
Date: Mon, 21 Mar 2011 22:02:47 +0100
fc5c27b
Subject: [PATCH 06/28] char: Equip the unix/tcp backend to handle nonblocking
3f1f296
 writes#
3f1f296
3f1f296
Now that the infrastructure is in place to return -EAGAIN to callers,
3f1f296
individual char drivers can set their update_fd_handlers() function to
3f1f296
set or remove an fd's write handler.  This handler checks if the driver
3f1f296
became writable.
3f1f296
3f1f296
A generic callback routine is used for unblocking writes and letting
3f1f296
users of chardevs know that a driver became writable again.
3f1f296
3f1f296
Signed-off-by: Amit Shah <amit.shah@redhat.com>
3f1f296
---
3f1f296
 qemu-char.c |   34 ++++++++++++++++++++++++++++++++++
3f1f296
 1 files changed, 34 insertions(+), 0 deletions(-)
3f1f296
3f1f296
diff --git a/qemu-char.c b/qemu-char.c
13f703f
index 5dbf063..f54ce04 100644
3f1f296
--- a/qemu-char.c
3f1f296
+++ b/qemu-char.c
3f1f296
@@ -106,6 +106,19 @@
3f1f296
 static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
3f1f296
     QTAILQ_HEAD_INITIALIZER(chardevs);
3f1f296
 
3f1f296
+/*
3f1f296
+ * Generic routine that gets called when chardev becomes writable.
3f1f296
+ * Lets chardev user know it's OK to send more data.
3f1f296
+ */
3f1f296
+static void char_write_unblocked(void *opaque)
3f1f296
+{
3f1f296
+    CharDriverState *chr = opaque;
3f1f296
+
3f1f296
+    chr->write_blocked = false;
3f1f296
+    chr->chr_disable_write_fd_handler(chr);
3f1f296
+    chr->chr_write_unblocked(chr->handler_opaque);
3f1f296
+}
3f1f296
+
3f1f296
 static void qemu_chr_event(CharDriverState *s, int event)
3f1f296
 {
3f1f296
     /* Keep track if the char device is open */
13f703f
@@ -2309,6 +2322,25 @@ static void tcp_chr_close(CharDriverState *chr)
3f1f296
     qemu_chr_event(chr, CHR_EVENT_CLOSED);
3f1f296
 }
3f1f296
 
3f1f296
+static void tcp_enable_write_fd_handler(CharDriverState *chr)
3f1f296
+{
3f1f296
+    TCPCharDriver *s = chr->opaque;
3f1f296
+
3f1f296
+    /*
3f1f296
+     * This function is called only after tcp_chr_connect() is called
3f1f296
+     * (either in 'server' mode or client mode.  So we're sure of
3f1f296
+     * s->fd being initialised.
3f1f296
+     */
3f1f296
+    enable_write_fd_handler(s->fd, char_write_unblocked);
3f1f296
+}
3f1f296
+
3f1f296
+static void tcp_disable_write_fd_handler(CharDriverState *chr)
3f1f296
+{
3f1f296
+    TCPCharDriver *s = chr->opaque;
3f1f296
+
3f1f296
+    disable_write_fd_handler(s->fd);
3f1f296
+}
3f1f296
+
5e10b14
 static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
3f1f296
 {
3f1f296
     CharDriverState *chr = NULL;
13f703f
@@ -2365,6 +2397,8 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
3f1f296
     chr->chr_close = tcp_chr_close;
3f1f296
     chr->get_msgfd = tcp_get_msgfd;
5e10b14
     chr->chr_add_client = tcp_chr_add_client;
3f1f296
+    chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
3f1f296
+    chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
3f1f296
 
3f1f296
     if (is_listen) {
3f1f296
         s->listen_fd = fd;
3f1f296
-- 
3f1f296
1.7.5.1
3f1f296