Blame SOURCES/0005-Recreate-watch-if-needed.patch

2580a2
From f5e24c5cf77b92ab2737eb230db7ae0b2fb102cc Mon Sep 17 00:00:00 2001
2580a2
From: Frediano Ziglio <freddy77@gmail.com>
2580a2
Date: Sat, 17 Sep 2022 09:28:08 +0100
2580a2
Subject: [PATCH 5/8] Recreate watch if needed
2580a2
2580a2
Do not always watch for output buffer.
2580a2
Watching for output buffer if we don't have nothing to write
2580a2
(which is the usual case) is consuming a lot of CPU.
2580a2
2580a2
This fixes https://gitlab.freedesktop.org/spice/usbredir/-/issues/24.
2580a2
2580a2
Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
2580a2
---
2580a2
 tools/usbredirect.c | 28 ++++++++++++++++++++++++++--
2580a2
 1 file changed, 26 insertions(+), 2 deletions(-)
2580a2
2580a2
diff --git a/tools/usbredirect.c b/tools/usbredirect.c
2580a2
index 6a8b68b..b6a30ad 100644
2580a2
--- a/tools/usbredirect.c
2580a2
+++ b/tools/usbredirect.c
2580a2
@@ -29,6 +29,7 @@ typedef struct redirect {
2580a2
     } device;
2580a2
     bool is_client;
2580a2
     bool keepalive;
2580a2
+    bool watch_inout;
2580a2
     char *addr;
2580a2
     int port;
2580a2
     int verbosity;
2580a2
@@ -42,6 +43,8 @@ typedef struct redirect {
2580a2
     GMainLoop *main_loop;
2580a2
 } redirect;
2580a2
 
2580a2
+static void create_watch(redirect *self);
2580a2
+
2580a2
 static bool
2580a2
 parse_opt_device(const char *device, int *vendor, int *product)
2580a2
 {
2580a2
@@ -162,6 +165,7 @@ parse_opts(int *argc, char ***argv)
2580a2
     }
2580a2
 
2580a2
     self = g_new0(redirect, 1);
2580a2
+    self->watch_inout = true;
2580a2
     if (!parse_opt_device(device, &self->device.vendor, &self->device.product)) {
2580a2
         g_printerr("Failed to parse device: '%s' - expected: vendor:product or busnum-devnum\n", device);
2580a2
         g_clear_pointer(&self, g_free);
2580a2
@@ -276,6 +280,20 @@ usbredir_log_cb(void *priv, int level, const char *msg)
2580a2
     g_log_structured(G_LOG_DOMAIN, glog_level, "MESSAGE", msg);
2580a2
 }
2580a2
 
2580a2
+static void
2580a2
+update_watch(redirect *self)
2580a2
+{
2580a2
+    const bool watch_inout = usbredirhost_has_data_to_write(self->usbredirhost) != 0;
2580a2
+    if (watch_inout == self->watch_inout) {
2580a2
+        return;
2580a2
+    }
2580a2
+    g_source_remove(self->watch_server_id);
2580a2
+    self->watch_server_id = 0;
2580a2
+    self->watch_inout = watch_inout;
2580a2
+
2580a2
+    create_watch(self);
2580a2
+}
2580a2
+
2580a2
 static int
2580a2
 usbredir_read_cb(void *priv, uint8_t *data, int count)
2580a2
 {
2580a2
@@ -321,6 +339,7 @@ usbredir_write_cb(void *priv, uint8_t *data, int count)
2580a2
         if (g_error_matches(err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
2580a2
             /* Try again later */
2580a2
             nbytes = 0;
2580a2
+            update_watch(self);
2580a2
         } else {
2580a2
             if (err != NULL) {
2580a2
                 g_warning("Failure at %s: %s", __func__, err->message);
2580a2
@@ -400,13 +419,18 @@ connection_handle_io_cb(GIOChannel *source, GIOCondition condition, gpointer use
2580a2
             goto end;
2580a2
         }
2580a2
     }
2580a2
-    if (condition & G_IO_OUT) {
2580a2
+    // try to write data in any case, to avoid having another iteration and
2580a2
+    // creation of another watch if there is space in output buffer
2580a2
+    if (usbredirhost_has_data_to_write(self->usbredirhost) != 0) {
2580a2
         int ret = usbredirhost_write_guest_data(self->usbredirhost);
2580a2
         if (ret < 0) {
2580a2
             g_critical("%s: Failed to write to guest", __func__);
2580a2
             goto end;
2580a2
         }
2580a2
     }
2580a2
+
2580a2
+    // update the watch if needed
2580a2
+    update_watch(self);
2580a2
     return G_SOURCE_CONTINUE;
2580a2
 
2580a2
 end:
2580a2
@@ -427,7 +451,7 @@ create_watch(redirect *self)
2580a2
 #endif
2580a2
 
2580a2
     self->watch_server_id = g_io_add_watch(io_channel,
2580a2
-            G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR,
2580a2
+            G_IO_IN | G_IO_HUP | G_IO_ERR | (self->watch_inout ? G_IO_OUT : 0),
2580a2
             connection_handle_io_cb,
2580a2
             self);
2580a2
 }
2580a2
-- 
2580a2
2.39.0
2580a2